Responsive UX/UI: tokens, hooks, drawer nav, workspace gate, a11y primitives #33
Reference in New Issue
Block a user
Delete Branch "devin/1776919187-responsive-uiux-system"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Adds a CSS-first, mobile-first responsive design system to the CurrenciCombo portal. The portal now adapts fluidly from 320 px phones to 2560 px desktops without layout shift, horizontal scroll, or unusable tap targets — and the workspace (IDE) bails gracefully to a dedicated mobile screen below
md.Full strategy, rationale, breakpoints, component inventory, and gotchas live in
docs/ux-responsive-strategy.md.What's in the box
Foundation —
src/styles/:tokens.css— breakpoints (--bp-xs 0 / sm 480 / md 768 / lg 1024 / xl 1440), fluid type scale and spacing viaclamp(), motion, z-index, focus-ring, safe-area-insets.responsive.css— all viewport-conditional overrides. Desktop behavior is byte-for-byte preserved (every rule is wrapped in@media (max-width: …)or@media (pointer: coarse)).a11y.css—:focus-visiblering,.skip-to-content,.sr-only, 44×44 px tap-target enforcement on coarse pointers.Hooks —
src/hooks/:useMediaQuery—useSyncExternalStore-based subscription tomatchMediachange events (nowindow.resize).useBreakpoint— returns{ current, isXs/Sm/Md/Lg/Xl, isMobile, isTablet, isDesktop }.useReducedMotion,useOrientation.a11y primitives —
src/components/a11y/:SkipToContent,VisuallyHidden.Layout changes:
mdso hamburger + logo mark + user avatar fit on a 320 px phone.md(backdrop, Escape to close, closes on route change or resize-up-to-desktop, body-scroll-lock). Tablet (md–lg) forces the 56 px icon-only rail. Desktop (≥ lg) unchanged.repeat(auto-fit, minmax(min(100%, 180px), 1fr))— six cards at xl → one card at xs, fluidly.portal-table--stackstacked-card mode at xs.md, safe-area insets,100dvhto avoid iOS Safari bottom-bar glitch.App.tsx) gates belowmdwith aWorkspaceMobileGate— explains why the IDE isn't shown and deep-links to/dashboard,/transactions,/accounts. Pattern matches VS Code Web, Figma, Replit.Global:
viewport-fit=cover,theme-color, skip-to-content link,<main id="main-content" tabIndex={-1}>landmark.Design rationale highlights
ResizeObserver, nowindow.resizelistener.clamp(min, preferred-with-vw, max)— avoids hard snap at breakpoints.clamp()sizes;auto-fitgrids; intrinsic-aspect-preserving media defaults;position: fixeddrawer.aria-expanded/aria-controls/aria-current, body-scroll-lock, Escape closes all menus.Type of Change
No runtime behavior changes at
≥ lgdesktop viewports — this is additive for smaller viewports.Testing
Automated (this PR):
npm run buildclean (tsc -b && vite build, 2075 modules, 510 ms).npm run lint— net zero new errors (pre-existing 195 errors, post-change 195 errors). Two intentional inlineeslint-disable-next-line react-hooks/set-state-in-effectcomments synchronizing drawer state with routerlocation.pathnameanduseBreakpoint().isMobile— the textbook "sync with external system" use ofuseEffect.Manual (follow-up on this PR):
Viewport sweep across 320 / 375 / 414 / 768 / 1024 / 1280 / 1440 / 1920 / 2560 in both orientations plus 2× DPR, plus Lighthouse mobile + desktop on the
vite previewbuild. Posting screenshots + scores as a comment thread.Checklist
docs/ux-responsive-strategy.md)main)Screenshots
Following up in a comment thread — capturing the viewport sweep + Lighthouse scores in test mode and will attach them directly to this PR.
Additional Notes
CT 8604 cutover status: paused per prior guidance. After this PR merges, I'll resume the 10-step cutover block from earlier. Nothing in this PR affects
scripts/deployment/.Runtime test results — PR #33 responsive UX/UI
Tested the
vite previewbuild of this branch at desktop + mobile emulation, exercised drawer nav, workspace mobile gate, and ran Lighthouse at both form factors. All assertions passed.Devin session: https://app.devin.ai/sessions/a33f9ebe303d413aab86e04252a1b4a1
Summary
display:none, KPI row shows 6 cards in one flex gridaria-label="Open navigation"aria-expanded="false", all nav items markedoffscreenaria-label="Close navigation"aria-expanded="true", nav items become visible (drawer opens with backdrop)/#/transaction-builderat mobile → Workspace Mobile Gate renders (<h2>Transaction Builder is designed for larger screens</h2>+ "Go to Overview" / "View Transactions" / "Accounts" CTAs); full IDE does NOT render/#/transaction-builderrenders full IDE (TitleBar · ActivityBar · LeftPanel · Components · Canvas · RightPanel · BottomPanel) without reload/#/login— Performance ≥ 70, Accessibility ≥ 90, Best-Practices ≥ 85/#/login— same thresholdsLighthouse scores
All three categories comfortably above the PR's own target thresholds in section 7 of the spec.
Workspace mobile gate — the headline behavior
This is the core of Layer C1: at
< mdthe IDE is replaced with a dedicated screen, not rendered-then-broken. A broken implementation would render the full multi-panel layout into a 375 px viewport. Instead you see three portal deep-links./#/transaction-builder(gate)/#/transaction-builder(IDE)<h2>text: "Transaction Builder is designed for larger screens". Three CTAs "Go to Overview" (primary), "View Transactions", "Accounts"Portal drawer — mobile chrome adaptation
aria-label="Open navigation"aria-expanded="false"; sidebar nav items markedoffscreen. Topbar shows logo-mark + notifications + user avatar only.aria-label="Close navigation"aria-expanded="true"; all 9 nav items render; main content dimmed by backdrop.Desktop regression spot-check
Desktop dashboard at 1600 × 1122 — six KPI cards in one fluid row, full sidebar with text labels, no horizontal scroll, hamburger hidden.
Not tested
viewport-fit=cover+100dvh+ safe-area-insets CSS is inherited correctness from spec; I didn't test it on a real device.md–lgicon-rail forced-56 px state was not captured as a distinct screenshot (Chromium mobile emulation is 375 px, not 768 px); the CSS rule exists insrc/styles/responsive.cssand is equivalent-by-construction to the mobile and desktop cases, but has no direct screenshot.prefers-reduced-motion+prefers-contrast: morebranches are media-query conditional; not exercised at runtime here.None of these gaps affect the primary flow the PR is trying to prove.
Ready to merge?
All assertions in the adversarial test plan passed; Lighthouse exceeds all thresholds; no console errors observed during the sweep. Recommend merge, then I'll resume the paused CT 8604 cutover guidance.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.