mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 22:59:04 +02:00
First wave of the RNR migration documented in apps/mobile/docs/ rnr-migration.md. The hand-written components/ui/ shell was producing a steady stream of dark-mode and sheet-handling bugs; this commit establishes the foundation that lets every subsequent screen pick up RNR-shipped components and a real theme system instead. Foundation (Phase 1): - global.css + tailwind.config.js switch to shadcn neutral CSS variables (light + dark) under :root and .dark:root, with Multica custom tokens appended. tailwind utilities resolve to hsl(var(--...)). - New lib/theme.ts mirrors the variables in TypeScript and exports NAV_THEME for React Navigation chrome. - New lib/use-color-scheme.ts wraps NativeWind's useColorScheme with expo-secure-store persistence (preference key: theme-preference, values: light/dark/system). - components.json registers shadcn CLI paths so `npx @rnr/cli add` writes to the expected aliases. metro.config.js gains inlineRem: 16. - app/_layout.tsx wraps the tree in ThemeProvider(NAV_THEME[scheme]) and mounts <PortalHost /> for RNR dialogs. - Settings → Appearance picker (three rows: Light / Dark / System, persisted) — the only product addition in this commit. Component canary (Phase 2): - button.tsx + text.tsx replaced by RNR's defaults via the CLI (uses TextClassContext to flow text variants from Button into nested Text). - 11 button call sites updated to wrap children in <Text> (the RNR convention). The old `brand` variant had zero call sites and was dropped without follow-up. Bottom navigation: - (tabs)/_layout.tsx tried NativeTabs first but rolled back to JS Tabs: NativeTabs hard-codes canPreventDefault: false on tabPress events, so the "More tap opens a sheet without navigating" pattern was unreachable. The rolled-back layout uses useColorScheme + THEME to derive active/inactive tint, fixing the dark-mode "dim selected tab" bug. - More tab intercepts tabPress and pushes /[workspace]/menu — a stack route registered with presentation: "formSheet" + sheetAllowedDetents: "fitToContents" so iOS sizes the sheet to the menu's intrinsic height (UIKit handles drag handle, swipe dismiss, blur backdrop). - The formSheet route is named `menu.tsx` rather than `more.tsx` to avoid the URL collision with (tabs)/more.tsx — both files would otherwise resolve to /[workspace]/more because (tabs) is a transparent route group. - components/nav/global-nav-menu.tsx refactored from a self-managed Modal into a plain ScrollView (no flex-1, so fitToContents can measure). Closes via router.dismiss() instead of an onClose prop. Docs / rules: - apps/mobile/CLAUDE.md adds two hard rules: "defaults first" and "iOS native > RNR > discuss" (the three-tier waterfall). - apps/mobile/docs/rnr-migration.md captures the alternatives evaluated, the three-tier component classification, the phased rollout, and the pitfalls hit during this commit. Out of scope for this wave (planned but not started): - Tier A remaining primitives (input / card / text-field / textarea) - Tier B sheets (the 18 hand-rolled Modal sheets — to be replaced one PR at a time with ActionSheetIOS / native pickers / RNR Dialog) - Tier C domain UI internal-token upgrades Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
93 lines
2.7 KiB
CSS
93 lines
2.7 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
/*
|
|
* Theme tokens — RNR template (verbatim) + Multica custom tokens appended.
|
|
*
|
|
* When changing any variable here, also update apps/mobile/lib/theme.ts —
|
|
* they mirror each other. See apps/mobile/docs/rnr-migration.md §5.
|
|
*
|
|
* Dark-mode values for the Multica custom tokens currently mirror their
|
|
* light values — they will be tuned when a screen using them actually
|
|
* needs dark-mode treatment. Don't pre-author (per §3.1 "defaults first").
|
|
*/
|
|
|
|
@layer base {
|
|
:root {
|
|
--background: 0 0% 100%;
|
|
--foreground: 0 0% 3.9%;
|
|
--card: 0 0% 100%;
|
|
--card-foreground: 0 0% 3.9%;
|
|
--popover: 0 0% 100%;
|
|
--popover-foreground: 0 0% 3.9%;
|
|
--primary: 0 0% 9%;
|
|
--primary-foreground: 0 0% 98%;
|
|
--secondary: 0 0% 96.1%;
|
|
--secondary-foreground: 0 0% 9%;
|
|
--muted: 0 0% 96.1%;
|
|
--muted-foreground: 0 0% 45.1%;
|
|
--accent: 0 0% 96.1%;
|
|
--accent-foreground: 0 0% 9%;
|
|
--destructive: 0 84.2% 60.2%;
|
|
--destructive-foreground: 0 0% 98%;
|
|
--border: 0 0% 89.8%;
|
|
--input: 0 0% 89.8%;
|
|
--ring: 0 0% 63%;
|
|
--radius: 0.625rem;
|
|
--chart-1: 12 76% 61%;
|
|
--chart-2: 173 58% 39%;
|
|
--chart-3: 197 37% 24%;
|
|
--chart-4: 43 74% 66%;
|
|
--chart-5: 27 87% 67%;
|
|
|
|
/* Multica custom tokens */
|
|
--brand: 225 71% 58%;
|
|
--brand-foreground: 0 0% 98%;
|
|
--success: 142 71% 45%;
|
|
--warning: 48 89% 47%;
|
|
--info: 217 91% 60%;
|
|
--priority: 25 95% 53%;
|
|
--code-surface: 240 4% 92%;
|
|
}
|
|
|
|
.dark:root {
|
|
--background: 0 0% 3.9%;
|
|
--foreground: 0 0% 98%;
|
|
--card: 0 0% 3.9%;
|
|
--card-foreground: 0 0% 98%;
|
|
--popover: 0 0% 3.9%;
|
|
--popover-foreground: 0 0% 98%;
|
|
--primary: 0 0% 98%;
|
|
--primary-foreground: 0 0% 9%;
|
|
--secondary: 0 0% 14.9%;
|
|
--secondary-foreground: 0 0% 98%;
|
|
--muted: 0 0% 14.9%;
|
|
--muted-foreground: 0 0% 63.9%;
|
|
--accent: 0 0% 14.9%;
|
|
--accent-foreground: 0 0% 98%;
|
|
--destructive: 0 70.9% 59.4%;
|
|
--destructive-foreground: 0 0% 98%;
|
|
--border: 0 0% 14.9%;
|
|
--input: 0 0% 14.9%;
|
|
--ring: 300 0% 45%;
|
|
--chart-1: 220 70% 50%;
|
|
--chart-2: 160 60% 45%;
|
|
--chart-3: 30 80% 55%;
|
|
--chart-4: 280 65% 60%;
|
|
--chart-5: 340 75% 55%;
|
|
|
|
/* Multica custom tokens — dark mirrors light until a screen demands tuning */
|
|
--brand: 225 71% 58%;
|
|
--brand-foreground: 0 0% 98%;
|
|
--success: 142 71% 45%;
|
|
--warning: 48 89% 47%;
|
|
--info: 217 91% 60%;
|
|
--priority: 25 95% 53%;
|
|
/* code-surface is the ONE exception that needs a real dark value —
|
|
* the light value (240 4% 92%) is near-white and would render code
|
|
* blocks with a brighter background than the page in dark mode. */
|
|
--code-surface: 240 4% 18%;
|
|
}
|
|
}
|