whynot-design/CHANGELOG.md

178 lines
11 KiB
Markdown
Raw Normal View History

2026-05-23 16:34:14 +02:00
# Changelog
All notable changes to `@whynot/design` are recorded here. Hand-edited until release cadence makes it painful.
2026-05-25 19:32:22 +02:00
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning rules: see [`DesignSystemIntroduction.md` §6](./DesignSystemIntroduction.md#6-versioning-discipline).
2026-05-23 16:34:14 +02:00
## [Unreleased]
2026-06-29 00:40:09 +02:00
## [0.4.0] — 2026-06-28
### Fixed
- **Showcase page no longer wedges the renderer** (WHYNOT-WP-0002 T11). `<wn-breadcrumb>`
inserted separator elements into its own light DOM on `slotchange` while cleaning up
in the shadow DOM, so separators were never removed — each insertion re-fired
`slotchange` and the main thread looped forever, so `examples/showcase/index.html`
never finished rendering. `WnBreadcrumb._onSlot` is now idempotent (excludes its own
separators; mutates only when they are not already correct). The showcase visual test
is un-`fixme`'d and captures a stable `showcase.png`, unblocking WHYNOT-WP-0003 T08
(showcase as per-version visual catalog).
### Removed
- **Dead Google-Fonts `@import`** from `src/styles/colors_and_type.css`. Every token
font stack is system-ui based, so the imported IBM Plex webfont was unused; it was
also a documented source of CI flakiness. No visual change (system fonts unchanged).
### Added
- **Versioned IR manifest + consumer drift-check** (WHYNOT-WP-0003, Phase 14). The
`ir/` contract is now the unit of versioned downstream consumption:
- `ir/manifest.json` (T03) — per-version inventory + diff anchor:
`{ schemaVersion, designVersion, generatedAt, tokensHash, components:[{name,group,hash}] }`,
each hash a deterministic sha256 over canonicalised JSON (formatting-invariant,
`generatedAt` reused on no-op runs → no git churn). Schema:
`ir/schema/manifest.schema.json`. Emitted by `make ir`.
- `ir/INDEX.md` (T07) — human-readable catalog generated from the contracts;
browse a version without cloning or running anything. Emitted by `make ir`.
- **`npx @whynot/design drift`** (T05) — consumer-side drift-check (`bin/whynot-design.mjs`,
new `bin` entry). Compares a consumer's adopted `.whynot-design.lock` against the
installed package's manifest and reports added/changed/removed components + token
changes (`--json`, `--update`, `--manifest`, `--version`, `--lock`). Exit codes
mirror the adapter contract: `0` in sync · `2` usage error · `3` drift.
- `.whynot-design.lock` sync-point format (T04) — `ir/schema/lock.schema.json` +
documented lifecycle (consumer-side mirror of `designbook/.design-sync.json`).
- `CONSUMING.md` (T06) — pin → inspect → drift → update guide, with a runnable
`examples/consumer-fixture/`; cross-linked from `README.md` and `MultiFrameworkSupport.md`.
- `CONSUMER_CONTRACT_PARITY.md` (T09) — design-only note + recorded go/defer
decision for the heavier live-UI-vs-contract parity mode (deferred).
- **Publishable to the coulomb Gitea npm registry** (WHYNOT-WP-0003 T02) — `private:false`,
`publishConfig.registry`, real `repository.url`, an `.npmrc` scope + `${NPM_AUTH_TOKEN}`
reference (no secret committed), and `PUBLISHING.md` (publish flow + consumer install +
token routing). The package now ships the `ir/` consumer contract (added to `files` and
the `./ir/*` export) so consumers can pin a version and track it.
### Changed
- **`lit` is now a `peerDependency`** (`^3`), not a direct dependency. Consumers must
install `lit` alongside `@whynot/design` (`npm i @whynot/design lit`) so their bundler
dedupes to a single `lit` instance.
2026-06-27 14:03:23 +02:00
## [0.3.0] — 2026-06-27
feat(designbook): technology-neutral IR + stack-adapter pipeline (WHYNOT-WP-0002 T01-T06) Author the design language once in the canonical React designbook and project it one-way onto each stack: React -> designbook/ -> ir/ -> adapters/<stack>/. Phase 0 — contracts & governance (T01-T03): - ir/SCHEMA.md + ir/schema/{component,tokens}.schema.json — neutral IR contract (W3C DTCG tokens; React prop -> HTML attribute mapping; non-portable props flagged). - adapters/ADAPTER_CONTRACT.md — inputs, drift-report + parity-result shapes, idempotency rules, CI exit codes (0 ok / 2 usage / 3 drift / 4 parity / 5 internal). - .claude/rules/designbook-propagation.md + DesignSystemIntroduction.md §5.1 — one-way directionality + drift-resolution workflow. T04 — canonical React designbook + the missing pull tool: - The bundled /design-sync skill only PUSHES repo->cloud; it cannot populate designbook/. Added scripts/designbook_pull.py + `make designbook-pull`, which drives the local claude binary headless (acceptEdits) so DesignSync fetch+write runs in a subprocess (contents never hit the orchestrator's context). Pulled 44 files; excludes the _whynot-design-seed/ self-copy. Corrected the docs that wrongly called /design-sync the pull. T05 — IR extractor (scripts/ir-extract.mjs + `make ir`): - ir/tokens.json (80 tokens, DTCG, var() -> {ref} alias resolution); ir/components/*.json (10 contracts parsed from .jsx signatures: enum/boolean/number inference, prop->attr map, style/callback marked non-portable); ir/exemplars/*. T06 — Lit token adapter (adapters/lit/ + `make adapt-lit`): - Full-gen tokens into src/styles/colors_and_type.css :root (marker-bounded, idempotent no-op on re-run; hand-authored type CSS preserved). NOTE: token regen synced Lit to canonical React — fonts IBM Plex -> system stacks and 8 status tokens added. This is a VISUAL change: review and run `pnpm test:visual:update` before merge. Remaining: T07 scaffold+drift, T08 parity, T09 runbook, T10 2nd-adapter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 12:36:24 +02:00
### Added
- **Technology-neutral IR + stack-adapter pipeline** (WHYNOT-WP-0002, Phase 03). The
design language is now authored once in the canonical React designbook and projected
one-way onto each stack: `React → designbook/ → ir/ → adapters/<stack>/`.
- `ir/` — committed, diffable blueprint: `ir/SCHEMA.md`, JSON Schemas
(`ir/schema/{component,tokens}.schema.json`), and the extractor's output
(`ir/tokens.json` in W3C DTCG format, `ir/components/*.json`, `ir/exemplars/*`).
- `adapters/ADAPTER_CONTRACT.md` — the contract every stack adapter implements
(inputs, drift report + parity result shapes, idempotency, CI exit codes).
- `scripts/designbook_pull.py` + `make designbook-pull` — pulls the React designbook
from Claude Design into `designbook/` (the bundled `/design-sync` skill only
*pushes*, so it cannot populate `designbook/`).
- `scripts/ir-extract.mjs` + `make ir` — extracts the IR from the `.jsx` ui-kit,
manifest, and previews.
- `adapters/lit/` + `make adapt-lit` — Lit reference adapter; tokens fully generated
into `src/styles/colors_and_type.css` (marker-bounded, idempotent).
- `.claude/rules/designbook-propagation.md` + `DesignSystemIntroduction.md` §5.1 —
one-way governance and drift-resolution workflow.
### Changed
- `src/styles/colors_and_type.css` — token `:root` block is now **generated** by
`make adapt-lit` from `ir/tokens.json` (between `@generated tokens` markers). This
synced the Lit token layer to the canonical React designbook: font stacks switched
from IBM Plex to system-font stacks, and the functional-status tokens
(`--status-error/warn/success/info` + `-bg`) were added. **Visual change — Playwright
baselines need review + `pnpm test:visual:update`.**
2026-05-23 16:34:14 +02:00
### Fixed
- **Visual-regression harness now renders deterministically.** The four
`examples/whynot-control` pages render and screenshot cleanly against the new tokens.
Snapshot baselines are now **gitignored** (generated locally via
`pnpm test:visual:update`, not committed — they are large binary test artifacts).
Along the way:
- `serve.json` (`cleanUrls:false`) — the static server was 301-redirecting
`/…/index.html` to a trailing-slash-stripped URL, shifting the document base and
404'ing every relative asset (also broke `pnpm showcase` in the browser).
- `examples/whynot-control/index.html` — token stylesheet linked a non-existent
root path; repointed to `../../src/styles/colors_and_type.css` so the page picks
up the design tokens.
- `examples/vendor/lit.js` — vendored a self-contained esbuild bundle of `lit` and
pointed the showcase importmap at it, replacing the multi-hop live esm.sh module
graph (regen command noted in the showcase importmap comment).
- `tests/visual/ui-kit.spec.mjs` — abort the (unused, post-IBM-Plex) Google-Fonts
CDN in tests; a hung font request was blocking module execution and `load`.
- The `showcase` "every component" visual test is `test.fixme` pending
**WHYNOT-WP-0002-T11** — that page wedges the renderer main thread (a demo
composition loops); the four control baselines are unaffected.
2026-05-25 19:32:22 +02:00
## [0.2.0] — 2026-05-25
2026-05-23 16:34:14 +02:00
2026-05-25 19:32:22 +02:00
**Architectural reframe.** The system is now delivered as three stacked layers — tokens + CSS, Lit web components, optional framework adapters. The previous React-only component layer has been removed.
2026-05-23 16:34:14 +02:00
### Added
2026-05-25 19:32:22 +02:00
- `MultiFrameworkSupport.md` — full integration guide for React, Django, HTMX, Vue, Svelte, plain HTML.
- `src/elements/` — Lit-based web components, light-DOM rendered:
- **Atoms** (`atoms.js`): `<wn-button>`, `<wn-tag>`, `<wn-eyebrow>`, `<wn-stamp>`, `<wn-stage-dot>`, `<wn-phase-dot>`, `<wn-icon>`.
- **Form** (`form.js`): `<wn-input>`, `<wn-textarea>`, `<wn-select>`, `<wn-search-input>`, `<wn-field-row>`.
- **Layout** (`layout.js`): `<wn-card>`, `<wn-modal>`, `<wn-table>` + `<wn-table-row>` + `<wn-table-cell>`, `<wn-banner>`, `<wn-toast>` + `<wn-toast-region>`, `<wn-empty-state>`, `<wn-breadcrumb>`.
- **Chrome** (`chrome.js`): `<wn-top-nav>`, `<wn-sidebar>` + `<wn-sidebar-group>` + `<wn-sidebar-item>`, `<wn-page-header>`, `<wn-pipeline>`, `<wn-prototype-card>`.
- `src/elements/icons.js` — Lucide-derived inline icon paths (no runtime CDN dependency).
- `src/styles/components.css` — utility-class layer (`wn-btn`, `wn-card`, `wn-tag`, etc.). Consumable directly from any HTML for the "Layer 1 only" use case.
- `adapters/django/templates/whynot/*.html``{% include %}`-ready partials for Django consumers (button, eyebrow, tag, stage-dot, page-header, pipeline, field-row, prototype-card, banner, empty-state).
- `adapters/django/README.md` — how to wire the partials into a Django app.
- `examples/showcase/index.html` — single-page reference rendering every component. Doubles as the Playwright visual-regression baseline.
- `lit` ^3.2.1 as a runtime dependency.
### Changed
- `DesignSystemIntroduction.md` — updated to describe the three-layer architecture, multi-framework consumption, and the revised propagation pipeline.
- `README.md` — top-level rewrite around the new architecture, with quick-start blocks per framework.
- `package.json` — adds per-group `exports` (`@whynot/design/atoms`, `/form`, `/layout`, `/chrome`, `/icons`).
- CI now runs visual regression against `examples/showcase/index.html` *and* `examples/whynot-control/index.html`.
### Removed
- `src/components/Atoms.jsx`, `src/components/Chrome.jsx` — the React-only component layer. Consumers using these from v0.1.0 should swap to the corresponding custom elements (drop-in replacements; see `MultiFrameworkSupport.md` § React).
- `peerDependencies` on React. React is no longer required to consume `@whynot/design`.
### Migration
If you were on v0.1.0 with React imports like `import { Button } from "@whynot/design"`:
| Before (v0.1.0) | After (v0.2.0) |
|---|---|
| `import { Button } from "@whynot/design"; <Button variant="primary">…</Button>` | `import "@whynot/design"; <wn-button variant="primary">…</wn-button>` |
| `import { Tag } from "@whynot/design"; <Tag active>…</Tag>` | `<wn-tag active>…</wn-tag>` |
| `<StageDot level="S2" />` | `<wn-stage-dot level="S2"></wn-stage-dot>` |
CSS imports are unchanged; add the new `components.css` import alongside `colors_and_type.css`.
2026-05-23 16:34:14 +02:00
### Known caveats
- IBM Plex is loaded from Google Fonts. Drop `.woff2` files into `fonts/` and swap to a local `@font-face` for offline use.
2026-05-25 19:32:22 +02:00
- The showcase uses `importmap` + esm.sh to load Lit (no bundler). Real consumers using `pnpm add` will pick up Lit from `node_modules` via the package's `dependencies` entry.
- No TypeScript declarations for JSX yet — deferred until a TS consumer asks.
- `<wn-select>` uses a native `<select>` internally; richer custom selects (ElementInternals-based) will appear when a real need shows up.
## [0.1.0] — 2026-05-23
**Initial seed.** Established `whynot-design` as the implementation surface for the `whynot` visual language. (Pre-architectural reframe — see v0.2.0.)
### Added
- `src/styles/colors_and_type.css` — full token set + semantic element styles.
- `tokens/` — source-of-truth JSON tokens for colours, type, spacing, radii, shadows.
- `src/components/Atoms.jsx` — React: `Eyebrow`, `Tag`, `Button`, `StageDot`, `Stamp`, `Icon`.
- `src/components/Chrome.jsx` — React: `TopNav`, `Sidebar`, `PageHeader`, `PipelineStrip`.
- `examples/whynot-control/` — click-through UI kit recreating the `whynot-control` surface.
- `assets/whynot-logo.png` — LEGO-brick + `?!` mark.
- `SKILL.md`, `README.md`, `DesignSystemIntroduction.md`, `CONTRIBUTING.md`, `BOOTSTRAP.md`.