docs: make the component sections executable in one pass
Quality / quality (ubuntu-latest) (push) Failing after 10m7s
Quality / quality (windows-latest) (push) Canceled after 0s

Expands 3.1 and 3.2 so the work can be done without re-deriving anything.

3.1 now records what 0.8.6 already fixed, separated into the ten components
that were miswired and the five that gained outputs they had been firing
undeclared, with the caveat that Map's three were converted but never confirmed
in a browser. For the 22 that remain it adds the finding that changes the
decision: all nine are pure scaffolds with no state, functions or handlers, and
five of them duplicate a component that already works -- FileUpload against
FileInput and FileUploadProgress, Toast and ToastNotifications against Toaster,
AdvancedDatePicker against DatePicker, AdvancedRangeSlider against RangeSlider.
Superseding those is a migration entry rather than new code, and leaves Chart,
TreeView, Confetti and CopyMarkup as the only ones needing to be built.

3.2 corrects the scaffold count from 23 to 28; the earlier figure used a looser
rule. Nine of the 28 are the 3.1 components, so the two items must be planned
together, and several of the rest are primitives that need only their styles
moved out of ui.css rather than any behaviour.

Also corrects the dead-output component count from 11 to 9 in both documents.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 10:34:22 +05:30
co-authored by Claude Opus 5
parent 9ed896d2b9
commit 69020b2555
87 changed files with 3058 additions and 275 deletions
+149 -32
View File
@@ -301,35 +301,150 @@ hydrated DOM, which already looks correct today.
### 3.1 Twenty-two outputs still have no emitter
**Issue.** 22 outputs across 9 components are declared and never fired:
FileUpload (upload, progress, success, cancel, remove), ToastNotifications (add,
dismiss, clear, action), AdvancedDatePicker (open, close, clear),
AdvancedRangeSlider (start, end), Chart (dataPointClick, legendToggle), Confetti
(start, complete), TreeView (expand, collapse), Toast (dismiss), CopyMarkup
(success).
Everything needed to do this in one pass is in this section: what was already
done, what is left, and which disposition each remaining component takes.
Unlike §1.2 these are not miswired — the components genuinely do nothing. Each
needs a real implementation.
#### 3.1.1 Already done in 0.8.6 — do not redo
**Change.** For each: implement the behaviour, or delete the output. Do not
leave a component advertising what it does not do. Deleting is a breaking change
and needs a migration note; implementing Chart and FileUpload is real work and
should be scheduled, not squeezed in.
Fifteen components were fixed. Ten had outputs that were **declared but
miswired** — they dispatched a hand-built `CustomEvent` instead of calling
`output.*`, so the declaration was right and only the emit was wrong. Nothing
was added to these; they were rewired:
**How to test.** The ratchet in `packages/ui/test/ui.test.ts` is pinned at 22
and only ever moves down. Lower the ceiling in the same commit that fixes a
component.
> Card, Footer, Breadcrumb, Accordion, alert, Badge, AnnouncementBar,
> AvatarGroup, ToggleCount, InputNumber
### 3.2 Twenty-three components are still scaffolds
Five more were **firing events they had never declared**, so no caller could
bind to them at all. These gained an `outputs {}` block _and_ were routed
through `output.*`:
**Issue.** No style block, no functions — the same shape as the Table scaffold
that was removed and the LayoutSplitter scaffold that was rebuilt.
| Component | Outputs added | Fires when |
| ----------- | ------------------------------- | ------------------------------------------------------ |
| `Map` | `markerClick`, `select`, `zoom` | marker pressed (both names fire); zoom in/out pressed |
| `SearchBox` | `search`, `clear` | form submitted; clear button pressed |
| `Marquee` | `pause`, `resume` | hover, focus, or the pause/play button |
| `List` | `select` | item pressed — **only items with an `href`**, see §3.4 |
| `Timeline` | `select` | item pressed |
**Change.** Rebuild them properly under §0.1, or remove them. A scaffold in a
published library is a promise the library does not keep.
Verified firing in a browser: `SearchBox`, `Marquee`, `List`, `Timeline`, plus
all ten rewired components. **`Map` was not verified** — its three outputs were
converted by the same mechanical change and the build passes, but no Map was on
the probe page. Put one on a page and confirm before treating it as done.
**How to test.** Per component: it renders, its interactive behaviour works in a
browser, its outputs fire, and it carries its own styles.
#### 3.1.2 What is left — 22 outputs, 9 components
**Issue.** These are not miswired. All nine are **pure scaffolds**: roughly 25
lines each, zero state, zero functions, no style block, no event handlers. They
are markup shells that declare outputs. "Add an emitter" is not the work — there
is nothing to emit from.
**The finding that should drive the decision: most of them duplicate a component
that already works.** This is the Table situation again, where Table was removed
because DataTable superseded it.
| Scaffold | Dead outputs | Already works elsewhere |
| --------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `FileUpload` | upload, progress, success, cancel, remove | `FileInput` (3 fns, 4 outputs) + `FileUploadProgress` (5 fns, 3 outputs), plus the `@wrnexus/uploader` package |
| `ToastNotifications` | add, dismiss, clear, action | `Toaster` (961 lines, 40 fns, fully built) |
| `Toast` | dismiss | `Toaster`, same |
| `AdvancedDatePicker` | open, close, clear | `DatePicker` (8 fns, 8 outputs) |
| `AdvancedRangeSlider` | start, end | `RangeSlider` (11 fns, 8 outputs) |
| `Chart` | dataPointClick, legendToggle | nothing — needs building |
| `TreeView` | expand, collapse | nothing — needs building |
| `Confetti` | start, complete | nothing — needs building |
| `CopyMarkup` | success | nothing — and `Clipboard` is a scaffold too (0 fns) |
**Change, in two groups.**
_Group A — supersede and remove: 5 components, 15 of the 22 outputs._
`FileUpload`, `ToastNotifications`, `Toast`, `AdvancedDatePicker`,
`AdvancedRangeSlider`. Each has a working counterpart, so building them a second
time adds duplicated surface area to maintain for no new capability. Removing
them is a **breaking change** and needs a migration entry naming the replacement
per component, in the same shape as the Table removal.
This is a judgement call and it is yours: superseding is cheap and honest,
keeping them means committing to build five more components properly.
_Group B — build for real: 4 components, 7 outputs._ `Chart`, `TreeView`,
`Confetti`, `CopyMarkup` (and `Clipboard` alongside it, since it is in the same
state). These have no counterpart, so their outputs only become meaningful once
the component exists. Build each under §0.1 — markup, behaviour and styles in
its own `.wrn`.
Notes that will save time:
- **`Chart` needs a rendering decision before any output can mean anything.** An
inline SVG renderer keeps the CSP story intact and adds no dependency; a
charting library ships faster but introduces a third-party runtime dependency
the framework does not currently carry. Decide that first — `dataPointClick`
and `legendToggle` are trivial once something is actually drawn.
- **`TreeView` should reuse the existing roving-focus controller** rather than
growing a new one. Expand/collapse state must live in the component, not in a
deferred callback — see §2.2.
- **`CopyMarkup`'s props are generic input boilerplate** (`name`, `value`,
`placeholder`, `type`, `min`) rather than anything copy-related, which
suggests it was generated rather than designed. Worth deciding what it is
meant to be before building it, or folding it into `Clipboard`.
Rough effort: `CopyMarkup`/`Clipboard` and `Confetti` are small and
self-contained. `TreeView` is medium — recursive rendering plus expand state.
`Chart` is the large one.
**How to test.**
- The ratchet in `packages/ui/test/ui.test.ts` is pinned at 22 and only ever
moves down. Lower the ceiling **in the same commit** that fixes or removes a
component — never in a separate one, or the ratchet stops meaning anything.
- For a removal: `bun run check:public-api` flags the dropped export, and the
migration entry is required before `release:prepare` will pass.
- For a build: the component renders, its behaviour works in a browser, its
outputs reach a page-level `@binding`, and it carries its own styles. Bind the
output from a page and confirm it arrives — §1.1 and §1.2 are both cases where
reading the source said it worked and the browser said otherwise.
### 3.2 Twenty-eight components are still scaffolds
**Issue.** No style block, no functions and no event handlers — markup shells,
the same shape as the Table scaffold that was removed and the LayoutSplitter
scaffold that was rebuilt. A scaffold in a published library is a promise the
library does not keep.
**Evidence.** Counted as components with no `style {}`, no `function` and no
`@handler`. An earlier figure of 23 in the audit was measured with a looser rule;
28 is the number:
> AdvancedDatePicker, AdvancedRangeSlider, AuthSplitLayout, avatar, Blockquote,
> button, Chart, Clipboard, Confetti, CopyMarkup, DataMap, DragAndDrop,
> FeatureIconCard, FileUpload, HeroActions, LegendIndicator, ListGroup,
> MarketingSectionHeader, progress, Rating, skeleton, spinner, StyledIcon,
> TextLink, Toast, ToastNotifications, TreeView, WysiwygEditor
**Nine of these are the §3.1 dead-output components** — AdvancedDatePicker,
AdvancedRangeSlider, Chart, Confetti, CopyMarkup, FileUpload, Toast,
ToastNotifications, TreeView. Do §3.1 first and this list drops to 19 without
any extra work. Do not plan the two items separately.
Separately, **58 components still carry the `wire-next` scaffold class** in
their markup, including many that are otherwise finished. That class is a
generation artefact rather than a design, and it is what ties them to `ui.css`
instead of their own styles (§4.1).
**Change.** Rebuild them under §0.1, or remove them. Note that several are
primitives where a scaffold is nearly the right answer — `skeleton`, `spinner`,
`avatar`, `Blockquote` and `StyledIcon` need styles but genuinely need no
behaviour, so for those "rebuild" means moving their CSS out of `ui.css` into
the component and nothing more. Sort the list into "needs behaviour" and "needs
only its styles" before starting; the second group is much larger and much
cheaper than it looks.
**How to test.** Per component: it renders, any interactive behaviour works in a
browser, its outputs reach a page-level binding, and it carries its own styles.
Track the count down the same way as §4.1:
```bash
bun run build && gzip -c examples/basic-app/dist/ui.css | wc -c
```
### 3.3 Seven components still use Tailwind utilities
@@ -613,16 +728,18 @@ assertion on top.
Ranked by return, not by size. The first item changes the cost of every item
below it, which is why it is first.
| # | Item | Why now |
| --- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| 1 | §2.1 dev-mode diagnostics | Changes the debugging economics of everything else. Every §1 bug would have been minutes instead of hours. |
| 2 | §2.3 reactive props | The biggest capability ceiling. Composition does not work without it. |
| 3 | §2.6 server-rendered i18n | Contained work; the core SSR claim currently fails on text. |
| 4 | §4.2 + §4.3 dev loop | Cheap, and it compounds across every task below. |
| 5 | §4.6 de-duplicate generated client modules | 490 kB decoded parsed per page, 90% of it duplicated. Codegen-only, no API impact. |
| 6 | §4.1 finish the CSS migration | 66 components, mechanical, takes ~26 kB off every page. |
| 7 | §4.6 split controllers out of the core runtime | 6.6 kB gzipped a typical page never executes. |
| 8 | §3.1 implement or delete the 22 dead outputs | Honesty. Deleting is an afternoon; implementing is scheduled work. |
| # | Item | Why now |
| --- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| 1 | §2.1 dev-mode diagnostics | Changes the debugging economics of everything else. Every §1 bug would have been minutes instead of hours. |
| 2 | §2.3 reactive props | The biggest capability ceiling. Composition does not work without it. |
| 3 | §2.6 server-rendered i18n | Contained work; the core SSR claim currently fails on text. |
| 4 | §4.2 + §4.3 dev loop | Cheap, and it compounds across every task below. |
| 5 | §4.6 de-duplicate generated client modules | 490 kB decoded parsed per page, 90% of it duplicated. Codegen-only, no API impact. |
| 6 | §4.1 finish the CSS migration | 66 components, mechanical, takes ~26 kB off every page. |
| 7 | §4.6 split controllers out of the core runtime | 6.6 kB gzipped a typical page never executes. |
| 8 | §3.1 Group A: supersede the 5 duplicate scaffolds | 15 of the 22 dead outputs, and 5 fewer components to maintain. Needs a migration entry, not new code. |
| 9 | §3.2 scaffolds that need only their styles | Larger and cheaper than it looks; folds into item 6. |
| 10 | §3.1 Group B: build Chart, TreeView, Confetti, CopyMarkup | Real component work. Chart needs a rendering decision first. |
§2.2, §2.4 and §2.5 fold into item 1 as diagnostics first, then into item 2 as
model work.
+2
View File
@@ -2413,6 +2413,8 @@
"StreamHandlers",
"StreamImplementOptions",
"StreamImplementation",
"StreamMetrics",
"StreamMetricsSnapshot",
"SubjectContext",
"ToResultOptions",
"Transport",
+3 -2
View File
@@ -82,8 +82,9 @@ do arrive.
A test pins this at 22 as a ceiling that only moves down.
**23 components are still on the `wire-next` scaffold pattern** — no style
block, no functions, and for 19 of them an outputs block they never honour.
**28 components are still scaffolds** — no style block, no functions and no
handlers. Nine of them also declare outputs nothing emits. (An earlier figure of
23 here used a looser rule; see §3.2 of the remediation plan.)
These are the same shape as the Table scaffold that was removed and the
LayoutSplitter scaffold that was rebuilt.