mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-06 14:00:09 +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>