# Changelog All notable changes to `@whynot/design` are recorded here. Hand-edited until release cadence makes it painful. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning rules: see [`DesignSystemIntroduction.md` §6](./DesignSystemIntroduction.md#6-versioning-discipline). ## [Unreleased] ## [0.4.0] — 2026-06-28 ### Fixed - **Showcase page no longer wedges the renderer** (WHYNOT-WP-0002 T11). `` 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 1–4). 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. ## [0.3.0] — 2026-06-27 ### Added - **Technology-neutral IR + stack-adapter pipeline** (WHYNOT-WP-0002, Phase 0–3). The design language is now authored once in the canonical React designbook and projected one-way onto each stack: `React → designbook/ → ir/ → adapters//`. - `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`.** ### 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. ## [0.2.0] — 2026-05-25 **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. ### Added - `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`): ``, ``, ``, ``, ``, ``, ``. - **Form** (`form.js`): ``, ``, ``, ``, ``. - **Layout** (`layout.js`): ``, ``, `` + `` + ``, ``, `` + ``, ``, ``. - **Chrome** (`chrome.js`): ``, `` + `` + ``, ``, ``, ``. - `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"; ` | `import "@whynot/design"; ` | | `import { Tag } from "@whynot/design"; ` | `` | | `` | `` | CSS imports are unchanged; add the new `components.css` import alongside `colors_and_type.css`. ### Known caveats - IBM Plex is loaded from Google Fonts. Drop `.woff2` files into `fonts/` and swap to a local `@font-face` for offline use. - 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. - `` uses a native `