From 7a9c6f94594d979c5e31d406ce61db8a548e7056 Mon Sep 17 00:00:00 2001 From: Thomas Joise Date: Fri, 17 Jul 2026 10:53:57 +0530 Subject: [PATCH] =?UTF-8?q?docs(spec):=20ideal-web-app=20pass=20=E2=80=94?= =?UTF-8?q?=20edit=20everywhere,=20dialogs,=20toasts,=20settings=20hub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pinterest-chrome modals (Dialog/ConfirmDialog), Toaster, client editing (server already supports it), send-by-email modal replacing window.prompt, /settings hub with dated reminder-schedule rows + sharing default (two small additive backend slices), favicon + per-route titles. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../specs/2026-07-17-ideal-web-app-design.md | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-17-ideal-web-app-design.md diff --git a/docs/superpowers/specs/2026-07-17-ideal-web-app-design.md b/docs/superpowers/specs/2026-07-17-ideal-web-app-design.md new file mode 100644 index 0000000..db27b5b --- /dev/null +++ b/docs/superpowers/specs/2026-07-17-ideal-web-app-design.md @@ -0,0 +1,111 @@ +# "Ideal Web App" Pass — Edit Everywhere, Dialogs, Toasts, Settings Hub + +*Approved 2026-07-17 (Approach A). Fixes the six gaps that keep the console feeling like a +wireframe despite the D17 restyle: no record editing, browser `window.prompt/confirm` +popups, silent success, no Settings home, inline wireframe forms, no favicon. Visual +reference: Pinterest's product chrome — centered rounded modals with generous padding and +pill buttons, and a left-rail settings page.* + +## 1. Goal & scope + +Make every flow feel like a finished web application. Mostly UI; two **small additive +backend slices** (reminder-schedule endpoints, sharing default). No schema changes beyond +zero (settings ride the existing `setting` table; cadence changes are new dated +`reminder_schedule` rows per rule 3). `@sims/ui` stays generic. + +**Key server fact:** `PATCH /clients/:id` already updates name / gstin / stateCode / +address / contacts / status / notes (`repos-clients.ts:85`) — client editing is pure UI. +`updateAmc`, `updateRecurringPlan`, `updateInteraction`, `patchModule`, `patchEmployee` +likewise exist and are under-used by the UI. + +## 2. App-chrome kit (`packages/ui` — generic only) + +| Piece | Contract | +|---|---| +| `Dialog` | Pinterest modal. Props: `open, onClose, title, size?: 'sm'\|'md'\|'lg'` (420/560/720px max-width), `footer?: ReactNode`, children = body (scrolls if tall). 16px radius, `--shadow-lg`, scrim (blur + dim) closes on click; Esc closes; **focus trap + focus restore** (same technique as `CommandPalette`); `role="dialog" aria-modal aria-label={title}`; ✕ button in the title row. Replaces the legacy `Modal` (currently zero call sites — delete it). | +| `ConfirmDialog` | On top of Dialog (`size='sm'`): `open, onClose, onConfirm, title, body?, confirmLabel?, tone?: 'danger'`. Confirm button is ink (or danger red); busy state while `onConfirm`'s promise resolves. Kills every `window.confirm`. | +| `Toaster` | `ToastProvider` (mounted once in `main.tsx`) + `useToast()` → `toast.ok(msg)`, `toast.err(msg)`. Bottom-right stack, max 3 visible, 4s auto-dismiss + ✕, `aria-live="polite"`, ok/err tones from tokens. Pure state logic in an exported reducer (`toast-store.ts`) so it's unit-testable without a DOM. | +| `FormGrid` | `display:grid; grid-template-columns: 1fr 1fr; gap 12px` (single column ≤560px); fields span-2 via a `wide` prop on a `FormField` wrapper (thin wrapper over existing `Field`). | +| `Button pill` | `pill?: boolean` prop → 999px radius (Pinterest button shape) — used in dialog footers only. | + +CSS: new `wf-dialog*`, `wf-toast*`, `wf-formgrid` blocks in `tokens.css`; z-order — drawer +40 < modal-back 50 < palette 60 < toasts 70. + +## 3. Edit everywhere (all modals; toast on success; ConfirmDialog on destructive) + +| Surface | Modal content | Endpoint (exists) | +|---|---|---| +| Client 360 header → **Edit** | name · GSTIN · state · address · notes + **contacts repeater** (name/email/phone/role rows, add/remove, ≥0 rows) | `PATCH /clients/:id` | +| Clients → New client | same form, empty; `?new=1` opens it | `POST /clients` | +| AMC row → Edit / new | coverage, period, amount ₹, reminder days | `PATCH /amc/:id`, create | +| Plan row → Edit / new | module, cadence, amount, next run, policy | `PATCH /recurring/:id`, create | +| Interaction row → Edit / log | type, date, outcome, follow-up, notes | `PATCH /interactions/:id`, create | +| Employees add / edit / reset-pw | as today's inline forms | existing | +| Modules new / add-price | as today's inline forms | existing | +| Deactivate (AMC/plan/employee) | ConfirmDialog, danger tone | existing | + +Quote-content editor stays inline (it has the live preview pane). Inline `Notice` remains +only for in-form validation; all mutation success/failure also lands a toast. + +## 4. Send-by-email modal + document confirms + +- **Send** (DocumentView): Dialog with **To** — `