# Nexus Phase 15 — Mobile Parity > Use `superpowers:test-driven-development`. Commit atomically. **Goal:** Bring the new frame to mobile breakpoint `< 768px`. Replace the legacy `MobileBottomNav` with a 4-destination bottom tab bar matching the desktop IconRail destinations (Assistant, Studio, Projects, Settings). Collapse the desktop slide-overs (History, Memory) to full-screen sheets on mobile. Make the project tab strip scroll horizontally without shrinking. Adapt the promote-to-project transition to a full-screen takeover on mobile instead of the split layout. **Source of truth:** spec §9 (Mobile). **Branch:** `nexus/design-system-migration`. --- ## Ownership boundaries **You may create or modify ONLY:** | Path | Action | |---|---| | `ui/src/components/frame/MobileTabBar.tsx` | Create | | `ui/src/components/frame/MobileTabBar.test.tsx` | Create | | `ui/src/components/Layout.tsx` | Modify — swap `MobileBottomNav` for `MobileTabBar` | | `ui/src/components/assistant/HistorySheet.tsx` | Modify — add mobile full-screen variant | | `ui/src/components/assistant/MemorySheet.tsx` | Modify — add mobile full-screen variant | | `ui/src/components/assistant/PromoteTransition.tsx` | Modify — mobile full-screen takeover variant | | `ui/src/components/projects/BuilderTabStrip.tsx` | Modify — horizontal scroll on mobile | | `ui/src/components/frame/TopStrip.tsx` | Modify if needed — mobile tweaks to cluster spacing | **You MUST NOT touch:** - Phase 8 icon rail semantics (desktop behavior stays) - Phase 9 Assistant thread layout (desktop stays) - Phase 10 Studio grid (mobile already collapses to 1-col) - Phase 11 Project card layout (desktop stays) - `ui/src/App.tsx` --- ## Scope ### 1. MobileTabBar component Replacement for `MobileBottomNav`. Renders 4 tab links at the bottom of the viewport: - Assistant (MessageCircle) - Studio (Sparkles) - Projects (FolderKanban) - Settings (Settings) Specs: - `fixed bottom-0 left-0 right-0 h-14` (56px tall) - `border-t border-border bg-background` — charcoal top border, pure black fill - Each tab is a flex column: icon on top (20×20), label below (10px uppercase 1.4px tracking) - Silver default, volt active with a 2px volt bar above the icon - Focus-visible styles per DESIGN.md - Safe-area aware: `pb-[env(safe-area-inset-bottom)]` - Active state derivation: same regex patterns as IconRail's `isActive` functions — factor out if possible Delete the existing `MobileBottomNav.tsx` after confirming the new bar covers its behavior. If `MobileBottomNav` has non-destination features (e.g., a "new issue" FAB), report them and the controller will decide whether to keep or drop. ### 2. Mobile slide-over → full-screen sheet Phase 9's `HistorySheet` and `MemorySheet` are desktop slide-overs at 320px / 340px. On mobile: - Take the full viewport width - Full viewport height below the top strip (48px) - Close button in the top-right of the sheet - Swipe-down-to-close gesture (optional — acceptable if CSS-only) Implementation: add a `useMediaQuery("(min-width: 768px)")` check; when mobile, render different class names that go full-screen. Do NOT duplicate the component — same file, conditional rendering. ### 3. Promote-to-project mobile takeover Phase 12's `PromoteTransition` split-screen layout (30% chat ribbon / 70% brainstormer) doesn't fit on mobile. On mobile, the brainstormer **completely covers the chat** — slides up to 100% viewport height instead of 70%. Implementation: same `PromoteTransition.tsx` file, conditional max-height and translate values based on `useMediaQuery`. Tests need a mobile case. ### 4. BuilderTabStrip horizontal scroll Phase 11's Project tab strip has 7 tabs that don't fit on narrow mobile. Spec §9.1 says "Project sub-tabs become a horizontally-scrolling strip under the header, no shrinking." Implementation: on mobile, wrap the tab list in a `flex overflow-x-auto` container with `scroll-snap-type: x mandatory` for tab-sized snapping. Add edge fades (`mask-image` or left/right gradient overlays) so users see there's more content. Tests need a mobile case. ### 5. TopStrip mobile polish On mobile, the top strip should: - Keep the 48px height - Drop the `⌘K` text label and show only the kbd glyph (already minimal — verify) - Keep the mic button - Keep the mode breadcrumb but allow it to truncate if too long - Consider whether to hide the breadcrumb entirely on very narrow screens --- ## Implementation notes ### `useMediaQuery("(min-width: 768px)")` already exists `ui/src/hooks/useMediaQuery.ts` (or similar) is used throughout the codebase. Consume it rather than adding a new media-query hook. ### Mobile breakpoint is single — 768px Per spec §9.2: "Single breakpoint: `>= 768px` is desktop frame, `< 768px` is mobile frame." Don't introduce intermediate breakpoints; everything is binary. ### Tailwind responsive classes vs runtime media query For simple show/hide behavior, use Tailwind's `hidden md:block` / `md:hidden`. For layout variants that need JS logic (like the promote transition's translate values), use `useMediaQuery`. Prefer CSS when possible. --- ## Acceptance criteria 1. On a viewport `< 768px`, the new MobileTabBar renders with 4 destinations matching the IconRail; clicking each navigates correctly 2. The 56px desktop IconRail is hidden on mobile (already `hidden md:flex` from Phase 8 — verify) 3. HistorySheet and MemorySheet render full-screen on mobile 4. The promote-to-project transition completely covers the chat on mobile 5. BuilderTabStrip scrolls horizontally on mobile with no tabs cropped 6. TopStrip remains 48px and functional on mobile 7. Safe-area insets (notch, home indicator) respected 8. `MobileBottomNav` file deleted or clearly documented as dead 9. All existing frame + assistant + projects tests pass 10. Mobile-specific tests added --- ## Report format - Status - Commit SHAs - Files created / modified / deleted - Mobile tests added - Features carried over from MobileBottomNav (if any) - Gesture support (swipe-down-to-close etc.) - Concerns, deviations, self-review