diff --git a/app/(app)/[appName]/[objectName]/index.tsx b/app/(app)/[appName]/[objectName]/index.tsx index 087d78f..c040c79 100644 --- a/app/(app)/[appName]/[objectName]/index.tsx +++ b/app/(app)/[appName]/[objectName]/index.tsx @@ -12,6 +12,7 @@ import { ScreenHeader } from "~/components/common/ScreenHeader"; import { useToast } from "~/components/ui/Toast"; import { useConfirm } from "~/components/ui/ConfirmDialog"; import { useObjectMeta } from "~/hooks/useObjectMeta"; +import { useThemeColors } from "~/lib/theme-colors"; export default function ObjectListScreen() { const { appName, objectName } = useLocalSearchParams<{ @@ -21,6 +22,7 @@ export default function ObjectListScreen() { const client = useClient(); const router = useRouter(); const { t } = useTranslation(); + const { accent } = useThemeColors(); const { toastError } = useToast(); const confirm = useConfirm(); @@ -100,7 +102,7 @@ export default function ObjectListScreen() { accessibilityLabel={t("records.createNamed", { name: displayName })} className="h-10 w-10 items-center justify-center rounded-full active:bg-muted" > - + } /> diff --git a/app/(app)/[appName]/index.tsx b/app/(app)/[appName]/index.tsx index 927f1d1..399bce3 100644 --- a/app/(app)/[appName]/index.tsx +++ b/app/(app)/[appName]/index.tsx @@ -8,6 +8,7 @@ import { ListSkeleton } from "~/components/ui/ListSkeleton"; import { ScreenHeader } from "~/components/common/ScreenHeader"; import { useApp, type NavigationItem } from "~/hooks/useApps"; import { getIcon } from "~/lib/getIcon"; +import { useThemeColors } from "~/lib/theme-colors"; /** * App home — renders the app's curated navigation tree (the same @@ -19,6 +20,7 @@ import { getIcon } from "~/lib/getIcon"; export default function AppHomeScreen() { const { appName } = useLocalSearchParams<{ appName: string }>(); const router = useRouter(); + const { accent } = useThemeColors(); const { app, isLoading, error } = useApp(appName); const displayName = @@ -71,7 +73,7 @@ export default function AppHomeScreen() { accessibilityLabel={item.label} > - + {item.label} diff --git a/app/(app)/packages.tsx b/app/(app)/packages.tsx index f96f2c1..fd92933 100644 --- a/app/(app)/packages.tsx +++ b/app/(app)/packages.tsx @@ -14,6 +14,7 @@ import { ScreenHeader } from "~/components/common/ScreenHeader"; import { EmptyState } from "~/components/ui/EmptyState"; import { ListSkeleton } from "~/components/ui/ListSkeleton"; import { useConfirm } from "~/components/ui/ConfirmDialog"; +import { useThemeColors } from "~/lib/theme-colors"; /** * Package management screen – list, enable, disable, uninstall packages. @@ -22,6 +23,7 @@ import { useConfirm } from "~/components/ui/ConfirmDialog"; */ export default function PackagesScreen() { const { t } = useTranslation(); + const { accent } = useThemeColors(); const { packages, isLoading, error, refetch, enable, disable, uninstall } = usePackageManagement(); const confirm = useConfirm(); @@ -87,7 +89,7 @@ export default function PackagesScreen() { - + {pkg.label} diff --git a/app/(tabs)/apps.tsx b/app/(tabs)/apps.tsx index bedb71a..2fbfcbd 100644 --- a/app/(tabs)/apps.tsx +++ b/app/(tabs)/apps.tsx @@ -12,11 +12,13 @@ import { useApps } from "~/hooks/useApps"; import { getIcon } from "~/lib/getIcon"; import { getUserErrorMessage } from "~/lib/error-handling"; import { tCount } from "~/lib/i18n"; +import { useThemeColors } from "~/lib/theme-colors"; export default function AppsScreen() { const { apps, isLoading, error, refetch } = useApps(); const router = useRouter(); const { t } = useTranslation(); + const { accent } = useThemeColors(); const [isRefreshing, setIsRefreshing] = useState(false); const handleAppPress = (appName: string) => { @@ -85,7 +87,7 @@ export default function AppsScreen() { accessibilityLabel={t("apps.openA11y", { name: app.label })} > - + diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 0ed59e5..029d088 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -129,7 +129,7 @@ export default function HomeScreen() { contentContainerStyle={webContentMaxWidth} showsVerticalScrollIndicator={false} refreshControl={ - + } > @@ -159,7 +159,7 @@ export default function HomeScreen() { accessibilityLabel={t("home.assistantTitle")} > - + @@ -263,7 +263,7 @@ export default function HomeScreen() { accessibilityLabel={`Open ${d.label} dashboard`} > - + diff --git a/app/(tabs)/search.tsx b/app/(tabs)/search.tsx index 6745537..af0d06e 100644 --- a/app/(tabs)/search.tsx +++ b/app/(tabs)/search.tsx @@ -10,10 +10,12 @@ import { Input } from "~/components/ui/Input"; import { EmptyState } from "~/components/ui/EmptyState"; import { useGlobalSearch } from "~/hooks/useGlobalSearch"; import { useSearchHistoryStore } from "~/stores/search-history-store"; +import { useThemeColors } from "~/lib/theme-colors"; export default function SearchScreen() { const router = useRouter(); const { t } = useTranslation(); + const { accent } = useThemeColors(); const { query, setQuery, groups, isSearching, hasSearched, totalCount, objectCount } = useGlobalSearch(); const recentQueries = useSearchHistoryStore((s) => s.queries); @@ -162,7 +164,7 @@ export default function SearchScreen() { accessibilityLabel={t("search.openLabel", { title: rec.title })} > - + diff --git a/components/batch/BatchActionBar.tsx b/components/batch/BatchActionBar.tsx index ecc1174..a536dae 100644 --- a/components/batch/BatchActionBar.tsx +++ b/components/batch/BatchActionBar.tsx @@ -2,6 +2,7 @@ import React from "react"; import { View, Text, Pressable } from "react-native"; import { Trash2, Edit3, X } from "lucide-react-native"; import { cn } from "~/lib/utils"; +import { useThemeColors } from "~/lib/theme-colors"; export interface BatchActionBarProps { /** Number of selected records */ @@ -25,6 +26,7 @@ export function BatchActionBar({ onClearSelection, className, }: BatchActionBarProps) { + const { accent } = useThemeColors(); if (selectedCount === 0) return null; return ( @@ -49,7 +51,7 @@ export function BatchActionBar({ onPress={onBatchEdit} className="flex-row items-center rounded-lg bg-primary/10 px-3 py-2" > - + Edit )} diff --git a/components/common/LanguageSelector.tsx b/components/common/LanguageSelector.tsx index 53bdf12..67a53cf 100644 --- a/components/common/LanguageSelector.tsx +++ b/components/common/LanguageSelector.tsx @@ -5,6 +5,7 @@ import { Check } from "lucide-react-native"; import * as Haptics from "expo-haptics"; import { SUPPORTED_LANGUAGES } from "~/lib/i18n"; import { useUIStore } from "~/stores/ui-store"; +import { useThemeColors } from "~/lib/theme-colors"; import { cn } from "~/lib/utils"; /** @@ -13,6 +14,7 @@ import { cn } from "~/lib/utils"; */ export function LanguageSelector({ className }: { className?: string }) { const { t } = useTranslation(); + const { accent } = useThemeColors(); const language = useUIStore((s) => s.language); const setLanguage = useUIStore((s) => s.setLanguage); @@ -48,7 +50,7 @@ export function LanguageSelector({ className }: { className?: string }) { > {lang.label} - {isActive && } + {isActive && } ); })} diff --git a/components/common/OfflineIndicator.tsx b/components/common/OfflineIndicator.tsx index b5324c5..eebe084 100644 --- a/components/common/OfflineIndicator.tsx +++ b/components/common/OfflineIndicator.tsx @@ -2,6 +2,7 @@ import React from "react"; import { View, Text, Pressable } from "react-native"; import { WifiOff, RefreshCw } from "lucide-react-native"; import { cn } from "~/lib/utils"; +import { useThemeColors } from "~/lib/theme-colors"; export interface OfflineIndicatorProps { isOffline: boolean; @@ -22,6 +23,7 @@ export function OfflineIndicator({ onSyncPress, className, }: OfflineIndicatorProps) { + const { accent } = useThemeColors(); if (!isOffline && pendingCount === 0) return null; return ( @@ -52,7 +54,7 @@ export function OfflineIndicator({ disabled={isSyncing} className="flex-row items-center rounded-lg bg-primary/10 px-2.5 py-1" > - + {isSyncing ? "Syncing…" : "Sync"} diff --git a/components/common/ScreenHeader.tsx b/components/common/ScreenHeader.tsx index 4029d92..9271b55 100644 --- a/components/common/ScreenHeader.tsx +++ b/components/common/ScreenHeader.tsx @@ -3,6 +3,7 @@ import { View, Text, Pressable } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { ChevronLeft } from "lucide-react-native"; import { useRouter } from "expo-router"; +import { useThemeColors } from "~/lib/theme-colors"; export interface ScreenHeaderProps { /** Primary title shown in the bar. */ @@ -44,6 +45,7 @@ export function ScreenHeader({ }: ScreenHeaderProps) { const router = useRouter(); const insets = useSafeAreaInsets(); + const { accent } = useThemeColors(); const handleBack = () => { if (onBack) { @@ -74,7 +76,7 @@ export function ScreenHeader({ accessibilityLabel="Go back" className="h-11 w-11 items-center justify-center rounded-full active:bg-muted" > - + )} diff --git a/components/common/ThemeSelector.tsx b/components/common/ThemeSelector.tsx index 8ec9a51..307a064 100644 --- a/components/common/ThemeSelector.tsx +++ b/components/common/ThemeSelector.tsx @@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next"; import { Check, Sun, Moon, SmartphoneNfc } from "lucide-react-native"; import * as Haptics from "expo-haptics"; import { useUIStore, type ThemeMode } from "~/stores/ui-store"; +import { useThemeColors } from "~/lib/theme-colors"; import { cn } from "~/lib/utils"; const OPTIONS: { mode: ThemeMode; icon: typeof Sun; labelKey: string }[] = [ @@ -19,6 +20,7 @@ const OPTIONS: { mode: ThemeMode; icon: typeof Sun; labelKey: string }[] = [ */ export function ThemeSelector({ className }: { className?: string }) { const { t } = useTranslation(); + const { accent } = useThemeColors(); const theme = useUIStore((s) => s.theme); const setTheme = useUIStore((s) => s.setTheme); @@ -47,7 +49,7 @@ export function ThemeSelector({ className }: { className?: string }) { }} > - + - {isActive && } + {isActive && } ); })} diff --git a/components/query/GlobalSearch.tsx b/components/query/GlobalSearch.tsx index 094a5bc..0492d6c 100644 --- a/components/query/GlobalSearch.tsx +++ b/components/query/GlobalSearch.tsx @@ -2,6 +2,7 @@ import React from "react"; import { View, TextInput } from "react-native"; import { Search } from "lucide-react-native"; import { cn } from "~/lib/utils"; +import { useThemeColors } from "~/lib/theme-colors"; export interface GlobalSearchProps { value: string; @@ -20,6 +21,7 @@ export function GlobalSearch({ placeholder = "Search across all fields…", className, }: GlobalSearchProps) { + const { accent } = useThemeColors(); return ( - + { const firstField = fields[0]?.name ?? ""; onAddFilter(firstField, "eq"); @@ -56,7 +58,7 @@ export function QueryBuilder({ onPress={onToggleLogic} className="flex-row items-center rounded-lg border border-primary/30 bg-primary/10 px-3 py-1.5" > - + Match {root.logic === "AND" ? "ALL" : "ANY"} diff --git a/components/renderers/CalendarViewRenderer.tsx b/components/renderers/CalendarViewRenderer.tsx index 26e52de..371d1d4 100644 --- a/components/renderers/CalendarViewRenderer.tsx +++ b/components/renderers/CalendarViewRenderer.tsx @@ -6,6 +6,7 @@ import { Pressable, } from "react-native"; import { ChevronLeft, ChevronRight } from "lucide-react-native"; +import { useThemeColors } from "~/lib/theme-colors"; import { Skeleton } from "~/components/ui/Skeleton"; import { cn } from "~/lib/utils"; @@ -112,6 +113,7 @@ export function CalendarViewRenderer({ initialYear, initialMonth, }: CalendarViewRendererProps) { + const { accent } = useThemeColors(); const now = new Date(); const [year, setYear] = useState(initialYear ?? now.getFullYear()); const [month, setMonth] = useState(initialMonth ?? now.getMonth()); @@ -183,13 +185,13 @@ export function CalendarViewRenderer({ {/* Month navigation */} - + {MONTH_NAMES[month]} {year} - + diff --git a/components/renderers/ChartViewRenderer.tsx b/components/renderers/ChartViewRenderer.tsx index e0bddd5..67c6319 100644 --- a/components/renderers/ChartViewRenderer.tsx +++ b/components/renderers/ChartViewRenderer.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from "react"; import { View, Text, ScrollView } from "react-native"; import { BarChart3, TrendingUp, PieChart, Activity, AlertCircle } from "lucide-react-native"; +import { useThemeColors } from "~/lib/theme-colors"; import { Card, CardHeader, CardTitle, CardContent } from "~/components/ui/Card"; import { Skeleton } from "~/components/ui/Skeleton"; import { EmptyState } from "~/components/ui/EmptyState"; @@ -32,15 +33,16 @@ export interface ChartViewRendererProps { /* ------------------------------------------------------------------ */ function ChartIcon({ type }: { type: ChartType }) { + const { accent } = useThemeColors(); switch (type) { case "line": - return ; + return ; case "pie": - return ; + return ; case "funnel": - return ; + return ; default: - return ; + return ; } } diff --git a/components/renderers/DashboardViewRenderer.tsx b/components/renderers/DashboardViewRenderer.tsx index 3da59a9..0da4dd3 100644 --- a/components/renderers/DashboardViewRenderer.tsx +++ b/components/renderers/DashboardViewRenderer.tsx @@ -12,6 +12,7 @@ import { Card, CardHeader, CardTitle, CardContent } from "~/components/ui/Card"; import { Skeleton } from "~/components/ui/Skeleton"; import { WidgetChart } from "./charts/WidgetChart"; import { formatByPattern, formatCurrency, formatNumber } from "~/lib/formatting"; +import { useThemeColors } from "~/lib/theme-colors"; import type { DashboardMeta, DashboardWidgetMeta } from "./types"; /** Skeleton grid shown while dashboard metadata + widget data load. */ @@ -90,6 +91,7 @@ function MetricWidget({ widget: DashboardWidgetMeta; data?: WidgetDataPayload; }) { + const { accent } = useThemeColors(); const value = data?.value ?? "—"; const trend = data?.trend; const isPositive = trend?.startsWith("+"); @@ -107,7 +109,7 @@ function MetricWidget({ {widget.title ?? widget.name} - + {data?.isLoading ? ( @@ -183,6 +185,7 @@ function ListWidget({ widget: DashboardWidgetMeta; data?: WidgetDataPayload; }) { + const { accent } = useThemeColors(); const records = data?.records ?? []; return ( @@ -192,7 +195,7 @@ function ListWidget({ {widget.title ?? widget.name} - + @@ -240,6 +243,7 @@ function ChartWidget({ widget: DashboardWidgetMeta; data?: WidgetDataPayload; }) { + const { accent } = useThemeColors(); const chartType = String(widget.chartConfig?.type ?? widget.type ?? "bar"); const colors = Array.isArray(widget.chartConfig?.colors) ? (widget.chartConfig?.colors as string[]) @@ -254,7 +258,7 @@ function ChartWidget({ {widget.title ?? widget.name} - + diff --git a/components/renderers/FilterDrawer.tsx b/components/renderers/FilterDrawer.tsx index e6ac299..172f620 100644 --- a/components/renderers/FilterDrawer.tsx +++ b/components/renderers/FilterDrawer.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from "react"; import { View, Text, Pressable, Modal } from "react-native"; import { Filter, X } from "lucide-react-native"; import { cn } from "~/lib/utils"; +import { useThemeColors } from "~/lib/theme-colors"; import { QueryBuilder } from "~/components/query"; import { useQueryBuilder } from "~/hooks/useQueryBuilder"; import type { FieldDefinition } from "~/components/renderers/types"; @@ -46,6 +47,8 @@ export function FilterDrawer({ hasFilters: _hasFilters, } = useQueryBuilder(); + const { accent } = useThemeColors(); + /* ---- Active filter count ---- */ const filterCount = root.filters.length; @@ -73,7 +76,7 @@ export function FilterDrawer({ {/* ---- Header ---- */} - + Filters diff --git a/components/renderers/MapViewRenderer.tsx b/components/renderers/MapViewRenderer.tsx index 7649560..d41f3cc 100644 --- a/components/renderers/MapViewRenderer.tsx +++ b/components/renderers/MapViewRenderer.tsx @@ -1,6 +1,7 @@ import React from "react"; import { View, Text, ScrollView, Pressable } from "react-native"; import { MapPin, Navigation } from "lucide-react-native"; +import { useThemeColors } from "~/lib/theme-colors"; import { Card, CardContent } from "~/components/ui/Card"; import { ListSkeleton } from "~/components/ui/ListSkeleton"; @@ -95,6 +96,7 @@ export function MapViewRenderer({ isLoading = false, onMarkerPress, }: MapViewRendererProps) { + const { accent } = useThemeColors(); if (isLoading) { return ( @@ -122,7 +124,7 @@ export function MapViewRenderer({ > {/* Summary header */} - + {markers.length} location{markers.length !== 1 ? "s" : ""} @@ -137,7 +139,7 @@ export function MapViewRenderer({ - + diff --git a/components/renderers/ReportRenderer.tsx b/components/renderers/ReportRenderer.tsx index e02a353..df529b6 100644 --- a/components/renderers/ReportRenderer.tsx +++ b/components/renderers/ReportRenderer.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from "react"; import { View, Text, ScrollView } from "react-native"; import { FileText, AlertCircle } from "lucide-react-native"; +import { useThemeColors } from "~/lib/theme-colors"; import { Card, CardHeader, CardTitle, CardContent } from "~/components/ui/Card"; import { Skeleton } from "~/components/ui/Skeleton"; import { EmptyState } from "~/components/ui/EmptyState"; @@ -307,6 +308,7 @@ export function ReportRenderer({ isLoading, error, }: ReportRendererProps) { + const { accent } = useThemeColors(); if (isLoading) { return ( @@ -357,7 +359,7 @@ export function ReportRenderer({ - + {title ?? "Report"} diff --git a/components/renderers/ViewRenderer.tsx b/components/renderers/ViewRenderer.tsx index c5bab84..96076e6 100644 --- a/components/renderers/ViewRenderer.tsx +++ b/components/renderers/ViewRenderer.tsx @@ -1,5 +1,6 @@ import React, { Suspense } from "react"; import { View, Text, ActivityIndicator } from "react-native"; +import { useThemeColors } from "~/lib/theme-colors"; import { ListViewRenderer, type ListViewRendererProps } from "./ListViewRenderer"; import { FormViewRenderer, type FormViewRendererProps } from "./FormViewRenderer"; import { DetailViewRenderer, type DetailViewRendererProps } from "./DetailViewRenderer"; @@ -55,9 +56,10 @@ const LazyGantt = React.lazy(() => /* ------------------------------------------------------------------ */ function RendererFallback() { + const { accent } = useThemeColors(); return ( - + ); } diff --git a/components/renderers/fields/FileField.tsx b/components/renderers/fields/FileField.tsx index 5f8959f..39a01c4 100644 --- a/components/renderers/fields/FileField.tsx +++ b/components/renderers/fields/FileField.tsx @@ -12,6 +12,7 @@ import { import type { FieldDefinition } from "../types"; import type { FileUploadResult } from "~/hooks/useFileUpload"; import { useToast } from "~/components/ui/Toast"; +import { useThemeColors } from "~/lib/theme-colors"; /* ------------------------------------------------------------------ */ /* Types */ @@ -82,6 +83,7 @@ export function FileField({ }: FileFieldProps) { const [isUploading, setIsUploading] = useState(false); const { toastError } = useToast(); + const { accent } = useThemeColors(); const fileInfo = resolveFileInfo(value); const handleUpload = useCallback( @@ -118,12 +120,12 @@ export function FileField({ {onDownload && fileInfo.id && ( onDownload(fileInfo.id!, fileInfo.name ?? "file")}> - + )} {onShare && fileInfo.id && ( onShare(fileInfo.id!, fileInfo.name ?? "file")}> - + )} @@ -149,7 +151,7 @@ export function FileField({ {/* Upload buttons */} {isUploading ? ( - + Uploading… ) : ( diff --git a/components/sync/ConflictResolutionDialog.tsx b/components/sync/ConflictResolutionDialog.tsx index 8a68708..7738969 100644 --- a/components/sync/ConflictResolutionDialog.tsx +++ b/components/sync/ConflictResolutionDialog.tsx @@ -2,6 +2,7 @@ import React from "react"; import { View, Text, Pressable, ScrollView, Modal } from "react-native"; import { AlertTriangle, RefreshCw, Trash2, X } from "lucide-react-native"; import type { SyncQueueEntry } from "~/lib/sync-queue"; +import { useThemeColors } from "~/lib/theme-colors"; /* ------------------------------------------------------------------ */ /* Props */ @@ -32,6 +33,7 @@ export function ConflictResolutionDialog({ onKeepServer, onClose, }: ConflictResolutionDialogProps) { + const { accent } = useThemeColors(); return ( @@ -76,7 +78,7 @@ export function ConflictResolutionDialog({ onPress={() => onKeepLocal(entry.id)} className="flex-1 flex-row items-center justify-center rounded-lg bg-primary/10 py-2" > - + Keep Local diff --git a/components/ui/MarkdownText.tsx b/components/ui/MarkdownText.tsx index d73cea1..5d4eb1b 100644 --- a/components/ui/MarkdownText.tsx +++ b/components/ui/MarkdownText.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from "react"; import { Linking, StyleSheet } from "react-native"; +import { useColorScheme } from "nativewind"; import Markdown from "react-native-markdown-display"; /** @@ -7,11 +8,16 @@ import Markdown from "react-native-markdown-display"; * tables) instead of plain text. LLM replies are markdown-heavy, so showing * them raw leaks `**`, `-`, and backticks into the UI. * - * Styled to match the app's light surfaces (card foreground text, primary - * links, muted code blocks). Pure-JS renderer — works on native and web. + * Theme-aware: the styles were hardcoded to light surfaces, which left the + * body text near-black (and code blocks pale) — unreadable once dark mode + * shipped. Pure-JS renderer — works on native and web. */ export function MarkdownText({ children }: { children: string }) { - const styles = useMemo(() => markdownStyles, []); + const { colorScheme } = useColorScheme(); + const styles = useMemo( + () => buildMarkdownStyles(colorScheme === "dark"), + [colorScheme], + ); return ( - + ) : ( - + )} ); diff --git a/lib/theme-colors.ts b/lib/theme-colors.ts new file mode 100644 index 0000000..481dc06 --- /dev/null +++ b/lib/theme-colors.ts @@ -0,0 +1,37 @@ +import { useColorScheme } from "nativewind"; + +/** + * Theme-aware colors for places that need a concrete hex rather than a Tailwind + * class — chiefly lucide icons (`color` prop) and a few inline styles. Mirrors + * the `global.css` tokens closely enough that icons read correctly in both + * light and dark mode, where a hardcoded `#1e40af` (too dark) or `#0f172a` + * (invisible on a dark card) would otherwise fail. + */ +export interface ThemeColors { + /** Brand/primary accent — for active icons, links, primary affordances. */ + accent: string; + /** Default foreground — for neutral icons on cards/surfaces. */ + foreground: string; + /** Muted foreground — secondary icons, chevrons, hints. */ + muted: string; +} + +const LIGHT: ThemeColors = { + accent: "#1e40af", + foreground: "#0f172a", + muted: "#94a3b8", +}; + +const DARK: ThemeColors = { + accent: "#60a5fa", + foreground: "#e2e8f0", + // Slate-400 reads acceptably on both themes; keep it stable so muted icons + // don't shift between light and dark. + muted: "#94a3b8", +}; + +/** Hook: theme-aware icon/inline colors for the current color scheme. */ +export function useThemeColors(): ThemeColors { + const { colorScheme } = useColorScheme(); + return colorScheme === "dark" ? DARK : LIGHT; +}