dd778d8850
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.
171 lines
10 KiB
Markdown
171 lines
10 KiB
Markdown
# 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 2–8, 58 unchecked)
|
||
|
||
Slice 1 is the only completed slice. The remaining unchecked work (Slices 2–8) 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.
|