Follow-up to #68 / PRD-018 SC-2. The catalogue landed in #68 — this issue tracks promoting the new primitives into existing higher layers and removing ad-hoc CSS.
✅ Done. Closed by PR #85 (merge commit 821e36c). EvidencePack EVID-023 actions PRD-018 SC-2 "deferred" → "pass". forgeplan score PRD-018 → R_eff = 1.00 (Adequate).
Sub-issues (decomposed 2026-05-07)
Note: widgets/update-dialog/ does not exist as a separate widget — UpdateDialog.svelte lives in widgets/version-footer/ui/. Batch 1 owned its visual atoms; batch 3 audited the form body. No widget extraction was needed.
Why
Issue #68 intentionally landed only the primitive catalogue + /playground showcase to keep the diff reviewable. Widget integration was scoped out (PRD-018 § Out of Scope, EVID-022 § Interpretation). This follow-up closed the design-drift gap.
Scope (in)
Replace ad-hoc atoms with @/shared/ui primitives:
Wider audit (added during the work, beyond the original 3 zones):
Scope (out)
- Refactoring
Button / Code / Dialog / Modal / Select (already shipped pre-PRD-018 — they stay).
- Adding new primitives — catalogue is locked at 26 + 5 existing.
- Theming changes — primitives already cover light/dark via PRD-015 tokens.
- Visual regression test infrastructure (separate effort).
Acceptance criteria
Forgeplan
- ✅ EVID-023 active, linked --informs--> PRD-018, RFC-016.
- ✅ PRD-018 R_eff: 1.00.
- ✅ Rule
24-shared-ui-ownership.md added — codifies "shared/ui owns primitives, upper layers compose only" so the design system stays durable.
Known debt (rule 24 cleanup, follow-up PRs)
Eleven :global() overrides in upper-layer <style> blocks (HealthBar, Filters, ArtifactPanel, InsightsRail, Timeline, UpdateButton, PaneFrame). Each marked TODO(rule-24-cleanup) in EVID-023 §Interpretation. Resolution path: add a new variant/size to the primitive (preferred) or remove.
Catalogue gaps surfaced (follow-up RFC candidate):
Button lacks href — anchor-styled-as-button cases.
Tooltip.Trigger always renders its own <button> — can't wrap <Button>.
Card padding caps at lg (16px) — large card paddings need padding="xl".
Related
Follow-up to #68 / PRD-018 SC-2. The catalogue landed in #68 — this issue tracks promoting the new primitives into existing higher layers and removing ad-hoc CSS.
✅ Done. Closed by PR #85 (merge commit
821e36c). EvidencePack EVID-023 actions PRD-018 SC-2 "deferred" → "pass".forgeplan score PRD-018→ R_eff = 1.00 (Adequate).Sub-issues (decomposed 2026-05-07)
widgets/version-footer/(batch 1/3)widgets/mosaic/(batch 2/3) — Tooltip deferred (catalogue gap)pages/home/(batch 3/3) — Field+Input N/A (no form inputs)Why
Issue #68 intentionally landed only the primitive catalogue +
/playgroundshowcase to keep the diff reviewable. Widget integration was scoped out (PRD-018 § Out of Scope, EVID-022 § Interpretation). This follow-up closed the design-drift gap.Scope (in)
Replace ad-hoc atoms with
@/shared/uiprimitives:widgets/version-footer/— UpdateButton inline<button>→Button. UpdateDialog/VersionFooter intentionally not modified (already primitives or non-atom chrome).widgets/mosaic/— 3 pane-icon<button>in PaneFrame →Button variant=ghost. Other mosaic files reviewed and skipped (drag chrome / layout / not-in-catalogue).UpdateDialogform body +pages/home/—.error-barblock →Alert + Button. UpdateDialog has no form inputs to migrate.Wider audit (added during the work, beyond the original 3 zones):
widgets/artifact-filters/— chips →ToggleGroup type="multiple".widgets/health-bar/— 3-segment theme switcher →ToggleGroup type="single". Notify →Toggle.widgets/insights-rail/— tab count badges →Badge. Lowest R_eff bars →Progress size="md".widgets/artifact-panel/—.kindchip →Badge. 5.ghostbuttons + close × →Button variant="ghost"× 6.widgets/timeline/— collapse trigger →Toggle. "now" button →Button. Error placeholder →<span class="bad">(not Alert — short inline error).Scope (out)
Button/Code/Dialog/Modal/Select(already shipped pre-PRD-018 — they stay).Acceptance criteria
grep -RIn '<style>' template/src/widgets/version-footer template/src/widgets/mosaic template/src/pages/homeshows only layout/motion styles, not atom styles. Verified post-merge — 9 style blocks remain (one per file), zero atom selectors (grep -E '\.(btn|badge|alert|separator|progress|skeleton)\s*\{'returns nothing).@/shared/ui.npm run checkpasses (0 errors, 0 warnings, 1039 files)./and/playground— 0 console errors, dual-theme parity (light + dark verified end-to-end via MCP, including DOM inspection of migrated nodes).PRD-018SC-2 from "deferred" → "pass". EVID-023 active, structured fields filled (verdict=supports, congruence_level=3 CL3, evidence_type=measurement).forgeplan score PRD-018→ R_eff = 1.00 (Adequate).Forgeplan
24-shared-ui-ownership.mdadded — codifies "shared/ui owns primitives, upper layers compose only" so the design system stays durable.Known debt (rule 24 cleanup, follow-up PRs)
Eleven
:global()overrides in upper-layer<style>blocks (HealthBar, Filters, ArtifactPanel, InsightsRail, Timeline, UpdateButton, PaneFrame). Each markedTODO(rule-24-cleanup)in EVID-023 §Interpretation. Resolution path: add a new variant/size to the primitive (preferred) or remove.Catalogue gaps surfaced (follow-up RFC candidate):
Buttonlackshref— anchor-styled-as-button cases.Tooltip.Triggeralways renders its own<button>— can't wrap<Button>.Cardpadding caps atlg(16px) — large card paddings needpadding="xl".Related
template/src/shared/ui/README.md(after PR feat(ui): shadcn-svelte primitives in shared/ui (issue #68) #80)./playgroundroute — visual reference.