Files
manage/openspec/changes/web-ui-rework/apply-progress.md
T
Developer dd778d8850 feat(frontend): slice 1 — foundation for MUI->shadcn migration
Web UI rework (openspec/changes/web-ui-rework). Foundation slice:
- Add @tanstack/react-table; remove orphaned recharts, d3
- Vendor shadcn primitives: tabs table dialog input label checkbox
  switch progress separator avatar textarea dropdown-menu scroll-area
- Add Vitest + @testing-library/react + jsdom harness; npm test script
- Delete no-op theme.ts shim; remove getAppTheme references
- Smoke test proves the harness

Gate: build + lint + test green.
2026-06-17 12:11:05 +00:00

171 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Apply Progress — web-ui-rework
> Cumulative apply log. Updated by `sdd-apply` after each slice/sub-slice.
> Strict TDD is **not** active for this change (no strict-tdd directive in
> `openspec/config.yaml`); this run used standard mode against `design.md` / `tasks.md`.
## Status context consumed
- `schemaName: gentle-pi.sdd-status`, `changeName: web-ui-rework`.
- `applyState` reported by the status engine: **blocked** (`blockedReasons`: domain
specs missing/partial; legacy flat `spec.md` present without domain specs). This is a
**planning-completeness** gap, not a safety/`actionContext` blocker.
- `actionContext`: `mode: repo-local`, `workspaceRoot: /home/user/Manage_01`,
`allowedEditRoots: ["/home/user/Manage_01"]`, `warnings: []` — safe.
- This run executed the explicitly delegated **Slice 1 (Foundation)** scope per the
parent acceptance contract. The foundation work is fully specified in `tasks.md`
(Slice 1) and does not depend on the missing domain specs, so it proceeds under the
parent's explicit delegation. The `instructions.apply` line itself says
"Implement only unchecked tasks from the tasks artifact."
- `artifactStore: openspec`; persisted task checkboxes updated in `tasks.md` (13 → `[x]`).
## Slice 1 — Foundation (primitives, TanStack Table, Vitest, token/Badge cleanup) — COMPLETE
All 13 Slice-1 tasks in `tasks.md` are marked `- [x]`. Summary below.
### Completed tasks (persisted checkboxes updated)
- [x] Added the missing shadcn primitives (13): `tabs table dialog input label checkbox
switch progress separator avatar textarea dropdown-menu scroll-area` via
`npx shadcn@latest add …`. The 9 already-present primitives
(`button tooltip sheet card badge alert select skeleton collapsible`) were **not** re-added.
- [x] Installed `@tanstack/react-table` (`^8.21.3`, dependency).
- [x] Removed orphaned charting deps: `recharts`, `d3`, and the companion `@types/d3`
from `package.json` (zero `from "recharts"` / `from "d3"` / `from "d3-*"` imports
existed in `frontend/src`).
- [x] Deleted `frontend/src/theme.ts` (no-op `getAppTheme` shim). Grep confirmed the
only reference was the file itself; no source file imported it.
- [x] Added the `success` Badge variant (`chart-2`) and the `warning` variant (`chart-3`)
to `frontend/src/components/ui/badge.tsx`, mirroring the `destructive` soft-cue pattern
exactly per design §2.3.
- [x] Documented the `chart-1..5` role mapping as an inline comment block above the
tokens in **both** the `@theme` block and `.dark` block of `frontend/src/index.css`
(chart-1=info/brand, chart-2=success, chart-3=warning, chart-4=destructive,
chart-5=neutral-accent). **No token value changed; no token dropped. Primary `#4f8cff`.**
- [x] Created `frontend/vitest.config.ts` (separate from `vite.config.ts`):
`vitest/config` `defineConfig`, `@vitejs/plugin-react`, `environment: "jsdom"`,
`globals: true`, `setupFiles: ["./src/test/setup.ts"]`, the `@` path alias from
`tsconfig.app.json`, and `include: ["src/**/*.{test,spec}.{ts,tsx}"]` (does NOT claim
the `frontend/tests/*.mjs` node suites).
- [x] Created `frontend/src/test/setup.ts` registering `@testing-library/jest-dom`
matchers (via the `/vitest` entry for runtime + TS augmentation).
- [x] Installed dev deps: `vitest@^4.1.9`, `@testing-library/react@^16.3.2`,
`@testing-library/jest-dom@^6.9.1`, `@testing-library/user-event@^14.6.1`,
`jsdom@^29.1.1`.
- [x] Added npm scripts: `"test": "vitest run"`, `"test:watch": "vitest"`,
`"test:node": "node --test tests/*.test.mjs"` (see Deviations).
- [x] Added one trivial passing component test: `src/components/ui/__tests__/badge.test.tsx`
(asserts a `success` Badge renders with the `chart-2` cue).
- [x] Verified lucide-react `1.14.0` exports every name used by later slices:
`Pencil, X, Paperclip, Bold, Italic, Link, List, Mail, Send, Trash2, DatabaseBackup,
ExternalLink`. **`DatabaseBackup` IS exported — no fallback needed** (slice-3 nav will
use `DatabaseBackup`).
- [x] **Exit gate green:** `npm run build` + `npm run lint` + `npm test` + `npm run
test:node` all pass; no `theme`/`getAppTheme` imports remain.
### Files changed (tracked)
Modified:
- `frontend/package.json` (added `@tanstack/react-table`, vitest/testing-library/jsdom
dev deps, test scripts; removed `recharts`, `d3`, `@types/d3`)
- `frontend/package-lock.json` (regenerated by npm)
- `frontend/src/components/ui/badge.tsx` (added `success` + `warning` variants)
- `frontend/src/components/ui/tabs.tsx` (vendored primitive; un-exported
`tabsListVariants` to satisfy `react-refresh/only-export-components` — see Deviations)
- `frontend/src/index.css` (chart-1..5 role-mapping comment blocks in `@theme` + `.dark`)
Deleted:
- `frontend/src/theme.ts`
Added (new):
- `frontend/vitest.config.ts`
- `frontend/src/test/setup.ts`
- `frontend/src/components/ui/__tests__/badge.test.tsx`
- 13 new shadcn primitives under `frontend/src/components/ui/`:
`tabs.tsx, table.tsx, dialog.tsx, input.tsx, label.tsx, checkbox.tsx, switch.tsx,
progress.tsx, separator.tsx, avatar.tsx, textarea.tsx, dropdown-menu.tsx,
scroll-area.tsx`
Untouched (no-unintended-edits respected): the 22 MUI page/component files in
Slice 1's scope (all `frontend/src/pages/*` and `frontend/src/components/*.tsx` outside
`components/ui/`) — `git status --porcelain frontend/src/pages 'frontend/src/components/*.tsx'
| grep -v 'components/ui/'` returns nothing.
Also touched (gitignored generated docs, not tracked changes): `frontend/src/.pi-map.md`
and `frontend/src/.pi-map.index.md` were refreshed to remove the now-deleted `theme.ts` /
`getAppTheme` references (the `project_map_patch` tool is unavailable in this session, so
the stale generated maps were minimally reconciled to match source).
### Commands run (validation)
- `npx shadcn@latest add tabs table dialog input label checkbox switch progress separator avatar textarea dropdown-menu scroll-area --yes` → created 14 files (13 primitives + a duplicate button written to a stray `@/` path; stray dir removed, dup button discarded).
- `npm i @tanstack/react-table` → ok.
- `npm i -D vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom` → ok.
- `npm uninstall recharts d3 @types/d3` → ok.
- `cd frontend && npm run build` → **PASS** (`tsc -b` + `vite build`).
- `cd frontend && npm run lint` → **PASS** (0 errors, 0 errors; 2 pre-existing `react-hooks/exhaustive-deps` warnings in `UsersPage.impl.tsx` that are out of Slice-1 scope).
- `cd frontend && npm test` → **PASS** (Vitest: 1 file, 1 test passed).
- `cd frontend && npm run test:node` → **PASS** (legacy node:test suites green).
### Deviations from design / task text (documented)
1. **`tabs.tsx` variant export.** The vendored shadcn `tabs.tsx` exported
`tabsListVariants` (a `cva` function) alongside components, which violates
`react-refresh/only-export-components` and broke `npm run lint`. The project's own
convention (`button.tsx`, `select.tsx`) is to **not** export the `cva` variant helper,
so `tabsListVariants` was removed from the `export { … }` statement (the `const` is
retained for internal use by `TabsList`). This keeps the component API intact for all
later slices (TabbedCard uses `<TabsList variant=…>`, not the helper).
2. **`test:node` script form.** The task text specifies `"test:node": "node --test tests"`,
but on **Node v22.22.2** a bare directory argument is resolved as a CommonJS module
entry point (`Error: Cannot find module '…/tests'`). The functional equivalent
`"test:node": "node --test tests/*.test.mjs"` is used instead, which targets exactly
the legacy node:test suites (`users.test.mjs`, `userState.test.mjs`) and passes.
`node --test` auto-discovery also passes; the glob form is the explicit, minimal choice.
3. **shadcn CLI path artifact.** The CLI resolved the `@/` alias to a literal
`frontend/@/` directory. All 13 primitives were moved to `frontend/src/components/ui/`
and the stray `frontend/@/` tree was deleted; the duplicate generated `button.tsx`
was discarded to keep the existing tracked `button.tsx` unchanged.
4. **Stale generated `.pi-map.md`** files referenced the deleted `theme.ts`. Since the
`project_map_patch` tool is unavailable this session, they were minimally reconciled to
match source (these are gitignored generated docs, not tracked changes).
### Slice boundary / PR
- Slice 1 is the foundation slice (~vendored primitives dominate the line count).
Per the Review Workload Forecast this slice is "at/over" 400 lines and may be taken as
a vendored-primitives **size exception** or sub-split 1a/1b. The majority of the diff is
generated shadcn primitives (mechanical, vendored). **No delivery decision was provided
in this run's delegation** (the parent delegated a single foundation slice); this run
implemented the whole foundation in one slice. The parent should confirm the PR shape
(1a/1b split vs. generated-code size exception) when opening the PR.
## Remaining tasks (Slices 28, 58 unchecked)
Slice 1 is the only completed slice. The remaining unchecked work (Slices 28) is listed
verbatim in `tasks.md`. The first unchecked items are (Slice 2 — Shared components):
- [ ] Migrate `frontend/src/components/SectionCard.tsx` …
- [ ] Migrate `frontend/src/components/SelectionRailCard.tsx` …
- [ ] … (see `tasks.md` Slice 2 → Slice 8)
Dependency order is fixed (DAG in `tasks.md`): `1 → 2 → {3,4,5,6}`; `4 ← 3`;
`{3,4,5,6} → 7`; `{1..7} → 8`. **Next recommended:** Slice 2 (Shared components) — it is
unblocked now that all primitives, TanStack Table, the Vitest harness, the `success`/
`warning` Badge variants, and the cleared `theme.ts` are in place.
## Risks / notes for the parent
- The overall change `applyState` is **blocked** on **missing domain specs** (legacy flat
`spec.md` present without domain specs). This does not block Slice 1 (done) but should
be resolved before `sdd-verify`/archive. Recommended: convert/supplement `spec.md` into
domain specs, or have the orchestrator confirm the flat spec is acceptable.
- The two `react-hooks/exhaustive-deps` **warnings** in `UsersPage.impl.tsx` are
pre-existing and out of Slice-1 scope (lint still passes — warnings, not errors).
- `npm audit` reports 8 vulnerabilities in the dependency tree (pre-existing across the
MUI/emotion/react stack); not introduced by this slice and out of scope.
- `DatabaseBackup` from lucide-react is available — Slice 3 nav should use it directly.