diff --git a/CLAUDE.md b/CLAUDE.md index 64f1a67..d2d8f28 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -274,6 +274,19 @@ When entity A embeds/references entity B, A's mutation handlers invalidate B's d --- +## Frontend — MUI Migration (in progress) + +The admin frontend is being migrated off ~7,100 lines of hand-written CSS onto **MUI (Material UI v7)** — a "Soft-SaaS shell + dense tables" look, dark/light preserved, **incremental and always shippable**. + +- **Spec:** `docs/superpowers/specs/2026-06-06-css-mui-migration-design.md`. **Per-phase plans:** `docs/superpowers/plans/2026-06-06-mui-migration-phase-*.md`. +- **Progress is tracked in agent memory** (`project_mui_migration.md` — what's merged, what's next). **Keep it updated as each phase merges.** Memory practice generally: durable, non-obvious facts about ongoing work / decisions / gotchas belong in the agent memory store (one fact per file, indexed in `MEMORY.md`), not left only in chat. +- **Migrating a page:** mirror `src/admin/pages/Vehicles.tsx` (the pilot). Import only from the **`src/admin/ui/` kit** — never `@mui/*` directly in pages. **Preserve ALL data logic verbatim** (hooks, mutations, `invalidate` arrays, validation, permissions); change only presentation; drop the page's `admin-*` CSS usage. Per page: plan → subagent-driven build → spec + code-quality review → user visual check → merge. +- **Kit (`src/admin/ui/`):** AppShell, Button, Card, TextField, Select (string-based — convert ids at the boundary), DateField (date-fns v4, `dd.MM.yyyy`, cs), Modal, ConfirmDialog (optional `children` + content freeze), DataTable (sortable via `sortKey`/`sortBy`/`onSort`), Pagination, Tabs/TabPanel, StatusChip, CheckboxField, SwitchField, Field, Alert. Theme + tokens in `src/admin/theme.ts`; one `data-theme` attribute drives MUI **and** legacy CSS. Dev-only `/ui-kit` showcase route. +- **Gates every step:** `npx tsc -b --noEmit` (NOT `-p tsconfig.json` — that's a vacuous solution file that checks nothing), `npm run build`, `npx vitest run`. +- **Dialog gotchas (solved in the kit — don't reintroduce):** dialogs lock `` via `useDialogScrollLock` (MUI only locks ``, and `html{overflow-x:hidden}` makes `` the scroll container); Modal/ConfirmDialog freeze title/label/loading through the close fade (derive-state-from-props) so nothing flashes during the transition. Login renders OUTSIDE the AppShell (sibling route). + +--- + ## Database Conventions - All models use `snake_case` column names; Prisma maps to camelCase in TypeScript.