From 6c9936cb6a4e7d91cacb88b9aeb0229c8318d0a1 Mon Sep 17 00:00:00 2001 From: Muhammed Sanjid Date: Tue, 31 Mar 2026 00:20:56 +0530 Subject: [PATCH] feat: ui issues fixes --- apps/platform/app/(docs)/[...slug]/page.tsx | 18 +- .../components/showcase/docs-primitives.tsx | 68 +++--- apps/showcase/app/(components)/[slug].tsx | 228 ++++++++++++++++-- apps/showcase/lib/ui-interop.ts | 3 +- packages/registry/registry.json | 26 +- .../registry/src/components/ui/avatar.tsx | 40 +-- packages/registry/src/components/ui/badge.tsx | 114 ++++----- .../registry/src/components/ui/button.tsx | 114 ++++----- packages/registry/src/components/ui/card.tsx | 60 +++-- packages/registry/src/components/ui/input.tsx | 172 ++++++++++--- packages/registry/src/components/ui/label.tsx | 11 +- .../registry/src/components/ui/separator.tsx | 12 +- packages/registry/src/components/ui/text.tsx | 106 ++++---- .../registry/src/components/ui/textarea.tsx | 155 +++++++++--- packages/registry/src/lib/theme.ts | 54 +++++ packages/registry/tsconfig.json | 2 +- 16 files changed, 819 insertions(+), 364 deletions(-) create mode 100644 packages/registry/src/lib/theme.ts diff --git a/apps/platform/app/(docs)/[...slug]/page.tsx b/apps/platform/app/(docs)/[...slug]/page.tsx index a3ce1ce..4e58df0 100644 --- a/apps/platform/app/(docs)/[...slug]/page.tsx +++ b/apps/platform/app/(docs)/[...slug]/page.tsx @@ -47,6 +47,11 @@ type ResolvedDocsPageData = { dependencies?: string[]; }; +const DEFAULT_APP_STORE_HREF = + "https://apps.apple.com/app/expo-go/id982107779"; +const DEFAULT_PLAY_STORE_HREF = + "https://play.google.com/store/apps/details?id=host.exp.exponent"; + export function generateStaticParams() { return docsSource.generateParams(); } @@ -134,6 +139,9 @@ export default async function DocsPage({ } const pager = getComponentPager(componentSlug); + const qrValue = pageData.qrValue ?? `showcase://components/${componentSlug}`; + const appStoreHref = pageData.appStoreHref ?? DEFAULT_APP_STORE_HREF; + const playStoreHref = pageData.playStoreHref ?? DEFAULT_PLAY_STORE_HREF; return (
- {pageData.qrValue && - pageData.appStoreHref && - pageData.playStoreHref ? ( + {qrValue ? (
@@ -186,9 +192,9 @@ export default async function DocsPage({ diff --git a/apps/platform/components/showcase/docs-primitives.tsx b/apps/platform/components/showcase/docs-primitives.tsx index bc70cb9..164d636 100644 --- a/apps/platform/components/showcase/docs-primitives.tsx +++ b/apps/platform/components/showcase/docs-primitives.tsx @@ -57,9 +57,9 @@ export function ApiTable({ }>; }) { return ( - -
- + +
+
@@ -170,40 +170,44 @@ export function DocsPager({ next?: { href: string; title: string; description: string }; }) { return ( -
+
{previous ? ( - - -
- - Previous - - - {previous.title} - -
- + + + +
+ + Previous + + + {previous.title} + +
+ +
) : (
)} {next ? ( - -
- - Next - - - {next.title} - -
- - + + +
+ + Next + + + {next.title} + +
+ + +
) : null}
); diff --git a/apps/showcase/app/(components)/[slug].tsx b/apps/showcase/app/(components)/[slug].tsx index 0059fc0..b89012f 100644 --- a/apps/showcase/app/(components)/[slug].tsx +++ b/apps/showcase/app/(components)/[slug].tsx @@ -1,5 +1,6 @@ import { Stack, useLocalSearchParams } from "expo-router"; -import { useState } from "react"; +import MaterialIcons from "@expo/vector-icons/MaterialIcons"; +import React, { useState } from "react"; import { ScrollView, StyleSheet, View } from "react-native"; import { SpotlightButton } from "@/components/animated/spotlight-button"; @@ -17,11 +18,10 @@ import { CardFooter, CardHeader, } from "@/registry/components/ui/card"; -import { Input } from "@/registry/components/ui/input"; import { Label } from "@/registry/components/ui/label"; import { Separator } from "@/registry/components/ui/separator"; import { Text } from "@/registry/components/ui/text"; -import { Textarea } from "@/registry/components/ui/textarea"; +import { useColorScheme } from "@/hooks/use-color-scheme"; const COMPONENT_META = { avatar: { title: "Avatar" }, @@ -37,6 +37,139 @@ const COMPONENT_META = { } as const; type ComponentSlug = keyof typeof COMPONENT_META; +const DemoNativeTextInput = require("react-native").TextInput as React.ComponentType; + +function useDemoFieldPalette() { + const colorScheme = useColorScheme() ?? "light"; + + return colorScheme === "dark" + ? { + background: "#09090b", + foreground: "#fafafa", + muted: "#27272a", + mutedForeground: "#a1a1aa", + input: "#27272a", + ring: "#d4d4d8", + destructive: "#7f1d1d", + } + : { + background: "#ffffff", + foreground: "#09090b", + muted: "#f4f4f5", + mutedForeground: "#71717a", + input: "#e4e4e7", + ring: "#18181b", + destructive: "#ef4444", + }; +} + +function DemoInput({ + leftSlot, + rightSlot, + invalid = false, + variant = "default", + editable = true, + style, + containerStyle, + onFocus, + onBlur, + ...props +}: any) { + const [focused, setFocused] = useState(false); + const palette = useDemoFieldPalette(); + + return ( + + + {leftSlot ? {leftSlot} : null} + {React.createElement(DemoNativeTextInput, { + ...props, + editable, + onFocus: (event: any) => { + setFocused(true); + onFocus?.(event); + }, + onBlur: (event: any) => { + setFocused(false); + onBlur?.(event); + }, + placeholderTextColor: props.placeholderTextColor ?? palette.mutedForeground, + selectionColor: invalid ? palette.destructive : palette.ring, + style: [styles.demoInputControl, { color: palette.foreground }, style], + })} + {rightSlot ? {rightSlot} : null} + + + ); +} + +function DemoTextarea({ + invalid = false, + variant = "default", + editable = true, + style, + containerStyle, + onFocus, + onBlur, + ...props +}: any) { + const [focused, setFocused] = useState(false); + const palette = useDemoFieldPalette(); + + return ( + + + {React.createElement(DemoNativeTextInput, { + ...props, + editable, + multiline: true, + textAlignVertical: "top", + onFocus: (event: any) => { + setFocused(true); + onFocus?.(event); + }, + onBlur: (event: any) => { + setFocused(false); + onBlur?.(event); + }, + placeholderTextColor: props.placeholderTextColor ?? palette.mutedForeground, + selectionColor: invalid ? palette.destructive : palette.ring, + style: [styles.demoTextareaControl, { color: palette.foreground }, style], + })} + + + ); +} function Block({ title, @@ -336,13 +469,18 @@ function InputPreview({ }) { return ( - } + /> + } /> - - + ); } @@ -359,17 +497,36 @@ function InputExamples({ - } /> - + } + /> + + + + + + } + /> + + Invalid, disabled, and slotted states now render through the same primitive. + @@ -385,8 +542,8 @@ function TextareaPreview({ }) { return ( -
prop