← Design · c135

plan.md

c135 plan: Component Cleanup (draft, before kick-off)

Gate: none. Mark's word. It can run beside everything else and helps both the web app (c134) and the token bridge (c132). Reader: Mark; the layer-expert and extraction-expert agents in ../../../q-nuxt-layer; the executor who upgrades the docs here. Mode: archaeology (surface what real use made of the catalog) → formula (apply the principles, group by group). Later stage, more order.

Why

The layer grew with the work: c92 through c128 added components as pages needed them, qdash staged its own library-grade pieces, and two parallel apps (c99) left a list of fixes. The catalog has duplicates and near cousins, components whose shape predates component_philosophy.md, code with no annotation, and documentation pages that show a default rather than the flavors the dashboard actually uses. The control plane web app will stand on this layer for years; the native app's token bridge needs the tokens clean. This is the moment Mark named: clean up the components and tighten the documentation.

What exists

  • The layer: components/ in 23 groups (actor, agent, alert, compliance, data, dev, endpoint, filter, form, health, icon, icon-nav, integration, layout, nav, people, policy, policy-config, prose, security, sentence, transcript, typography, ux), about 250 .vue files. Released by tag (v0.9.37 current). Consumers: design, qdash UI, www, app.qpoint.io.
  • The docs: component-registry.ts (the count of record), 193 demo files with adminProps, the coverage system, /patterns, /layer/consolidation-gaps, the /document-components, /document-pattern and /scan-patterns skills.
  • The principles: component_philosophy.md (unified pantry: visual components live in the layer; business logic stays local; composition over configuration; Tailwind-native; replicate first, optimize later), design_tokens.md, the layer's authoring rules (no relative imports, no arbitrary-value Tailwind, no unscoped element selectors).
  • Waiting lists: LAYER-CANDIDATES.md in the qdash UI (ProjectedBadge, Panel, StatTile, Spark, MetricCell, BarList, Attention*, JsonTree, useVirtualRows, AlertHandlers, SkeletonRows, StateEmpty, plus a state port for DataTable and friends) and the Opus track's 59 fixes (UxIcon id, UxPill danger tone, logo-only AgentAvatar, highlight.js optimizeDeps, and more).

The scorecard

Every component gets one row. The five checks are Mark's, in his order:

CheckPass means
Modularone purpose; a clean interface to the whole; internals free (purpose + protocol)
Cleanno dead props, no arbitrary values, no relative imports, no unscoped selectors; passes the layer's lint
Documenteda doc comment on the component and on every prop, emit and slot (the annotation standard, Phase 0)
Shapedcomposition over configuration; slots where consumers compose; no deep prop trees; tokens not hex
Docs pagea registry entry, a demo with adminProps for every useful prop, and examples that show the dashboard's real flavors (empty, minimal, typical, overflow, error where they apply)

Plus three columns: used by (consumer and count, from a scan), cousins (components it overlaps), and resolution (keep · merge into X · alias and deprecate · split · retire · extract from qdash).

Resolution strategies for duplicates and cousins

  • Merge when two components show the same thing with different props: one survives, the other becomes an alias that warns, removed two minor releases later.
  • Split when one component carries two purposes (a prop that changes what it is).
  • Alias and deprecate when consumers can't move in one release.
  • Retire when no consumer uses it and no pattern needs it (checked against the scan, not memory).
  • Extract when qdash staged a library-grade piece the layer lacks (the waiting lists).
  • Keep with a note when the overlap is deliberate (a dense and a roomy variant that a pattern documents).

Decisions (defaults)

#QuestionDefault
D1Order of groupsux → data → filter, nav, layout → form → the domain groups (actor, agent, policy, compliance, …) → icon, typography, prose. The most-used first.
D2What counts as a duplicatetwo components a consumer could swap without the page meaning something else (the 5-question framework's "is it necessary?").
D3Deprecation windowtwo minor releases, with a console warning and a note in the release.
D4Domain groupsstay in the layer (unified pantry), but each must show a qdash flavor in its docs or it is a retire candidate.
D5Flavors in the docsharvested from the qdash UI by /scan-patterns and recorded as named examples in the demo, not hand-invented.
D6Annotation standardJSDoc-style doc comments on the component, props, emits and slots; a lint rule that fails the layer's build when one is missing (added after the first group passes, so the rule is written from practice).
D7Releasesone per group pass, with the consumers' lockfiles bumped by update-consumers.sh.
D8The waiting listsmerged into one list in the layer repo at Phase 1 and extracted during Phase 2, each ahead of the group it belongs to, so the control plane web app (c134) finds them in the layer from its first page. Ruled 2026-11-09.

Phases

0. Tooling

A script that produces the scorecard skeleton: every component, its props, emits and slots, its demo and adminProps coverage, and its usages across the four consumers. The annotation standard drafted. A scorecard.md committed in this cycle directory.

1. Census

The cousins and duplicates named across the whole catalog, with a proposed resolution each. The two waiting lists merged. Review stop with Mark: the resolutions ruled.

2. Group passes (D1 order)

For each group: apply the resolutions, bring every component to five passes, write the annotations, upgrade the docs pages with harvested flavors and adminProps, release, bump consumers, record. Review stop per group.

3. The lint

D6's rule, from what the first two groups taught; turned on for the whole layer.

4. Close

Coverage numbers before and after, the retired and merged lists, component_philosophy.md updated with anything the work changed, and the /document-components skill updated to produce the new docs shape by default.

Clarifying questions

  1. app.qpoint.io a consumer? Answered 2026-11-09: yes, in the form of its successor, c134's control plane web app (whether it keeps the app.qpoint.io name is a c0 item). It starts from a blank slate, so the layer must already hold what it needs.
  2. Release cadence during the cleanup: per group (D7) or fewer, larger releases?
  3. Extractions here? Answered 2026-11-09: yes, now. Mark: plan on adding the missing components to the layer now, since the successor app starts from a blank slate and builds from the ground up (D8 revised).
  4. Any component families you already know are duplicates, so the census starts from your list?

Patterns to consider

  • The scorecard as a living page on the design site (like /layer/consolidation-gaps), regenerated by the script, so the cleanup's progress is visible and the standard outlives the cycle.
  • Flavors harvested, not invented: a demo example that names the qdash page it came from is a test of the component against real use.
  • graduatedFrom on the registry entry (a pipeline.md follow-up): the cycle and mock each component came from, filled in during the group passes.
  • The token audit as a by-product: every hex or arbitrary value found becomes a token or a bug, feeding c132's bridge.
  • The 5-question framework per component in the scorecard's notes: useful, clear, precise, necessary, beautiful.

Qpoint Brand Style Guide