feat(client): universal client nav shell — icons, collapse, theme + locale switchers, native drawer #210

Closed
opened 2026-06-21 15:55:42 +00:00 by james · 0 comments
Owner

Context

#185 deleted the Next.js UI; the Expo client is now the user-facing surface. The minimal nav shell that landed alongside #185 (a flat list of nav links + identity + logout) gets users from screen to screen but misses several features the deleted PWA sidebar had. This ticket brings the universal client's nav shell up to parity with the old UI.

Scope

Visual + interaction parity

  • Icons on every nav row (sidebar collapsed shows icon-only; expanded shows icon + label). The deleted PWA used Lucide; ship lucide-react-native or @expo/vector-icons (Lucide line icons per the CLAUDE.md voice rules). Pick one and pin it.
  • Collapse / expand sidebar with a toggle button. State persists per-user via useSettings/useUpdateSettings if there's room in the DTO; otherwise local secure storage. The nav.collapseSidebar / nav.expandSidebar i18n keys already exist for the toggle's aria label.
  • Active-route highlight — already present, but tighten styling to match the design package's spec (accent border on the left edge plus the soft fill).
  • Brand row styling — match the design package; today it's a plain text label.
  • Theme switcher — light / dark / system. Reuses useSettings + useUpdateSettings. The nav.theme + nav.toggleTheme keys already exist.
  • Locale switcher — exposes SUPPORTED_LOCALES. The nav.locale key already exists.
  • Identity row keeps email + logout (already present).

Native (Android, Flatpak)

  • Real drawer, not the stacked layout the placeholder ships today. Bring in @react-navigation/drawer (Expo Router supports it as a drop-in replacement for Slot). On web the drawer collapses to the sidebar above; on native it slides from the left.
  • Mobile-width breakpoint on web — under ~720px the sidebar collapses to a hamburger that opens the same drawer.

Acceptance criteria

  • Sidebar shows icon + label on web (expanded) and icon-only (collapsed).
  • Toggle button persists collapse state across reloads.
  • Theme + locale switchers in the footer drive the same hooks the Account screen uses; switching from either site reflects everywhere.
  • Active route gets the accent treatment.
  • Native build (pnpm -F @carol/client web and build:android) shows a drawer, not a stacked layout.
  • Web below 720px shows a hamburger that opens the same drawer.
  • All strings via react-i18next; no hardcoded copy.

Out of scope

  • A bottom-tab navigator on native — drawer covers the requirement for now.
  • Bringing back the design system playground (/dev/components) — that lives with the API and was deleted in #185.
  • Adding new sidebar entries for surfaces that aren't ported yet.

Composes with

  • #176 epic (universal client).
  • The settings DTO may need a sidebarCollapsed field; either land that with this ticket or use secure storage if the DTO change is heavy.

Part of

#176

## Context #185 deleted the Next.js UI; the Expo client is now the user-facing surface. The minimal nav shell that landed alongside #185 (a flat list of nav links + identity + logout) gets users from screen to screen but misses several features the deleted PWA sidebar had. This ticket brings the universal client's nav shell up to parity with the old UI. ## Scope ### Visual + interaction parity - **Icons** on every nav row (sidebar collapsed shows icon-only; expanded shows icon + label). The deleted PWA used Lucide; ship `lucide-react-native` or `@expo/vector-icons` (Lucide line icons per the CLAUDE.md voice rules). Pick one and pin it. - **Collapse / expand sidebar** with a toggle button. State persists per-user via `useSettings`/`useUpdateSettings` if there's room in the DTO; otherwise local secure storage. The `nav.collapseSidebar` / `nav.expandSidebar` i18n keys already exist for the toggle's aria label. - **Active-route highlight** — already present, but tighten styling to match the design package's spec (accent border on the left edge plus the soft fill). - **Brand row** styling — match the design package; today it's a plain text label. ### Quick-action controls in the sidebar footer - **Theme switcher** — light / dark / system. Reuses `useSettings` + `useUpdateSettings`. The `nav.theme` + `nav.toggleTheme` keys already exist. - **Locale switcher** — exposes `SUPPORTED_LOCALES`. The `nav.locale` key already exists. - **Identity row** keeps email + logout (already present). ### Native (Android, Flatpak) - **Real drawer**, not the stacked layout the placeholder ships today. Bring in `@react-navigation/drawer` (Expo Router supports it as a drop-in replacement for `Slot`). On web the drawer collapses to the sidebar above; on native it slides from the left. - **Mobile-width breakpoint on web** — under ~720px the sidebar collapses to a hamburger that opens the same drawer. ## Acceptance criteria - [ ] Sidebar shows icon + label on web (expanded) and icon-only (collapsed). - [ ] Toggle button persists collapse state across reloads. - [ ] Theme + locale switchers in the footer drive the same hooks the Account screen uses; switching from either site reflects everywhere. - [ ] Active route gets the accent treatment. - [ ] Native build (`pnpm -F @carol/client web` and `build:android`) shows a drawer, not a stacked layout. - [ ] Web below 720px shows a hamburger that opens the same drawer. - [ ] All strings via `react-i18next`; no hardcoded copy. ## Out of scope - A bottom-tab navigator on native — drawer covers the requirement for now. - Bringing back the design system playground (`/dev/components`) — that lives with the API and was deleted in #185. - Adding new sidebar entries for surfaces that aren't ported yet. ## Composes with - #176 epic (universal client). - The settings DTO may need a `sidebarCollapsed` field; either land that with this ticket or use secure storage if the DTO change is heavy. ## Part of #176
james closed this issue 2026-06-23 11:52:55 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#210
No description provided.