css-is-awesome 1.7.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -3
- package/CHANGELOG.md +21 -0
- package/CONTRACT.md +32 -13
- package/README.md +18 -17
- package/ROADMAP.md +28 -25
- package/THREE-TIERS.md +2 -2
- package/VERSIONING.md +53 -63
- package/css-is-awesome.instructions.md +2 -2
- package/package.json +1 -1
- package/public/theme.css +24 -15
- package/public/themes/boilerplate-dark/theme.css +8 -5
- package/public/themes/boilerplate-light/theme.css +8 -5
- package/public/themes/sketchbook-light/theme.css +8 -5
- package/scss/themes/boilerplate-dark.scss +8 -5
- package/scss/themes/boilerplate-light.scss +8 -5
- package/scss/themes/sketchbook-light.scss +8 -5
package/AGENTS.md
CHANGED
|
@@ -275,11 +275,11 @@ self-contained and needs no setup.
|
|
|
275
275
|
|
|
276
276
|
## Where to read deeper
|
|
277
277
|
|
|
278
|
-
Live docs site: **https://jerry2d3d.github.io/css-is-awesome
|
|
278
|
+
Live docs site: **https://cssisawesome.com** (mirror: https://jerry2d3d.github.io/css-is-awesome/) — mixin reference, recipes, theme authoring, MCP setup, mobile playbook.
|
|
279
279
|
|
|
280
280
|
Inside this package (all whitelisted in `files`):
|
|
281
281
|
|
|
282
|
-
- **`css-is-awesome.instructions.md`** — full authoring rules (~
|
|
282
|
+
- **`css-is-awesome.instructions.md`** — full authoring rules (~25 KB, Cursor/Copilot pick up via `applyTo: "**"` frontmatter)
|
|
283
283
|
- **`README.md`** — install, scripts, links
|
|
284
284
|
- **`THREE-TIERS.md`** — full tier explanation with examples
|
|
285
285
|
- **`THEMING.md`** — theme contract and dark-mode pattern
|
|
@@ -344,4 +344,4 @@ The markdown files above, the `cia` CLI, and the MCP server are the source of tr
|
|
|
344
344
|
|
|
345
345
|
---
|
|
346
346
|
|
|
347
|
-
If you're a human reading this and want full developer docs, start at `README.md` or the docs site: https://
|
|
347
|
+
If you're a human reading this and want full developer docs, start at `README.md` or the docs site: https://cssisawesome.com.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [1.8.1](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.8.0...v1.8.1) (2026-09-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **docs:** full documentation currency sweep - root markdown, site pages, three theme sources ([d64642a](https://github.com/Jerry2d3d/css-is-awesome/commit/d64642ab58c8dbeffb1c205df181115a9a5864d9))
|
|
7
|
+
* **mobile:** docs footer yields to the dock below lg ([65eb664](https://github.com/Jerry2d3d/css-is-awesome/commit/65eb66465a7c5c193bd4f6a0eb5c3b8296ebbbda))
|
|
8
|
+
* **site:** footer on the blog, themes, and docs routes ([1bd98b2](https://github.com/Jerry2d3d/css-is-awesome/commit/1bd98b2356b49a2b8da60abcd4a8d3222fd23c21))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **site:** GitHub and npm links in the landing nav ([b797625](https://github.com/Jerry2d3d/css-is-awesome/commit/b79762514844ad703c5894a7e32485a9d90b0753))
|
|
14
|
+
|
|
15
|
+
# [1.8.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.7.0...v1.8.0) (2026-09-04)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **site:** DataTable restacks into cards on phones ([b114156](https://github.com/Jerry2d3d/css-is-awesome/commit/b11415635c5fdd2f4bf56d44b612ff86d7b1d0c3))
|
|
21
|
+
|
|
1
22
|
# [1.7.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.6.2...v1.7.0) (2026-09-04)
|
|
2
23
|
|
|
3
24
|
|
package/CONTRACT.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Every theme declares these tokens. The [theme validator](./scripts/theme-validator.js) enforces completeness on every PR against the machine-readable companion at [`scripts/theme-contract.json`](./scripts/theme-contract.json).
|
|
4
4
|
|
|
5
5
|
- **Source of truth:** this document.
|
|
6
|
-
- **Reference implementation:** [`public/theme.css`](./public/theme.css) (Sketchbook).
|
|
6
|
+
- **Reference implementation:** [`public/themes/sketchbook/theme.css`](./public/themes/sketchbook/theme.css) (Sketchbook). (`public/theme.css` is the all-theme bundle.)
|
|
7
7
|
- **Validate a theme:** `node scripts/theme-validator.js <path-to-theme.css>`
|
|
8
8
|
- **Validate every theme in the repo:** `npm run validate-themes`
|
|
9
9
|
|
|
10
|
-
A theme file is a single
|
|
10
|
+
A theme file is a single token block plus (optionally) an `@import` for fonts — authored via `cia.theme()`, which emits it as `:root, :root[data-theme="<name>"]`. No component CSS lives in a theme file. Tokens only.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -18,7 +18,7 @@ Library mixins resolve every token through a `var(--token, fallback)` pattern, s
|
|
|
18
18
|
| Mixin call | Emitted CSS | Required token |
|
|
19
19
|
| -------------------------------- | ---------------------------------------- | -------------------- |
|
|
20
20
|
| `m.color(surface-default)` | `var(--surface-default, #fff)` | `--surface-default` |
|
|
21
|
-
| `m.space(
|
|
21
|
+
| `m.space(4)` | `var(--space-4, 1rem)` | `--space-4` |
|
|
22
22
|
| `m.radius(lg)` | `var(--radius-lg, 0.5rem)` | `--radius-lg` |
|
|
23
23
|
| `m.shadow(md)` | `var(--shadow-md, …)` | `--shadow-md` |
|
|
24
24
|
| `m.font-family(primary)` | `var(--font-primary, sans-serif)` | `--font-primary` |
|
|
@@ -218,14 +218,22 @@ These are the raw pigment tokens. Semantic aliases below reference them. In othe
|
|
|
218
218
|
|
|
219
219
|
## Space scale
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
| `--space-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
221
|
+
The **numbered scale is the source of truth and is contract-required**: a theme declares `--space-0` … `--space-9`, and `cia.space(N)` compiles to `var(--space-N)` — so a theme can re-proportion the page, not just recolor it.
|
|
222
|
+
|
|
223
|
+
| Token | Type | Example (default rhythm) | Purpose |
|
|
224
|
+
| --------------------------- | ------ | --------------------------------- | -------------------------------- |
|
|
225
|
+
| `--space-0` … `--space-9` | length | `0`, `0.25rem`, `0.5rem`, … `6rem` | The numbered scale — **required** |
|
|
226
|
+
|
|
227
|
+
The t-shirt names are **optional aliases**. The library emits `xs`–`xl` as `var()` references into the numbered scale, so they follow it automatically; `--space-2xs` sits outside the numbered scale and emits as a literal:
|
|
228
|
+
|
|
229
|
+
| Token | Type | Emitted as | Purpose |
|
|
230
|
+
| ------------- | ------ | ------------------ | --------------------------- |
|
|
231
|
+
| `--space-2xs` | length | `0.25rem` (literal) | Hairline gap / 2xs padding |
|
|
232
|
+
| `--space-xs` | length | `var(--space-1)` | Tight gap / xs padding |
|
|
233
|
+
| `--space-sm` | length | `var(--space-2)` | Compact gap / sm padding |
|
|
234
|
+
| `--space-md` | length | `var(--space-4)` | Default gap / md padding |
|
|
235
|
+
| `--space-lg` | length | `var(--space-5)` | Comfortable gap / lg padding |
|
|
236
|
+
| `--space-xl` | length | `var(--space-6)` | Section gap / xl padding |
|
|
229
237
|
|
|
230
238
|
---
|
|
231
239
|
|
|
@@ -425,9 +433,20 @@ onto `--paper` so the math reflects what users actually see.
|
|
|
425
433
|
| `--warning-text` on `--warning-subtle` | 4.5 : 1 | text |
|
|
426
434
|
| `--error-text` on `--error-subtle` | 4.5 : 1 | text |
|
|
427
435
|
| `--info-text` on `--info-subtle` | 4.5 : 1 | text |
|
|
428
|
-
| `--border-default` on `--paper` | 3.0 : 1 | non-text |
|
|
436
|
+
| `--border-default` on `--paper` | 3.0 : 1 | non-text (decorative — reported as info, never FAIL) |
|
|
429
437
|
| `--border-focus` on `--paper` | 3.0 : 1 | non-text |
|
|
430
438
|
| `--shu` on `--paper` | 3.0 : 1 | non-text |
|
|
439
|
+
| `--code-ink` on `--code-bg` | 4.5 : 1 | text |
|
|
440
|
+
| `--code-muted` on `--code-bg` | 4.5 : 1 | text |
|
|
441
|
+
| `--code-accent` on `--code-bg` | 4.5 : 1 | text |
|
|
442
|
+
| `--code-blue` on `--code-bg` | 4.5 : 1 | text |
|
|
443
|
+
| `--code-green` on `--code-bg` | 4.5 : 1 | text |
|
|
444
|
+
|
|
445
|
+
That's **22 audited pairs per theme**, the five `--code-*` pairs included —
|
|
446
|
+
syntax highlighting is body text, so it carries the full 4.5:1 requirement.
|
|
447
|
+
For dual-mode themes the audit evaluates **both** `light-dark()` branches and
|
|
448
|
+
keeps the worse result. `--border-default` is treated as decorative per WCAG
|
|
449
|
+
2.2 SC 1.4.11 and reports as info, not FAIL.
|
|
431
450
|
|
|
432
451
|
Each pair is reported as **PASS**, **WARN** (close to threshold; `--text-tertiary`
|
|
433
452
|
and `--ink-faint` warn when they pass the 3:1 large-text bar but fall below the
|
|
@@ -450,7 +469,7 @@ The contract is versioned via `scripts/theme-contract.json` (`version: "1"`).
|
|
|
450
469
|
- **Minor bump** (`"1" → "1.1"`): adds OPTIONAL tokens. Existing themes remain valid.
|
|
451
470
|
- **Major bump** (`"1" → "2"`): renames or removes REQUIRED tokens. Existing themes must migrate.
|
|
452
471
|
|
|
453
|
-
Any PR that adds a new `m.color(X)` / `m.space(X)` / `m.radius(X)` reference in the library must add `--X` to both this document and `scripts/theme-contract.json`, and add a declaration to every theme in `
|
|
472
|
+
Any PR that adds a new `m.color(X)` / `m.space(X)` / `m.radius(X)` reference in the library must add `--X` to both this document and `scripts/theme-contract.json`, and add a declaration to every theme source in `scss/themes/*.scss` (then `npm run build:css:themes` — the CSS under `public/` is generated, never hand-edited). The `npm run validate-themes` check in CI will block the merge otherwise.
|
|
454
473
|
|
|
455
474
|
---
|
|
456
475
|
|
package/README.md
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
**Bring your own selectors. We bring the design system.** One CSS file per theme — drop it in and the page restyles, no markup change. 24 themes. Zero JavaScript in the npm package. Six browser-native interactive components. Small enough to read in an afternoon.
|
|
8
8
|
|
|
9
|
-
**Docs:** [
|
|
9
|
+
**Docs:** [cssisawesome.com](https://cssisawesome.com/) · **Install:** `npm install css-is-awesome`
|
|
10
10
|
|
|
11
|
-
> **Shipped in 1.0.0:** a **recipes book** for building any component in any framework using cia mixins — five recipes today (`dialog`, `combobox`, `print-to-pdf`, `mobile-nav`, `bottom-nav`), with `datepicker`, `data-table` and `command-palette` queued. AI agents read recipes via MCP and generate components in your stack; humans read them at [`/docs/recipes`](https://
|
|
11
|
+
> **Shipped in 1.0.0:** a **recipes book** for building any component in any framework using cia mixins — five recipes today (`dialog`, `combobox`, `print-to-pdf`, `mobile-nav`, `bottom-nav`), with `datepicker`, `data-table` and `command-palette` queued. AI agents read recipes via MCP and generate components in your stack; humans read them at [`/docs/recipes`](https://cssisawesome.com/docs/recipes/).
|
|
12
12
|
|
|
13
13
|
## For AI agents — start here
|
|
14
14
|
|
|
@@ -33,7 +33,7 @@ npm install -D @modelcontextprotocol/sdk zod # required — npm will NOT insta
|
|
|
33
33
|
|
|
34
34
|
The SDK and `zod` are declared as *optional* peer dependencies, so a plain `npm install css-is-awesome` skips them and the server exits with `@modelcontextprotocol/sdk is not installed`. Install both. `npx css-is-awesome-mcp` does **not** work around this — npx fetches the package but not its optional peers.
|
|
35
35
|
|
|
36
|
-
Why it matters more here than for older frameworks: no model has memorised cia's API the way it has memorised Tailwind's class names. Without `llm.txt` or MCP, an agent will confidently invent a Tailwind-shaped API. With them, it reads the real thing. Details at [`/docs/mcp`](https://
|
|
36
|
+
Why it matters more here than for older frameworks: no model has memorised cia's API the way it has memorised Tailwind's class names. Without `llm.txt` or MCP, an agent will confidently invent a Tailwind-shaped API. With them, it reads the real thing. Details at [`/docs/mcp`](https://cssisawesome.com/docs/mcp/).
|
|
37
37
|
|
|
38
38
|
## Three ways to use it
|
|
39
39
|
|
|
@@ -59,7 +59,7 @@ npm install -D sass
|
|
|
59
59
|
<link rel="stylesheet" href="/cia/themes/boilerplate/theme.css">
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
Author your own class names; the mixin handles the styling. Mixins for buttons, forms, layout, typography, color, motion, plus the six zero-JS components: `accordion`, `modal`, `tooltip`, `dropdown`, `tabs`, `copy-button` — plus the mobile navigation family (`hamburger`, `drawer`, `sheet`, `dock`) and print-to-PDF via a pure-CSS `@media print` layer. Full reference at [`/docs/mixins`](https://
|
|
62
|
+
Author your own class names; the mixin handles the styling. Mixins for buttons, forms, layout, typography, color, motion, plus the six zero-JS components: `accordion`, `modal`, `tooltip`, `dropdown`, `tabs`, `copy-button` — plus the mobile navigation family (`hamburger`, `drawer`, `sheet`, `dock`) and print-to-PDF via a pure-CSS `@media print` layer. Full reference at [`/docs/mixins`](https://cssisawesome.com/docs/mixins/).
|
|
63
63
|
|
|
64
64
|
**Two imports, two jobs.** Emit the tokens once from your root/global stylesheet (`@use 'css-is-awesome';` or `<link>` a theme file), then import the **zero-emit authoring barrel** in each component stylesheet:
|
|
65
65
|
|
|
@@ -122,7 +122,7 @@ One line styles the whole site. Zero classes. Wrapped in `:where()` (specificity
|
|
|
122
122
|
<link rel="stylesheet" href="/themes/terminal-dark/theme.css" media="(prefers-color-scheme: dark)">
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Newspaper by day, hacker terminal by night. No JS, no mixin — pure browser behavior. Most design systems give you dark mode; cia lets you ship a second brand at night. See [`/docs/themes/pairing`](https://
|
|
125
|
+
Newspaper by day, hacker terminal by night. No JS, no mixin — pure browser behavior. Most design systems give you dark mode; cia lets you ship a second brand at night. See [`/docs/themes/pairing`](https://cssisawesome.com/docs/themes/pairing/).
|
|
126
126
|
|
|
127
127
|
Each theme is one file of CSS custom properties. Tokens only — no component rules. See `public/themes/<name>/theme.css` for the compiled output and `scss/themes/<name>.scss` for the sources. Full contract documented in [THEMING.md](./THEMING.md).
|
|
128
128
|
|
|
@@ -149,7 +149,7 @@ node scripts/theme-validator.js public/themes/midnight/theme.css
|
|
|
149
149
|
# <link rel="stylesheet" href="/themes/midnight/theme.css">
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
-
Full authoring walkthrough: [`/docs/authoring/themes`](https://
|
|
152
|
+
Full authoring walkthrough: [`/docs/authoring/themes`](https://cssisawesome.com/docs/authoring/themes/). The contract (127 required + 36 optional tokens) is at [`scripts/theme-contract.json`](./scripts/theme-contract.json).
|
|
153
153
|
|
|
154
154
|
## Token contract
|
|
155
155
|
|
|
@@ -204,9 +204,9 @@ cia ships **no component library** — deliberately. Interactive patterns arrive
|
|
|
204
204
|
|
|
205
205
|
**Shipped:** `dialog`, `combobox`, `print-to-pdf`, `mobile-nav`, `bottom-nav`. Queued next: `datepicker`, `data-table`, `command-palette`.
|
|
206
206
|
|
|
207
|
-
**Mobile navigation is system API, not an exercise for the reader.** Four mixins — `cia.hamburger`, `cia.drawer`, `cia.sheet`, `cia.dock` — cover both phone layouts: the **flex layout** (one fluid nav/main/footer shell that reshapes with the screen, hamburger opening a slide-in drawer — recipe [`mobile-nav`](./scss/recipes/mobile-nav.md)) and the **app layout** (a fixed bottom dock whose slots open slide-up sheets — recipe [`bottom-nav`](./scss/recipes/bottom-nav.md)). Zero JavaScript: everything rides CSS Grid and the native Popover API — the browser owns open state, `aria-expanded`, Esc and light dismiss. The docs site dogfoods the app layout on phones. The same doctrine extends to dropdowns: on phones an interactive surface takes the space it's in, so a `cia.dropdown` menu opens 1px under its full-width trigger at the trigger's exact width — CSS anchor positioning, flipping above when the screen bottom would clip it. The full spec is the [mobile playbook](https://
|
|
207
|
+
**Mobile navigation is system API, not an exercise for the reader.** Four mixins — `cia.hamburger`, `cia.drawer`, `cia.sheet`, `cia.dock` — cover both phone layouts: the **flex layout** (one fluid nav/main/footer shell that reshapes with the screen, hamburger opening a slide-in drawer — recipe [`mobile-nav`](./scss/recipes/mobile-nav.md)) and the **app layout** (a fixed bottom dock whose slots open slide-up sheets — recipe [`bottom-nav`](./scss/recipes/bottom-nav.md)). Zero JavaScript: everything rides CSS Grid and the native Popover API — the browser owns open state, `aria-expanded`, Esc and light dismiss. The docs site dogfoods the app layout on phones. The same doctrine extends to dropdowns: on phones an interactive surface takes the space it's in, so a `cia.dropdown` menu opens 1px under its full-width trigger at the trigger's exact width — CSS anchor positioning, flipping above when the screen bottom would clip it. The full spec is the [mobile playbook](https://cssisawesome.com/docs/mobile/).
|
|
208
208
|
|
|
209
|
-
Humans read them at [`/docs/recipes`](https://
|
|
209
|
+
Humans read them at [`/docs/recipes`](https://cssisawesome.com/docs/recipes/); AI agents pull them over MCP with `list_recipes` / `get_recipe`.
|
|
210
210
|
|
|
211
211
|
## Migrating from Tailwind or Bootstrap
|
|
212
212
|
|
|
@@ -217,7 +217,7 @@ npx cia migrate tailwind ./tailwind.config.js # auto-detects tailwind.config.*
|
|
|
217
217
|
npx cia migrate bootstrap ./scss/_variables.scss
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
Both accept `--help` for the full option list. Prose walkthroughs live at [`/docs/migration-tailwind`](https://
|
|
220
|
+
Both accept `--help` for the full option list. Prose walkthroughs live at [`/docs/migration-tailwind`](https://cssisawesome.com/docs/migration-tailwind/) and [`/docs/migration-bootstrap`](https://cssisawesome.com/docs/migration-bootstrap/).
|
|
221
221
|
|
|
222
222
|
## Print / PDF (zero JS)
|
|
223
223
|
|
|
@@ -256,7 +256,7 @@ The scope is kept narrow: 8 `!important` declarations, all inside `@media print`
|
|
|
256
256
|
|
|
257
257
|
## MCP server (for AI agents)
|
|
258
258
|
|
|
259
|
-
cia ships a Model Context Protocol stdio server (JSON-RPC over stdio, protocol `2024-11-05`) at [`mcp/server.cjs`](./mcp/server.cjs), exposed as the `css-is-awesome-mcp` bin. It's in the `files` manifest, so it lands in every consumer's `node_modules`. Any MCP-aware client (Claude Code, Cursor, Aider, Gemini, Copilot) can then query cia's real design system — mixin signatures, tokens, themes, recipes — instead of guessing, without grep-walking the repo. Exposes **30 tools** across 8 families (themes, mixins, functions, tokens · 127 required of them, animations, components, recipes, doc readers) plus `assemble_prompt` (context bundles) and `resolve_size` (snap design px values to cia's 4px grid). Full reference: [`/docs/mcp`](https://
|
|
259
|
+
cia ships a Model Context Protocol stdio server (JSON-RPC over stdio, protocol `2024-11-05`) at [`mcp/server.cjs`](./mcp/server.cjs), exposed as the `css-is-awesome-mcp` bin. It's in the `files` manifest, so it lands in every consumer's `node_modules`. Any MCP-aware client (Claude Code, Cursor, Aider, Gemini, Copilot) can then query cia's real design system — mixin signatures, tokens, themes, recipes — instead of guessing, without grep-walking the repo. Exposes **30 tools** across 8 families (themes, mixins, functions, tokens · 127 required of them, animations, components, recipes, doc readers) plus `assemble_prompt` (context bundles) and `resolve_size` (snap design px values to cia's 4px grid). Full reference: [`/docs/mcp`](https://cssisawesome.com/docs/mcp/).
|
|
260
260
|
|
|
261
261
|
**Setup is two steps — do both, or the server won't start.**
|
|
262
262
|
|
|
@@ -283,7 +283,7 @@ cia ships a Model Context Protocol stdio server (JSON-RPC over stdio, protocol `
|
|
|
283
283
|
|
|
284
284
|
## Docs site
|
|
285
285
|
|
|
286
|
-
The docs site is live at **https://jerry2d3d.github.io/css-is-awesome/**
|
|
286
|
+
The docs site is live at **https://cssisawesome.com** (production — Vercel, deployed from the `prod-css-is-awesome` branch), with a GitHub Pages mirror at **https://jerry2d3d.github.io/css-is-awesome/** that auto-deploys from `main`. To run it locally:
|
|
287
287
|
|
|
288
288
|
```bash
|
|
289
289
|
git clone https://github.com/Jerry2d3d/css-is-awesome.git
|
|
@@ -292,7 +292,7 @@ npm install
|
|
|
292
292
|
npm run dev # http://localhost:5173
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
The docs site is a Next.js
|
|
295
|
+
The docs site is a Next.js 16 app at `src/` that dogfoods the library — every page uses CSS Modules composed from the same tokens and mixins the library ships.
|
|
296
296
|
|
|
297
297
|
## Scripts
|
|
298
298
|
|
|
@@ -317,7 +317,7 @@ The docs site is a Next.js 15 app at `src/` that dogfoods the library — every
|
|
|
317
317
|
|
|
318
318
|
## Testing
|
|
319
319
|
|
|
320
|
-
|
|
320
|
+
Twelve checks, all gated in CI on every PR. Each one exists because the failure it catches actually happened.
|
|
321
321
|
|
|
322
322
|
| Check | What it proves |
|
|
323
323
|
|---|---|
|
|
@@ -327,11 +327,12 @@ Eleven checks, all gated in CI on every PR. Each one exists because the failure
|
|
|
327
327
|
| `validate-icons` | the 49-glyph core pack is intact (extras allowed) |
|
|
328
328
|
| `validate-api` | the `/api` barrel still emits zero CSS until a mixin is called |
|
|
329
329
|
| `validate-package` | packs → installs into a temp project → compiles all **10** documented `@use` specifiers |
|
|
330
|
-
| `coverage:api` | calls **
|
|
330
|
+
| `coverage:api` | calls **183/183** public mixins + functions and asserts the output |
|
|
331
331
|
| `coverage:mcp` | calls **30/30** MCP tools over stdio |
|
|
332
|
-
| `
|
|
332
|
+
| `validate-recipes` | every recipe's SCSS compiles and its documented mixin calls resolve |
|
|
333
|
+
| `test` | Playwright — route smoke, axe a11y, per-theme visual snapshots, theme-editor behaviour, across three engines |
|
|
333
334
|
|
|
334
|
-
**Call-and-assert coverage.** SCSS has no line-coverage tooling, so cia measures whether every part of the public API is actually callable: parse every public `@mixin`/`@function`, generate a fixture that calls it, compile, and assert it works — no `null` leaking into CSS, functions return a value, mixins emit. **
|
|
335
|
+
**Call-and-assert coverage.** SCSS has no line-coverage tooling, so cia measures whether every part of the public API is actually callable: parse every public `@mixin`/`@function`, generate a fixture that calls it, compile, and assert it works — no `null` leaking into CSS, functions return a value, mixins emit. **183/183 SCSS units and 30/30 MCP tools**, with CI failing below 98%. A unit with no fixture counts as uncovered, so skipping a test lowers the number rather than hiding.
|
|
335
336
|
|
|
336
337
|
**What 100% means here:** every public mixin and function is invoked and produces sane output. It catches renames, broken signatures and undefined variables — it found one on its first run, an undefined `$icon-size` that broke four icon mixins. It does **not** prove the CSS is visually correct; that's a deliberate trade against golden-file snapshots, which would churn dozens of files on any token change. Page-level visual correctness is covered by the Playwright snapshots instead.
|
|
337
338
|
|
|
@@ -339,7 +340,7 @@ Eleven checks, all gated in CI on every PR. Each one exists because the failure
|
|
|
339
340
|
|
|
340
341
|
**Known gaps**, stated plainly: **a11y runs on routes, not component states** — axe checks a set of pages; individual component states are not swept. (Cross-engine coverage used to be the gap here; the suite now runs chromium, firefox and webkit, which matters because cia leans on `light-dark()`, `:has()`, `[popover]` and `mask`.)
|
|
341
342
|
|
|
342
|
-
Full detail: [`/docs/testing`](https://
|
|
343
|
+
Full detail: [`/docs/testing`](https://cssisawesome.com/docs/testing/).
|
|
343
344
|
|
|
344
345
|
## Size (gzipped)
|
|
345
346
|
|
package/ROADMAP.md
CHANGED
|
@@ -138,7 +138,7 @@ Shared chrome + reusable building blocks now live in `src/components/`:
|
|
|
138
138
|
- [ ] Sections: Tokens (color/spacing/type grids — DONE), Utilities (searchable table — TODO), Mixins API (TODO), Migration from Bootstrap (started; needs polish).
|
|
139
139
|
- [x] Live color swatches, spacing visualizers, type scale preview — `/docs/tokens` reads `getComputedStyle` after mount and re-resolves on theme swap via `useThemeAttribute`.
|
|
140
140
|
- [x] Copy-to-clipboard code snippets — every `<Example.Code>` has a Copy button (CopyButton client island, secure-context fallback to execCommand).
|
|
141
|
-
- [
|
|
141
|
+
- [x] Deploy to the external host + link from README — done: GitHub Pages mirror live and linked, and production at https://cssisawesome.com on Vercel since 2026-09-04 (deploys from the `prod-css-is-awesome` branch).
|
|
142
142
|
|
|
143
143
|
### New pages
|
|
144
144
|
- [x] **`/themes` gallery** — all 6 themes with live-swap preview + download per tile. Uses `ThemeTile` component. (Now at `/themes/gallery`; `/themes` is the editor.)
|
|
@@ -265,9 +265,10 @@ out-of-date copy that contradicts the rest of the site. Fix the
|
|
|
265
265
|
content before doing any CSS work on these files so the dogfood
|
|
266
266
|
pass doesn't restyle copy that's about to be replaced.
|
|
267
267
|
|
|
268
|
-
**`/blog`** —
|
|
269
|
-
|
|
270
|
-
|
|
268
|
+
**`/blog`** — *Resolved 2026-08-17: a real markdown-driven `/blog` +
|
|
269
|
+
`/blog/[slug]` shipped with 7 posts written from the commit history
|
|
270
|
+
(see Phase 5.95) — effectively Path A, all seven.* Original decision
|
|
271
|
+
for the record:
|
|
271
272
|
- [ ] **Path A — Ship a subset for real.** Pick 2-3 of the 7 drafted
|
|
272
273
|
topics ("Why the overflow stays", "Five voices, one system",
|
|
273
274
|
"Planning a CLI and an MCP server" are the strongest hooks) and
|
|
@@ -341,7 +342,7 @@ docs-site quality only.
|
|
|
341
342
|
|
|
342
343
|
## Phase 5.95 — Post-1.0 hardening (2026-08-17 → 08-18)
|
|
343
344
|
|
|
344
|
-
**v1.0.0 was cut 2026-08-17** (`253610a`, tagged) at 24 of 42 stories, deliberately: no external users yet, so the SemVer commitment cost nothing. **
|
|
345
|
+
**v1.0.0 was cut 2026-08-17** (`253610a`, tagged) at 24 of 42 stories, deliberately: no external users yet, so the SemVer commitment cost nothing. **First published to npm 2026-09-01**; semantic-release has cut every version since (the current one is always the `version` field of `package.json` — never hand-type it).
|
|
345
346
|
|
|
346
347
|
What the cut surfaced, in the order it hurt:
|
|
347
348
|
|
|
@@ -353,7 +354,7 @@ What the cut surfaced, in the order it hurt:
|
|
|
353
354
|
- [x] **Visual baselines stale since 2026-05-03**, keeping CI red. Keyed by `{platform}`, win32 set regenerated. **Linux set still needs one manual run of the "Update visual snapshots" workflow.**
|
|
354
355
|
- [x] Release friction: `pack:consumer` collapses the three-step pack → re-pin → install dance into one command.
|
|
355
356
|
|
|
356
|
-
**Still open:**
|
|
357
|
+
**Still open:** run the snapshot workflow once to create the linux baseline set; the remaining v1.0 stories (Playground is 0/7). ~~Publish to npm~~ — done 2026-09-01.
|
|
357
358
|
|
|
358
359
|
---
|
|
359
360
|
|
|
@@ -361,6 +362,8 @@ What the cut surfaced, in the order it hurt:
|
|
|
361
362
|
|
|
362
363
|
**Locked 2026-05-23** after long architecture synthesis (panel review + Gemini external read + Jerry instinct refinement).
|
|
363
364
|
|
|
365
|
+
> **Status 2026-09-04:** v1.0.0 cut 2026-08-17, first npm publish 2026-09-01; releases continue via semantic-release. The sprint checklist below is preserved as written — unchecked items are genuinely still open (see the "Definition of the best" list for per-item status).
|
|
366
|
+
|
|
364
367
|
**Goal:** Ship v1.0 as a humans-first design system whose AI-friendliness is the bonus. Five tracks, ~42 user stories, ~18-26 working days.
|
|
365
368
|
|
|
366
369
|
### Priority ladder (the v1.0 pitch order)
|
|
@@ -412,11 +415,11 @@ See [`roadmap/epics/v1-0/post-v1-ideas.md`](./roadmap/epics/v1-0/post-v1-ideas.m
|
|
|
412
415
|
|
|
413
416
|
### Definition of "the best out there" after this sprint
|
|
414
417
|
|
|
415
|
-
- [
|
|
416
|
-
- [ ] 11+ recipes shipped across overlay / input / data / navigation / feedback
|
|
418
|
+
- [x] Migration CLI handles real Tailwind + Bootstrap configs end-to-end (`npx cia migrate` shipped)
|
|
419
|
+
- [ ] 11+ recipes shipped across overlay / input / data / navigation / feedback (5 shipped as of 2026-09-04: dialog, combobox, print-to-pdf, mobile-nav, bottom-nav)
|
|
417
420
|
- [ ] `/playground` functional in-browser; every recipe page links to a starter URL
|
|
418
421
|
- [ ] Inline contrast validator runs live in the theme editor
|
|
419
|
-
- [
|
|
422
|
+
- [x] Blog shipped for real — markdown-driven `/blog` with 7 posts written from the commit history (2026-08-17)
|
|
420
423
|
- [ ] boilerplate-slim ships React + Angular + HTML (34 each)
|
|
421
424
|
- [ ] `/showcase` rebuilt + `/docs/migrate-from-shadcn` guide published
|
|
422
425
|
- [ ] Boiler dogfoods cia + ≥5 external testers have built something real
|
|
@@ -483,7 +486,7 @@ The original Phase 6 ("Ecosystem v1.1+") below describes legacy items some of wh
|
|
|
483
486
|
- [x] GitHub Action: CI (build + lint), Release (semver + npm publish + changelog) — semantic-release wired up since v0.7.
|
|
484
487
|
- [x] Badge suite in README (npm version, license, semantic-release) — shipped.
|
|
485
488
|
- [x] Contribution guide + issue templates — `CONTRIBUTING.md` + `CONTRIBUTING-THEMES.md` shipped.
|
|
486
|
-
- [
|
|
489
|
+
- [x] TypeScript token definitions (`tokens.d.ts`) — shipped; generated from the contract via `npm run build:token-types`, exported as `css-is-awesome/tokens.d.ts`
|
|
487
490
|
- [ ] PostCSS plugin for tree-shaking unused utilities
|
|
488
491
|
- [ ] Starter templates: plain HTML, Vite, Next.js, Astro
|
|
489
492
|
- [ ] Storybook or Ladle instance — lives in Gremlin UI's repo, not here (see Phase 8).
|
|
@@ -494,11 +497,11 @@ The original Phase 6 ("Ecosystem v1.1+") below describes legacy items some of wh
|
|
|
494
497
|
|
|
495
498
|
**Goal:** Move from "another design system" to "the obvious choice for SCSS-first teams who want zero-JS theming." Items from the Gemini critique that widen the moat once the foundations are stable.
|
|
496
499
|
|
|
497
|
-
- [
|
|
500
|
+
- [x] **Zero-JS interactive components** — shipped in v0.8/v1.0: accordion, modal, tooltip, dropdown, tabs, copy-button on `<details name>`, `<dialog>`, `[popover]`, radio + `:has()`; plus the mobile navigation family (hamburger / drawer / sheet / dock, 2026-08). Biggest moat vs shadcn — they need a runtime, we don't.
|
|
498
501
|
- [x] **A11y linter inside `theme-validator.js`** — WCAG 2.2 AA contrast checks on 17 token pairs per theme. **FAIL-by-default as of v0.7** (commit `4e1bbf1`, 2026-05-11) after triaging every theme; zero FAILs across all 22 theme blocks. `--allow-a11y-fail` opts out; `--strict` is retained as a no-op alias for backwards compat. `--border-default` is treated as decorative (informational only) per WCAG 2.2 SC 1.4.11.
|
|
499
|
-
- [
|
|
500
|
-
- [
|
|
501
|
-
- [
|
|
502
|
+
- [x] **SCSS↔TS token bridge** — shipped: `npm run build:token-types` generates `dist/tokens.d.ts` from the contract.
|
|
503
|
+
- [x] **Intrinsic layout mixins** — shipped in the v1.0 surface: `stack` / `cluster` / `switcher` / `sidebar` as first-class mixins.
|
|
504
|
+
- [x] **Tailwind→Awesome migration CLI** — shipped as `npx cia migrate tailwind` (config-level conversion into a cia theme; the class-string-scanning variant described here was not built).
|
|
502
505
|
- [ ] **Component depth audit** — catalog gaps vs Bootstrap (modal, toast, popover, tooltip, accordion, breadcrumb, pagination, badge, avatar, dropdown, offcanvas) and prioritize zero-JS implementations.
|
|
503
506
|
|
|
504
507
|
---
|
|
@@ -541,9 +544,9 @@ Naming "Gremlin UI" / "Gremlin Components" / "Companion Boilerplate" — all ret
|
|
|
541
544
|
|
|
542
545
|
1. ~~**Utility naming:** stay close to Bootstrap (`.p-3`) or Tailwind-like (`.p-md`)?~~ **Decided:** Tailwind-style (`.cia-p-md`) with `cia-` prefix.
|
|
543
546
|
2. ~~**Namespace:** should utilities be prefixed?~~ **Decided:** yes, `cia-` on everything.
|
|
544
|
-
3.
|
|
545
|
-
4. **Browser support target:** modern evergreen only, or include a legacy build? Still open.
|
|
546
|
-
5.
|
|
547
|
+
3. ~~**Default CSS output:** include utilities by default or opt-in?~~ **Decided (v0.8):** opt-in on the Sass path (`$utilities: true`); pre-built CDN bundles still ship every utility.
|
|
548
|
+
4. **Browser support target:** modern evergreen only, or include a legacy build? Still open (in practice: modern evergreen — the system leans on `light-dark()`, `:has()`, `[popover]`).
|
|
549
|
+
5. ~~**Sizing scale:** refactor `xs/sm/md/lg/xl/2xl/3xl/4xl` → numbered `1–9` with aliases?~~ **Decided (locked 2026-05-04):** numbered scale is the source of truth; t-shirt names are optional aliases.
|
|
547
550
|
|
|
548
551
|
---
|
|
549
552
|
|
|
@@ -567,12 +570,12 @@ Items 1-13, 15, 16, the a11y linter triage, and the theme-editor import round-tr
|
|
|
567
570
|
19. ~~A11y linter triage~~ — done 2026-05-11 (commit `4e1bbf1`). Zero FAILs across all 22 theme blocks. `--border-default` reclassified as decorative (info status) per WCAG 2.2 SC 1.4.11. Validator now FAILs by default; `--allow-a11y-fail` opts out; `--strict` retained as a no-op alias.
|
|
568
571
|
20. ~~Theme-editor import~~ — upload `.css` to keep editing landed 2026-05-12 (uncommitted on `main`; round-trips a previously-downloaded theme file).
|
|
569
572
|
|
|
570
|
-
### Open / next up — Phase 5
|
|
573
|
+
### Open / next up — Phase 5 was the live gate (since resolved)
|
|
571
574
|
|
|
572
|
-
**Phase 5 (publish v0.7)
|
|
575
|
+
**Phase 5 (publish v0.7) was the correct next step at the time.** A11y is at zero FAILs, validator is FAIL-by-default, tarball is clean, boilerplate theme + Lucide icons ship, theme editor round-trips. Only the publish command itself + a downstream smoke install remain.
|
|
573
576
|
|
|
574
|
-
8.
|
|
575
|
-
9.
|
|
577
|
+
8. ~~**`npm publish`**~~ — done. The package shipped via semantic-release through the 0.7/0.8 line; the 1.x line first published to the public registry 2026-09-01.
|
|
578
|
+
9. ~~**Boilerplate consumer install**~~ — done. boiler-project-ai consumes cia (all components + app pages migrated to the `cia` import, 2026-07-11).
|
|
576
579
|
|
|
577
580
|
### After v0.7 ships
|
|
578
581
|
|
|
@@ -583,9 +586,9 @@ Items 1-13, 15, 16, the a11y linter triage, and the theme-editor import round-tr
|
|
|
583
586
|
|
|
584
587
|
### Smaller items still on the board
|
|
585
588
|
|
|
586
|
-
-
|
|
587
|
-
-
|
|
588
|
-
-
|
|
589
|
+
- ~~**Utilities searchable table** at `/docs/utilities`~~ — shipped (route live on the docs site).
|
|
590
|
+
- ~~**Mixins API reference** at `/docs/mixins`~~ — shipped (README links it as the full reference).
|
|
591
|
+
- ~~**README homepage URL** + Pages-deploy verification~~ — done; Pages mirror + cssisawesome.com production both live.
|
|
589
592
|
- **Icon index page** listing every glyph in every pack.
|
|
590
593
|
- **Pull Sketchbook docs-flourishes** (seal, draft stamp, brush rules) out of any future "base system" port.
|
|
591
594
|
|
|
@@ -599,7 +602,7 @@ Items 1-13, 15, 16, the a11y linter triage, and the theme-editor import round-tr
|
|
|
599
602
|
|
|
600
603
|
All of the following must be true before Season 1 production begins:
|
|
601
604
|
|
|
602
|
-
- [
|
|
605
|
+
- [x] cia published to npm (first publish 2026-09-01; 1.x line live)
|
|
603
606
|
- [ ] All v1.0 epic acceptance criteria met (42 stories shipped or explicitly punted)
|
|
604
607
|
- [ ] No planned mixin renames or API changes within the next 6 months
|
|
605
608
|
- [ ] Recipes book stable — at least 11 recipes shipped and not changing
|
package/THREE-TIERS.md
CHANGED
|
@@ -9,8 +9,8 @@ css-is-awesome ships three authoring surfaces for the same components. Pick the
|
|
|
9
9
|
## Tier 1 — Drop-in CSS + HTML (no build)
|
|
10
10
|
|
|
11
11
|
```html
|
|
12
|
+
<link rel="stylesheet" href="themes/sketchbook/theme.css">
|
|
12
13
|
<link rel="stylesheet" href="css-is-awesome.min.css">
|
|
13
|
-
<link rel="stylesheet" href="theme-sketchbook.css">
|
|
14
14
|
|
|
15
15
|
<main class="cia-container">
|
|
16
16
|
<h1>Welcome</h1>
|
|
@@ -100,7 +100,7 @@ The split to hold in your head: **cia owns the system values — colour, spacing
|
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
**Audience:** content-heavy sites, blog posts, READMEs rendered as HTML, anywhere the author doesn't want to think about classes.
|
|
103
|
-
**Rules:** zero classes required. The recipe styles every common bare tag
|
|
103
|
+
**Rules:** zero classes required. The recipe styles every common bare tag wrapped in `:where()` (specificity `0,0,0`) — no `@layer`. Any selector you add — even another bare tag — wins automatically.
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
package/VERSIONING.md
CHANGED
|
@@ -9,7 +9,7 @@ How `css-is-awesome` versions its public surfaces, deprecates old APIs, and reco
|
|
|
9
9
|
| Surface | Lives in | Consumed as |
|
|
10
10
|
| ------------------- | ------------------------------------------ | ------------------------------------------ |
|
|
11
11
|
| CSS class names | `dist/*.css` | HTML / SCSS / React class strings |
|
|
12
|
-
| SCSS mixin API | `scss/` (`_mixins.scss`, `_layout.scss`, …) | Authors who `@use
|
|
12
|
+
| SCSS mixin API | `scss/` (`_mixins.scss`, `_layout.scss`, …) | Authors who `@use 'css-is-awesome'` / `@use 'css-is-awesome/api'` |
|
|
13
13
|
| Token contract | [`CONTRACT.md`](./CONTRACT.md) + [`scripts/theme-contract.json`](./scripts/theme-contract.json) | Themes declared in a `:root { … }` block |
|
|
14
14
|
|
|
15
15
|
The **library version** lives in [`package.json`](./package.json). The **contract version** lives in the `version` field of `scripts/theme-contract.json`. They move together on most MAJOR bumps but are independent: a library MINOR can ship without bumping the contract.
|
|
@@ -31,8 +31,7 @@ Any change that can break a consumer upgrading blindly.
|
|
|
31
31
|
| SCSS mixin default changes rendered output | `m.card()` default radius flips from `md` → `lg` |
|
|
32
32
|
| Contract: required token renamed or removed | `--surface-default` → `--surface-base` |
|
|
33
33
|
| Contract: `version` field bumps to a new major (`"1"` → `"2"`) | Required-token removal in `scripts/theme-contract.json` |
|
|
34
|
-
|
|
|
35
|
-
| Peer-dependency floor rises | `react: >=18` → `react: >=19` |
|
|
34
|
+
| Optional-peer floor rises | `@modelcontextprotocol/sdk` minimum raised |
|
|
36
35
|
|
|
37
36
|
### MINOR — `0.x.0`
|
|
38
37
|
|
|
@@ -43,8 +42,7 @@ Additive, non-breaking changes.
|
|
|
43
42
|
| New public CSS class | `.cia-grid-auto-fit` added |
|
|
44
43
|
| New public SCSS mixin | `m.cluster($gap)` added |
|
|
45
44
|
| New optional token added to contract (`"1"` → `"1.1"`) | `--dropdown-offset-y` added to component section |
|
|
46
|
-
| New
|
|
47
|
-
| Additive component prop with a sensible default | `<Button loading>` added, defaults to `false` |
|
|
45
|
+
| New theme or recipe shipped | `prism` family added; `mobile-nav` recipe added |
|
|
48
46
|
| New utility class (`.cia-*`) | `.cia-text-balance` added |
|
|
49
47
|
|
|
50
48
|
### PATCH — `0.0.x`
|
|
@@ -61,14 +59,14 @@ Internal-only or visually-identical changes.
|
|
|
61
59
|
|
|
62
60
|
---
|
|
63
61
|
|
|
64
|
-
## 2. Pre-1.0 rules
|
|
62
|
+
## 2. Pre-1.0 rules (historical)
|
|
65
63
|
|
|
66
|
-
While the library
|
|
64
|
+
While the library was pre-1.0 (`0.x.x`), the rules above applied with one carve-out: we reserved the right to ship a genuinely-breaking change as a **MINOR** bump when it was the right call for the system's long-term shape (the v0.7 theme renames and the v0.8 mixin-first reframe both used it). Every such change was:
|
|
67
65
|
|
|
68
|
-
1. Called out loudly in the `CHANGELOG.md` entry
|
|
66
|
+
1. Called out loudly in the `CHANGELOG.md` entry with a **BREAKING** prefix.
|
|
69
67
|
2. Called out again in the release notes with a migration snippet.
|
|
70
68
|
|
|
71
|
-
**`1.0.0`
|
|
69
|
+
**`1.0.0` locked the contract** (cut 2026-08-17). Breaking changes now require a MAJOR bump, no exceptions.
|
|
72
70
|
|
|
73
71
|
---
|
|
74
72
|
|
|
@@ -80,9 +78,8 @@ Every public symbol — CSS class, SCSS mixin, React prop, contract token — fo
|
|
|
80
78
|
|
|
81
79
|
1. **Mark** the symbol with an inline `@deprecated` comment citing the replacement and the intended removal version.
|
|
82
80
|
2. **Warn** at use-time:
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
- CSS classes / tokens → no runtime warning possible; rely on the `@deprecated` JSDoc and changelog.
|
|
81
|
+
- SCSS mixins → `@warn "m.old-name is deprecated, use m.new-name (removed in 2.0)";`.
|
|
82
|
+
- CSS classes / tokens → no runtime warning possible; rely on the `@deprecated` comment and changelog.
|
|
86
83
|
3. **Announce** in the next MINOR release's `CHANGELOG.md` under `### Deprecated`.
|
|
87
84
|
4. **Keep functional** for **at least one full MINOR release cycle** after the deprecation lands.
|
|
88
85
|
5. **Remove** only in a MAJOR bump.
|
|
@@ -92,9 +89,9 @@ Every public symbol — CSS class, SCSS mixin, React prop, contract token — fo
|
|
|
92
89
|
```scss
|
|
93
90
|
// scss/_mixins.scss
|
|
94
91
|
/// @deprecated Use `m.btn-primary` with `$bg: action-secondary-default` override.
|
|
95
|
-
/// Removed in
|
|
92
|
+
/// Removed in 2.0.
|
|
96
93
|
@mixin btn-secondary($size: md) {
|
|
97
|
-
@warn "m.btn-secondary is deprecated; use m.btn-primary with $bg: action-secondary-default. Removed in
|
|
94
|
+
@warn "m.btn-secondary is deprecated; use m.btn-primary with $bg: action-secondary-default. Removed in 2.0.";
|
|
98
95
|
@include btn-primary($size, $bg: action-secondary-default);
|
|
99
96
|
}
|
|
100
97
|
```
|
|
@@ -112,70 +109,63 @@ A deprecated contract token:
|
|
|
112
109
|
|
|
113
110
|
## 4. Changelog format
|
|
114
111
|
|
|
115
|
-
|
|
112
|
+
**[`CHANGELOG.md`](./CHANGELOG.md) is GENERATED — never edit it by hand.** [semantic-release](https://github.com/semantic-release/semantic-release) writes each release entry from the Conventional Commits that landed since the previous tag, grouped under the conventional-changelog headings:
|
|
116
113
|
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
119
|
-
- `
|
|
120
|
-
- `Removed` — removed features.
|
|
121
|
-
- `Fixed` — bug fixes.
|
|
122
|
-
- `Security` — vulnerabilities and mitigations.
|
|
114
|
+
- `Features` — from `feat:` commits.
|
|
115
|
+
- `Bug Fixes` — from `fix:` commits.
|
|
116
|
+
- `Performance Improvements` — from `perf:` commits.
|
|
123
117
|
|
|
124
|
-
|
|
118
|
+
**Version pace — the number belongs to the PACKAGE, not the website.**
|
|
119
|
+
The docs site lives in this repo but ships nowhere in the npm tarball, so
|
|
120
|
+
site-only work must not spend minor versions. The rules (enforced by a
|
|
121
|
+
`releaseRules` override in `.releaserc.json`, adopted 2026-09-04 after
|
|
122
|
+
site `feat` commits marched 1.1 → 1.8 in a week):
|
|
125
123
|
|
|
126
|
-
|
|
124
|
+
- Library API work (new/changed mixins, tokens, recipes, packaged docs) —
|
|
125
|
+
normal Conventional Commits semantics: `feat` → minor, `fix` → patch.
|
|
126
|
+
- Site-only work — scope it `(site)` or `(docs-site)`: `feat(site)` is
|
|
127
|
+
demoted to a **patch**, `fix(site)` patches, `chore`/`docs` don't
|
|
128
|
+
release at all. Prefer `chore(site)` when nothing packaged changed and
|
|
129
|
+
no npm release is needed — production deploys come from the
|
|
130
|
+
`prod-css-is-awesome` branch, not from npm.
|
|
131
|
+
- MAJOR (2.0.0) is reserved for real breaking changes to the public
|
|
132
|
+
surfaces above — nothing else may reach it.
|
|
133
|
+
- `BREAKING CHANGES` — from `feat!:` / `fix!:` or a `BREAKING CHANGE:` footer.
|
|
127
134
|
|
|
128
|
-
|
|
129
|
-
## [0.6.0] - 2026-05-12
|
|
130
|
-
|
|
131
|
-
### Added
|
|
132
|
-
- `<DataTable>` component with generic row typing and optional pagination (#142).
|
|
133
|
-
- Theme validator now supports `--watch` mode (#138).
|
|
134
|
-
|
|
135
|
-
### Changed
|
|
136
|
-
- `Pagination` props: native `HTMLAttributes.onChange` is `Omit`ped so the custom `onChange(page)` stops colliding. Non-breaking for existing consumers (#140).
|
|
137
|
-
|
|
138
|
-
### Deprecated
|
|
139
|
-
- `m.btn-secondary` — use `m.btn-primary` with `$bg: action-secondary-default` override. Removed in 1.0 (#143).
|
|
140
|
-
|
|
141
|
-
### Fixed
|
|
142
|
-
- Theme picker no longer injected duplicate `<link>` elements on first paint (#145).
|
|
143
|
-
```
|
|
135
|
+
Each entry links the commit (and any referenced issue / PR numbers) automatically. There is no hand-maintained `Unreleased` section — in-flight changes are simply the commits on `main` that no tag covers yet.
|
|
144
136
|
|
|
145
137
|
---
|
|
146
138
|
|
|
147
|
-
## 5. Conventional Commits →
|
|
139
|
+
## 5. Conventional Commits → Release
|
|
148
140
|
|
|
149
|
-
Commits follow [Conventional Commits](https://www.conventionalcommits.org/). The prefix
|
|
141
|
+
Commits follow [Conventional Commits](https://www.conventionalcommits.org/). The prefix decides both the version bump and the changelog section:
|
|
150
142
|
|
|
151
|
-
| Commit prefix | Changelog section
|
|
152
|
-
| ----------------------------------------- |
|
|
153
|
-
| `feat:` | `
|
|
154
|
-
| `feat!:` or `BREAKING CHANGE:` footer | `
|
|
155
|
-
| `fix:` | `
|
|
156
|
-
| `perf:` | `
|
|
157
|
-
| `docs:` | *omit*
|
|
158
|
-
| `refactor:` | *omit*
|
|
159
|
-
| `test:` | *omit*
|
|
160
|
-
| `chore:` | *omit*
|
|
161
|
-
| `build:` / `ci:` | *omit*
|
|
143
|
+
| Commit prefix | Bump | Changelog section |
|
|
144
|
+
| ----------------------------------------- | ------- | -------------------------- |
|
|
145
|
+
| `feat:` | MINOR | `Features` |
|
|
146
|
+
| `feat!:` or `BREAKING CHANGE:` footer | MAJOR | `BREAKING CHANGES` |
|
|
147
|
+
| `fix:` | PATCH | `Bug Fixes` |
|
|
148
|
+
| `perf:` | PATCH | `Performance Improvements` |
|
|
149
|
+
| `docs:` | *no release* | *omit* |
|
|
150
|
+
| `refactor:` | *no release* | *omit* |
|
|
151
|
+
| `test:` | *no release* | *omit* |
|
|
152
|
+
| `chore:` | *no release* | *omit* |
|
|
153
|
+
| `build:` / `ci:` | *no release* | *omit* |
|
|
162
154
|
|
|
163
|
-
|
|
155
|
+
Deprecations are announced in the deprecating commit's body (and land in the release notes through it), plus an inline `@deprecated` comment per §3.
|
|
164
156
|
|
|
165
157
|
---
|
|
166
158
|
|
|
167
159
|
## 6. Release process
|
|
168
160
|
|
|
169
|
-
The policy in this document tells you **what** a version number means. The mechanics
|
|
161
|
+
The policy in this document tells you **what** a version number means. The mechanics are automated: on every push to `main` that contains a releasable commit, semantic-release computes the next version from the commit messages, regenerates `CHANGELOG.md`, builds the bundles (`prepublishOnly` runs `build:css:all`), tags `vX.Y.Z`, and publishes to npm. Nobody hand-types a version number anywhere — the hero, the MCP server, and the docs all read it from `package.json`.
|
|
162
|
+
|
|
163
|
+
What remains manual:
|
|
170
164
|
|
|
171
|
-
|
|
165
|
+
1. Bumping `version` in `scripts/theme-contract.json` when the contract itself changes (§7).
|
|
166
|
+
2. The CI gates (lint, validators, coverage, size budget, Playwright) — a red PR never reaches `main`, so a release is never cut from a failing tree.
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
2. Bumps `version` in `package.json` per the rules in §1.
|
|
175
|
-
3. Bumps `version` in `scripts/theme-contract.json` if the contract changed.
|
|
176
|
-
4. Runs `npm run validate-themes` — must pass.
|
|
177
|
-
5. Rebuilds `dist/*.css` via `npm run build:css:all`.
|
|
178
|
-
6. Tags the commit `vX.Y.Z` and pushes.
|
|
168
|
+
Contributor-facing workflow detail lives in [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
179
169
|
|
|
180
170
|
---
|
|
181
171
|
|
|
@@ -185,7 +175,7 @@ Two version numbers, two files:
|
|
|
185
175
|
|
|
186
176
|
| Version | Source | Bumps on |
|
|
187
177
|
| ------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
188
|
-
| Library version | `version` field of [`package.json`](./package.json) | Any change to CSS / SCSS /
|
|
178
|
+
| Library version | `version` field of [`package.json`](./package.json) | Any change to the CSS / SCSS / contract public surfaces per §1. |
|
|
189
179
|
| Contract version | `version` field of [`scripts/theme-contract.json`](./scripts/theme-contract.json) | Contract-only changes (new optional token → minor; required token renamed or removed → major). |
|
|
190
180
|
|
|
191
181
|
They usually move together on a library MAJOR. They move independently on MINOR and PATCH.
|
|
@@ -197,4 +187,4 @@ They usually move together on a library MAJOR. They move independently on MINOR
|
|
|
197
187
|
- [`CHANGELOG.md`](./CHANGELOG.md) — the actual change log.
|
|
198
188
|
- [`CONTRACT.md`](./CONTRACT.md) — the token contract.
|
|
199
189
|
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — release mechanics and contributor workflow.
|
|
200
|
-
- [`ROADMAP.md`](./ROADMAP.md) — where the library is headed
|
|
190
|
+
- [`ROADMAP.md`](./ROADMAP.md) — where the library is headed.
|
|
@@ -385,7 +385,7 @@ Library defaults emit under **`:where(:root)`** (specificity 0,0,0), so any them
|
|
|
385
385
|
|
|
386
386
|
**Never hand-edit `public/theme.css` or `public/themes/**/theme.css`.** They are generated from `scss/themes/*.scss` and gated by `check:theme-drift`.
|
|
387
387
|
|
|
388
|
-
See `/docs/authoring/themes` on the docs site (https://
|
|
388
|
+
See `/docs/authoring/themes` on the docs site (https://cssisawesome.com/docs/authoring/themes/) for the full guide.
|
|
389
389
|
|
|
390
390
|
### Spacing is themeable — set the numbered step
|
|
391
391
|
|
|
@@ -489,7 +489,7 @@ How to reach them:
|
|
|
489
489
|
|
|
490
490
|
- **AI agents** — `list_recipes` / `get_recipe(name)` over MCP. Prefer this over
|
|
491
491
|
writing an interactive pattern from memory; the recipe encodes the a11y work.
|
|
492
|
-
- **Humans** — `/docs/recipes` on the docs site (https://
|
|
492
|
+
- **Humans** — `/docs/recipes` on the docs site (https://cssisawesome.com/docs/recipes/), or read the markdown directly.
|
|
493
493
|
|
|
494
494
|
Note the two different things living in `scss/recipes/`: `<slug>.md` files are
|
|
495
495
|
*pattern* recipes (read them, don't import them), while `_<slug>.scss` files —
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "css-is-awesome",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "A token-driven SCSS design system with light/dark theming, semantic color tokens, and a 800+ LOC mixin API.",
|
|
5
5
|
"homepage": "https://github.com/Jerry2d3d/css-is-awesome#readme",
|
|
6
6
|
"bugs": {
|
package/public/theme.css
CHANGED
|
@@ -320,11 +320,14 @@
|
|
|
320
320
|
--error-text: #fca5a5;
|
|
321
321
|
/* Space scale */
|
|
322
322
|
--space-2xs: 0.25rem;
|
|
323
|
-
--space-xs:
|
|
324
|
-
--space-sm:
|
|
325
|
-
--space-md:
|
|
326
|
-
--space-lg:
|
|
327
|
-
--space-xl:
|
|
323
|
+
--space-xs: var(--space-1);
|
|
324
|
+
--space-sm: var(--space-2);
|
|
325
|
+
--space-md: var(--space-4);
|
|
326
|
+
--space-lg: var(--space-5);
|
|
327
|
+
--space-xl: var(--space-6);
|
|
328
|
+
--space-2xl: var(--space-7);
|
|
329
|
+
--space-3xl: var(--space-8);
|
|
330
|
+
--space-4xl: var(--space-9);
|
|
328
331
|
/* Radius alias */
|
|
329
332
|
--radius-sm: var(--r-sm);
|
|
330
333
|
--radius-md: var(--r-md);
|
|
@@ -490,11 +493,14 @@
|
|
|
490
493
|
--error-text: #b91c1c;
|
|
491
494
|
/* Space scale */
|
|
492
495
|
--space-2xs: 0.25rem;
|
|
493
|
-
--space-xs:
|
|
494
|
-
--space-sm:
|
|
495
|
-
--space-md:
|
|
496
|
-
--space-lg:
|
|
497
|
-
--space-xl:
|
|
496
|
+
--space-xs: var(--space-1);
|
|
497
|
+
--space-sm: var(--space-2);
|
|
498
|
+
--space-md: var(--space-4);
|
|
499
|
+
--space-lg: var(--space-5);
|
|
500
|
+
--space-xl: var(--space-6);
|
|
501
|
+
--space-2xl: var(--space-7);
|
|
502
|
+
--space-3xl: var(--space-8);
|
|
503
|
+
--space-4xl: var(--space-9);
|
|
498
504
|
/* Radius alias */
|
|
499
505
|
--radius-sm: var(--r-sm);
|
|
500
506
|
--radius-md: var(--r-md);
|
|
@@ -3818,11 +3824,14 @@
|
|
|
3818
3824
|
---------------------------------------------------------- */
|
|
3819
3825
|
/* Space scale (rem for accessibility) */
|
|
3820
3826
|
--space-2xs: 0.25rem;
|
|
3821
|
-
--space-xs:
|
|
3822
|
-
--space-sm:
|
|
3823
|
-
--space-md:
|
|
3824
|
-
--space-lg:
|
|
3825
|
-
--space-xl:
|
|
3827
|
+
--space-xs: var(--space-1);
|
|
3828
|
+
--space-sm: var(--space-2);
|
|
3829
|
+
--space-md: var(--space-4);
|
|
3830
|
+
--space-lg: var(--space-5);
|
|
3831
|
+
--space-xl: var(--space-6);
|
|
3832
|
+
--space-2xl: var(--space-7);
|
|
3833
|
+
--space-3xl: var(--space-8);
|
|
3834
|
+
--space-4xl: var(--space-9);
|
|
3826
3835
|
/* Radius alias — mirrors --r-* with standard names so
|
|
3827
3836
|
`m.radius(size)` in the library finds --radius-<size>. */
|
|
3828
3837
|
--radius-sm: var(--r-sm);
|
|
@@ -130,11 +130,14 @@
|
|
|
130
130
|
--error-text: #fca5a5;
|
|
131
131
|
/* Space scale */
|
|
132
132
|
--space-2xs: 0.25rem;
|
|
133
|
-
--space-xs:
|
|
134
|
-
--space-sm:
|
|
135
|
-
--space-md:
|
|
136
|
-
--space-lg:
|
|
137
|
-
--space-xl:
|
|
133
|
+
--space-xs: var(--space-1);
|
|
134
|
+
--space-sm: var(--space-2);
|
|
135
|
+
--space-md: var(--space-4);
|
|
136
|
+
--space-lg: var(--space-5);
|
|
137
|
+
--space-xl: var(--space-6);
|
|
138
|
+
--space-2xl: var(--space-7);
|
|
139
|
+
--space-3xl: var(--space-8);
|
|
140
|
+
--space-4xl: var(--space-9);
|
|
138
141
|
/* Radius alias */
|
|
139
142
|
--radius-sm: var(--r-sm);
|
|
140
143
|
--radius-md: var(--r-md);
|
|
@@ -130,11 +130,14 @@
|
|
|
130
130
|
--error-text: #b91c1c;
|
|
131
131
|
/* Space scale */
|
|
132
132
|
--space-2xs: 0.25rem;
|
|
133
|
-
--space-xs:
|
|
134
|
-
--space-sm:
|
|
135
|
-
--space-md:
|
|
136
|
-
--space-lg:
|
|
137
|
-
--space-xl:
|
|
133
|
+
--space-xs: var(--space-1);
|
|
134
|
+
--space-sm: var(--space-2);
|
|
135
|
+
--space-md: var(--space-4);
|
|
136
|
+
--space-lg: var(--space-5);
|
|
137
|
+
--space-xl: var(--space-6);
|
|
138
|
+
--space-2xl: var(--space-7);
|
|
139
|
+
--space-3xl: var(--space-8);
|
|
140
|
+
--space-4xl: var(--space-9);
|
|
138
141
|
/* Radius alias */
|
|
139
142
|
--radius-sm: var(--r-sm);
|
|
140
143
|
--radius-md: var(--r-md);
|
|
@@ -146,11 +146,14 @@
|
|
|
146
146
|
---------------------------------------------------------- */
|
|
147
147
|
/* Space scale (rem for accessibility) */
|
|
148
148
|
--space-2xs: 0.25rem;
|
|
149
|
-
--space-xs:
|
|
150
|
-
--space-sm:
|
|
151
|
-
--space-md:
|
|
152
|
-
--space-lg:
|
|
153
|
-
--space-xl:
|
|
149
|
+
--space-xs: var(--space-1);
|
|
150
|
+
--space-sm: var(--space-2);
|
|
151
|
+
--space-md: var(--space-4);
|
|
152
|
+
--space-lg: var(--space-5);
|
|
153
|
+
--space-xl: var(--space-6);
|
|
154
|
+
--space-2xl: var(--space-7);
|
|
155
|
+
--space-3xl: var(--space-8);
|
|
156
|
+
--space-4xl: var(--space-9);
|
|
154
157
|
/* Radius alias — mirrors --r-* with standard names so
|
|
155
158
|
`m.radius(size)` in the library finds --radius-<size>. */
|
|
156
159
|
--radius-sm: var(--r-sm);
|
|
@@ -167,11 +167,14 @@
|
|
|
167
167
|
|
|
168
168
|
/* Space scale */
|
|
169
169
|
--space-2xs: 0.25rem;
|
|
170
|
-
--space-xs:
|
|
171
|
-
--space-sm:
|
|
172
|
-
--space-md:
|
|
173
|
-
--space-lg:
|
|
174
|
-
--space-xl:
|
|
170
|
+
--space-xs: var(--space-1);
|
|
171
|
+
--space-sm: var(--space-2);
|
|
172
|
+
--space-md: var(--space-4);
|
|
173
|
+
--space-lg: var(--space-5);
|
|
174
|
+
--space-xl: var(--space-6);
|
|
175
|
+
--space-2xl: var(--space-7);
|
|
176
|
+
--space-3xl: var(--space-8);
|
|
177
|
+
--space-4xl: var(--space-9);
|
|
175
178
|
|
|
176
179
|
/* Radius alias */
|
|
177
180
|
--radius-sm: var(--r-sm);
|
|
@@ -164,11 +164,14 @@
|
|
|
164
164
|
|
|
165
165
|
/* Space scale */
|
|
166
166
|
--space-2xs: 0.25rem;
|
|
167
|
-
--space-xs:
|
|
168
|
-
--space-sm:
|
|
169
|
-
--space-md:
|
|
170
|
-
--space-lg:
|
|
171
|
-
--space-xl:
|
|
167
|
+
--space-xs: var(--space-1);
|
|
168
|
+
--space-sm: var(--space-2);
|
|
169
|
+
--space-md: var(--space-4);
|
|
170
|
+
--space-lg: var(--space-5);
|
|
171
|
+
--space-xl: var(--space-6);
|
|
172
|
+
--space-2xl: var(--space-7);
|
|
173
|
+
--space-3xl: var(--space-8);
|
|
174
|
+
--space-4xl: var(--space-9);
|
|
172
175
|
|
|
173
176
|
/* Radius alias */
|
|
174
177
|
--radius-sm: var(--r-sm);
|
|
@@ -185,11 +185,14 @@
|
|
|
185
185
|
|
|
186
186
|
/* Space scale (rem for accessibility) */
|
|
187
187
|
--space-2xs: 0.25rem;
|
|
188
|
-
--space-xs:
|
|
189
|
-
--space-sm:
|
|
190
|
-
--space-md:
|
|
191
|
-
--space-lg:
|
|
192
|
-
--space-xl:
|
|
188
|
+
--space-xs: var(--space-1);
|
|
189
|
+
--space-sm: var(--space-2);
|
|
190
|
+
--space-md: var(--space-4);
|
|
191
|
+
--space-lg: var(--space-5);
|
|
192
|
+
--space-xl: var(--space-6);
|
|
193
|
+
--space-2xl: var(--space-7);
|
|
194
|
+
--space-3xl: var(--space-8);
|
|
195
|
+
--space-4xl: var(--space-9);
|
|
193
196
|
|
|
194
197
|
/* Radius alias — mirrors --r-* with standard names so
|
|
195
198
|
`m.radius(size)` in the library finds --radius-<size>. */
|