From bbe125892dc6d36f84fb9680d34ee9f66e14750e Mon Sep 17 00:00:00 2001 From: Thomas Joise Date: Sat, 18 Jul 2026 12:19:09 +0530 Subject: [PATCH] fix(d26): accent picker off top bar + mobile UX pass + responsive billing - The 7-swatch accent selector is removed from the top bar (it now lives only in Settings > Appearance); the bar keeps a single compact light/dark ModeToggle. This declutters the header and fixes most of the mobile congestion. - Mobile pass (<=640px): search takes the bar, Ctrl-K hint + Gmail pill hidden, avatar-only user chip; pages get real padding + bottom room; toolbars/chips wrap with air; inputs full-width & 42px tall; stats 2-up; tables padded. - Billing composer: client search + line-item cards go full-width and stack on phones (composer-search / composer-line classes) so no container is undersized. typecheck + web build clean, web tests 4/4. Co-Authored-By: Claude Fable 5 --- apps/hq-web/src/Layout.tsx | 4 +-- apps/hq-web/src/app.css | 49 +++++++++++++++++++++++++-- apps/hq-web/src/pages/NewDocument.tsx | 4 +-- packages/ui/src/ThemeSwitcher.tsx | 20 ++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/apps/hq-web/src/Layout.tsx b/apps/hq-web/src/Layout.tsx index 550bb9f..d975c41 100644 --- a/apps/hq-web/src/Layout.tsx +++ b/apps/hq-web/src/Layout.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { Navigate, NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom' import { LogOut, Menu, Search, UserRound } from 'lucide-react' import { - avatarColors, Badge, CommandPalette, initials, ThemeSwitcher, type PaletteItem, + avatarColors, Badge, CommandPalette, initials, ModeToggle, type PaletteItem, } from '@sims/ui' import { clearSession, displayName, getClients, getEmailStatus, getReminders, hasSession, role } from './api' import { NAV_GROUPS } from './nav' @@ -204,7 +204,7 @@ export function Layout() { {gmail === 'ok' ? 'Gmail' : 'Gmail disconnected'} )} - + {/* D18 WS-E: the user chip opens a small menu — Profile / Logout. */} Appearance), and phones get real breathing room. Targets + ≤640px: the cramped-phone width the user tested on. + ============================================================================ */ +@media (max-width: 640px) { + /* Top bar: search is the star, everything else compact. */ + .hq-top { gap: 8px; padding: 8px 12px; } + .hq-search { flex: 1; min-width: 0; height: 40px; font-size: 15px; } + .hq-search kbd { display: none; } /* the Ctrl-K hint is desktop-only */ + .hq-pill { display: none; } /* Gmail status shows in the banner/Settings, not the phone bar */ + .mode { padding: 6px 9px; font-size: 15px; } + .hq-user .hq-user-name { display: none; } /* avatar + role only */ + .hq-user { padding: 4px 6px; gap: 5px; } + + /* Pages: generous, single-column, full-width children. */ + .wf-page { padding: 14px 14px 96px; } /* bottom room so content clears the thumb zone */ + .wf-card { padding: 14px; } + .wf-page > *, .wf-card { max-width: 100% !important; } + + /* Toolbars & filter chips wrap with air, don't jam into one line. */ + .wf-toolbar { flex-wrap: wrap; gap: 8px; row-gap: 10px; } + .wf-toolbar > .wf, .wf-toolbar select.wf, .wf-toolbar input.wf { flex: 1 1 auto; min-width: 140px; } + .wf-chips { flex-wrap: wrap; gap: 6px; } + + /* Inputs full width & tall enough to tap; 16px kills iOS focus-zoom (already set globally). */ + input.wf, select.wf, textarea.wf { width: 100%; min-height: 42px; } + .wf-field { width: 100%; } + + /* Stats: two-up so the numbers stay big and readable. */ + .wf-stats { grid-template-columns: 1fr 1fr; gap: 10px; } + + /* Dialogs already bottom-sheet (earlier pass); keep them roomy. */ + .wf-dialog-body { padding: 14px 16px; } + + /* Tables scroll, with a subtle hint that there's more sideways. */ + table.wf { font-size: 13.5px; } + table.wf th, table.wf td { padding: 9px 10px; white-space: nowrap; } + + /* The New-Document composer: every container fills the screen (no 340px caps). */ + .wf-page .composer-search, .wf-page .composer-line { max-width: 100% !important; width: 100%; } + .wf-page .composer-line { flex-direction: column; align-items: stretch; } + .wf-page .composer-line > * { width: 100%; } +} diff --git a/apps/hq-web/src/pages/NewDocument.tsx b/apps/hq-web/src/pages/NewDocument.tsx index a911851..b100520 100644 --- a/apps/hq-web/src/pages/NewDocument.tsx +++ b/apps/hq-web/src/pages/NewDocument.tsx @@ -180,7 +180,7 @@ export function NewDocument() { ) : ( -
+
setQ(e.target.value)} /> {hits.length > 0 && (
@@ -222,7 +222,7 @@ export function NewDocument() { const editions = editionsOf(prices) const priceGap = warnings.some((w) => mod !== undefined && w.includes(mod.code)) return ( -
+