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() { { setClient(undefined); setQ(''); commit() }}>Change ) : ( - + 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 ( - + { diff --git a/packages/ui/src/ThemeSwitcher.tsx b/packages/ui/src/ThemeSwitcher.tsx index 7cf9cc0..82ce869 100644 --- a/packages/ui/src/ThemeSwitcher.tsx +++ b/packages/ui/src/ThemeSwitcher.tsx @@ -11,7 +11,25 @@ const SWATCH: Record = { amber: '#b97e10', } -/** Compact mode toggle + accent picker; drops into any header. */ +/** Just the light/dark toggle — a single small button for the top bar. The full + * accent picker lives in Settings → Appearance (keeps the header uncluttered). */ +export function ModeToggle() { + const [mode, setMode] = useState(getThemeMode()) + return ( + { + const next = mode === 'light' ? 'dark' : 'light' + setThemeMode(next) + setMode(next) + }} + > + {mode === 'light' ? '☾' : '☀'} + + ) +} + +/** Compact mode toggle + accent picker; drops into any header (used in Settings). */ export function ThemeSwitcher() { const [mode, setMode] = useState(getThemeMode()) const [accent, setAccentState] = useState(getAccent())