9.9 KiB
HQ Console Redesign — Design Spec
STATUS: DELIVERED 2026-07-17. All 14 plan tasks landed (warm token system, grouped sidebar shell + Ctrl-K palette, new primitives, every page restyled incl. Client 360 tabs + relationship-pulse ribbon and split-panel login); verification recorded in commit
062ddd0and the suite has stayed green since (293 tests at last count).
Approved direction: "system upgrade" — Direction A v2's system discipline wearing H-04's
warm palette. Sources reviewed: admin_design_v2.html (a Claude Design handoff tar; the
chosen "Direction A v2" system), H-04 Client 360 (timeline ribbon).html, Tecnostac Unified Workspace promo, the small APEX card/loan-detail mockups, and the current
@sims/ui tokens. Companion docs: 2026-07-17-apex-82963-ux-reference.md (UX checklist
honoured throughout), 2026-07-17-quote-to-close-funnel-design.md (pages this shell must
accommodate).
1. Goal & scope
Visual + UX upgrade of apps/hq-web and packages/ui. UI-only: no backend or schema
changes; all data from existing endpoints. Money math, repos, and tests untouched.
@sims/ui stays generic — HQ-specific composites live in apps/hq-web.
2. Design tokens (packages/ui/src/tokens.css)
Warm neutrals + teal default accent; flat, border-defined surfaces (shadows only on overlays); black-ink primary buttons; accent reserved for state.
| Token | Light | Dark (warm-tinted) |
|---|---|---|
--bg |
#FAFAF7 |
#131210 |
--bg-raised |
#FFFFFF |
#1B1A17 |
--bg-hover |
#F2F1EC |
#242320 |
--bg-inset |
#F2F1EC |
#0E0D0B |
--border |
#E7E5DE |
#2B2A25 |
--border-strong |
#D6D4CC |
#3A3830 |
--text |
#1A1A17 |
#EAE8E2 |
--text-dim |
#6B6A62 |
#A8A69C |
- Semantic colors keep current structure (
ok/warn/err+*-soft) re-tuned to the muted H-04 range (ok#047857, warn#A8702B, err#A64242in light; brighter in dark). - New accent
teal(#115E59/ strong#0F4F4A; dark-mode accent ≈#2DA89A) added to the switcher and made the default intheme.ts. All six existing accents stay. - Primary buttons become near-black ink (
--text-derived), not accent-filled. Accent paints active nav, selected chips, links, focus rings. Danger stays red-toned. - Radius:
--radius: 6px(cards, buttons),--radius-sm: 4px(chips, inputs) new,--radius-lg: 10px(modals, palette). Pills 999px. - Type: Inter for UI + money (
tabular-numskept); JetBrains Mono for machine data — client codes, doc numbers, GSTINs, IDs — via a.monoutility class. Uppercase micro-labels 11px / 0.06em tracking (never below 11px — WCAG note from the H-04 review). - Shadows:
--shadow-sm/mdnear-removed from resting surfaces (cards are 1px-bordered, flat);--shadow-lgkept for modals/palette.
3. App shell (Layout.tsx, app.css)
- Sidebar, grouped with uppercase eyebrows + count badges:
- WORK — Dashboard (badge: reminder queue count; amber, red if any failed), Clients, New Document. (Pipeline slots here when the funnel spec lands.)
- CATALOG — Modules
- INSIGHT — Reports
- ADMIN — Employees (currently routed but missing from nav — fixed here; role visibility mirrors the page's own gating), Document Template (owner-only, as today)
- Active item: soft warm fill + 2px accent left bar + 600 weight. Footer: app version +
server-health dot (existing
/api/health).
- Top bar: breadcrumb (route-derived, e.g.
Clients / <name>); search field opening the command palette (Ctrl Kkbd hint); Gmail status pill (ok dot "Gmail" / amber "Gmail disconnected") — the hard-down banner stays as today, restyled; ThemeSwitcher; user chip (initials avatar + display name + role); logout. - Command palette (Ctrl+K): 640px overlay over scrim. Groups: Clients (live results
from the existing
getClients(q)search), Go to (static routes), Actions ("New document", "New client"). Keyboard-first (↑↓ enter esc). Debounced fetch; no new endpoints. - Responsive-lite (APEX-checklist item h): below ~900px the sidebar collapses behind a
hamburger; content single-columns; tables scroll horizontally inside their card
(
overflow-x: auto) — usable on a phone browser, not a native-app layout.
4. Component upgrades (packages/ui — generic only)
| Component | Change |
|---|---|
PageHeader |
Adds optional breadcrumb (Direction A v2 header pattern). Existing call sites keep working (all new props optional). (As built: the status-chip/stat-strip slots were dropped — pages compose Badge/Stats directly, visually equivalent; record pages hand-roll wf-crumbs beside RecordHeader.) |
DataTable |
Per-row tone (subtle *-soft tinting — e.g. overdue rows err-soft; APEX-checklist "pending first" is data-side, tinting is the visual half); per-column mono; sticky header. |
FilterChips new |
Pill row with counts, single-select (All · Active · Dormant · Lost). Serves the funnel spec's `All |
Skeleton new |
Varied-width shimmer bars; replaces every "Loading…" EmptyState. |
ErrorState new |
Message + "Try again" button wired to the page's reload(). |
RecordHeader new |
Initials avatar (deterministic tint from name hash) + title + status pill + meta line + right action cluster. |
Tabs new |
Underline style, optional mono count per tab. |
CommandPalette new |
Generic overlay taking grouped items + async group loader. |
Badge, StatCard, Stats, Modal, Notice, Button, inputs |
Restyled via tokens; StatCard gains optional tone on the hint (delta coloring). |
Icons: lucide-react (new dependency, tree-shaken) for nav + action icons — replaces
the mockups' emoji placeholders. Used in apps/hq-web only, so @sims/ui gains no dependency.
5. Pages (apps/hq-web)
- Dashboard — header stat strip (Overdue ₹ · Queued · Failed · Follow-ups today); reminder queue as the hero card (row-tinted by status; preview/send/dismiss inline as today); remaining sections become cards in a 2-col grid ≥1100px, stacked below. Counts visible on every card; no silent caps (unchanged data contracts).
- Clients — FilterChips by status with counts + existing search + total badge;
codecolumn mono; inline-create form restyled as a card. - ClientDetail → "Client 360" (hero page):
RecordHeader: avatar, name, status pill, meta line (code · state · GSTIN · contact—sincedropped: the Client API carries no createdAt), actions: Log call · Record payment · New document.- KPI row (as built): Active modules · Advance on account ₹ · Open documents · Last interaction. (Spec originally said Outstanding ₹ + AMC status; the server exposes no outstanding figure and client-side paise math is banned — revisit when the ledger endpoint grows an outstanding field.)
- Timeline ribbon "Relationship pulse — last 12 months" (HQ-specific component in
apps/hq-web): 4 lanes — Documents / Payments / Interactions / AMC & renewals — on a shared 12-month axis, plotted from data the page already loads. Hover → readout bar below the strip (H-04's scrubber line:APR · INVOICE INV-042 — ₹1,20,000 · paid); click → navigate to the record (doc →/documents/:id) or switch to its tab. Pure SVG/CSS, no chart library. Legend included for every marker shape. - Tabs replace the 7-section stack: Overview (KPIs + ribbon + recent items) · Modules · Documents · Payments & plans · AMC · Interactions · AWS — counts in labels. Tab state in the URL hash query so links deep-link.
- DocumentView — RecordHeader treatment (doc number mono + status pill + actions), totals right-aligned tabular.
- NewDocument — restyled two-pane (form + LivePreview) with new inputs/cards.
- Reports — pill tab switcher between report types; export/copy affordance kept.
- Modules, Employees, DocumentTemplate — restyled with new primitives; Employees added to nav (ADMIN group).
- Login — split panel: dark warm brand panel (SiMS HQ lockup) + form card.
6. Explicitly not doing
Density toggle; permission matrix / tenant screens (not HQ's domain); roadmap badges in
nav; bulk-select bars and inline table editing (no use case yet); native-app mobile
patterns (responsive-lite only); backend changes of any kind; the Pipeline page itself
(funnel spec builds it — this design only reserves its nav slot and provides FilterChips
/ row-toning it needs).
7. Error handling & states
Every page: Skeleton while loading, ErrorState with retry on fetch failure (wired to
the existing useData.reload), EmptyState with a next-action hint when lists are empty.
Command palette shows "no matches" and network-error rows inline. Gmail pill degrades to
banner behavior exactly as today.
8. Testing & verification
npm run typecheckandnpm teststay green — no domain code touched.- New
@sims/uilogic gets vitest tests (as built: pure-function tests only — avatar hashing, palette matching, pulse month-bucketing; the repo has no DOM test environment, so FilterChips/Tabs/DataTable render behavior is covered by typecheck + the e2e walk rather than render tests). - End-to-end: run server + Vite, exercise Dashboard → Clients → Client 360 (all tabs, ribbon hover/click) → DocumentView → NewDocument preview → Reports → theme/accent switch (light+dark) → Ctrl+K palette → narrow-viewport pass, before claiming done.
9. Build order (for the implementation plan)
- Tokens + base restyle (everything inherits immediately)
- Shell (sidebar groups, top bar, Gmail pill, responsive-lite)
- Generic components (Skeleton/ErrorState/FilterChips/Tabs/RecordHeader/DataTable/PageHeader upgrades)
- Command palette
- Dashboard + Clients
- Client 360 (tabs, then ribbon)
- Remaining pages + Login
- Verification pass (§8)