css-is-awesome 1.1.0
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 +343 -0
- package/CHANGELOG.md +1036 -0
- package/CLAUDE.md +9 -0
- package/CONTRACT.md +580 -0
- package/GEMINI.md +9 -0
- package/LICENSE +21 -0
- package/LICENSE-third-party +88 -0
- package/MIGRATION.md +312 -0
- package/README.md +380 -0
- package/ROADMAP.md +714 -0
- package/THEMING.md +290 -0
- package/THREE-TIERS.md +158 -0
- package/VERSIONING.md +200 -0
- package/_index.scss +34 -0
- package/api.scss +16 -0
- package/bin/README.md +57 -0
- package/bin/cia.cjs +114 -0
- package/bin/migrate-bootstrap.cjs +427 -0
- package/bin/migrate-tailwind.cjs +832 -0
- package/css-is-awesome.instructions.md +533 -0
- package/dist/css-is-awesome.core.css +598 -0
- package/dist/css-is-awesome.core.min.css +1 -0
- package/dist/css-is-awesome.css +3733 -0
- package/dist/css-is-awesome.min.css +1 -0
- package/dist/css-is-awesome.utilities.css +2445 -0
- package/dist/css-is-awesome.utilities.min.css +1 -0
- package/dist/tokens.css +508 -0
- package/dist/tokens.d.ts +266 -0
- package/dist/tokens.min.css +1 -0
- package/figma-tokens/README.md +57 -0
- package/figma-tokens/primitives-brand.scss +121 -0
- package/figma-tokens/semantic-dark.scss +61 -0
- package/figma-tokens/semantic-light.scss +61 -0
- package/figma-tokens/tokens.json +144 -0
- package/llm.txt +183 -0
- package/mcp/server.cjs +1495 -0
- package/package.json +199 -0
- package/public/icons/README.md +278 -0
- package/public/icons/arrow-right.svg +4 -0
- package/public/icons/check.svg +4 -0
- package/public/icons/chevron-down.svg +4 -0
- package/public/icons/close.svg +4 -0
- package/public/icons/core/arrow-down.svg +13 -0
- package/public/icons/core/arrow-left.svg +13 -0
- package/public/icons/core/arrow-right.svg +13 -0
- package/public/icons/core/arrow-up.svg +13 -0
- package/public/icons/core/bell.svg +13 -0
- package/public/icons/core/calendar.svg +15 -0
- package/public/icons/core/check.svg +12 -0
- package/public/icons/core/chevron-down.svg +12 -0
- package/public/icons/core/chevron-left.svg +12 -0
- package/public/icons/core/chevron-right.svg +12 -0
- package/public/icons/core/chevron-up.svg +12 -0
- package/public/icons/core/clock.svg +13 -0
- package/public/icons/core/close.svg +13 -0
- package/public/icons/core/copy.svg +13 -0
- package/public/icons/core/download.svg +14 -0
- package/public/icons/core/edit.svg +13 -0
- package/public/icons/core/error.svg +14 -0
- package/public/icons/core/external-link.svg +14 -0
- package/public/icons/core/eye-off.svg +15 -0
- package/public/icons/core/eye.svg +13 -0
- package/public/icons/core/filter.svg +12 -0
- package/public/icons/core/heart.svg +12 -0
- package/public/icons/core/help.svg +14 -0
- package/public/icons/core/home.svg +13 -0
- package/public/icons/core/info.svg +14 -0
- package/public/icons/core/loading.svg +12 -0
- package/public/icons/core/lock.svg +13 -0
- package/public/icons/core/mail.svg +13 -0
- package/public/icons/core/menu.svg +14 -0
- package/public/icons/core/message.svg +12 -0
- package/public/icons/core/minus.svg +12 -0
- package/public/icons/core/more-horizontal.svg +14 -0
- package/public/icons/core/pause.svg +13 -0
- package/public/icons/core/play.svg +12 -0
- package/public/icons/core/plus.svg +13 -0
- package/public/icons/core/refresh.svg +15 -0
- package/public/icons/core/save.svg +14 -0
- package/public/icons/core/search.svg +13 -0
- package/public/icons/core/settings.svg +13 -0
- package/public/icons/core/share.svg +14 -0
- package/public/icons/core/sort.svg +15 -0
- package/public/icons/core/star.svg +12 -0
- package/public/icons/core/success.svg +13 -0
- package/public/icons/core/trash.svg +16 -0
- package/public/icons/core/unlock.svg +13 -0
- package/public/icons/core/upload.svg +14 -0
- package/public/icons/core/user.svg +13 -0
- package/public/icons/core/users.svg +15 -0
- package/public/icons/core/warning.svg +14 -0
- package/public/icons/download.svg +4 -0
- package/public/icons/edit.svg +4 -0
- package/public/icons/menu.svg +4 -0
- package/public/icons/search.svg +4 -0
- package/public/theme.css +4179 -0
- package/public/themes/README.md +102 -0
- package/public/themes/boilerplate/theme.css +154 -0
- package/public/themes/boilerplate-dark/theme.css +171 -0
- package/public/themes/boilerplate-light/theme.css +171 -0
- package/public/themes/cupertino/theme.css +165 -0
- package/public/themes/cupertino-dark/theme.css +200 -0
- package/public/themes/cupertino-light/theme.css +227 -0
- package/public/themes/glass/theme.css +190 -0
- package/public/themes/glass-dark/theme.css +201 -0
- package/public/themes/glass-light/theme.css +229 -0
- package/public/themes/graphite/theme.css +155 -0
- package/public/themes/graphite-dark/theme.css +223 -0
- package/public/themes/graphite-light/theme.css +191 -0
- package/public/themes/press/theme.css +189 -0
- package/public/themes/press-dark/theme.css +199 -0
- package/public/themes/press-light/theme.css +235 -0
- package/public/themes/prism/theme.css +159 -0
- package/public/themes/prism-dark/theme.css +185 -0
- package/public/themes/prism-light/theme.css +188 -0
- package/public/themes/sketchbook/theme.css +152 -0
- package/public/themes/sketchbook-dark/theme.css +194 -0
- package/public/themes/sketchbook-light/theme.css +188 -0
- package/public/themes/terminal/theme.css +159 -0
- package/public/themes/terminal-dark/theme.css +229 -0
- package/public/themes/terminal-light/theme.css +152 -0
- package/scripts/README.md +70 -0
- package/scripts/icon-contract.json +67 -0
- package/scripts/icon-validator.js +205 -0
- package/scripts/prepare-dist.mjs +65 -0
- package/scripts/theme-a11y.js +415 -0
- package/scripts/theme-contract.json +171 -0
- package/scripts/theme-validator.js +674 -0
- package/scss/README.md +55 -0
- package/scss/_animations-utilities.scss +107 -0
- package/scss/_animations.scss +248 -0
- package/scss/_app-styles.scss +15 -0
- package/scss/_generator.scss +174 -0
- package/scss/_icons.scss +475 -0
- package/scss/_index.scss +17 -0
- package/scss/_layout.scss +597 -0
- package/scss/_mixins.scss +1036 -0
- package/scss/_system.scss +291 -0
- package/scss/_utilities.scss +377 -0
- package/scss/api.scss +61 -0
- package/scss/components/_accordion.scss +72 -0
- package/scss/components/_buttons.scss +171 -0
- package/scss/components/_copy-button.scss +69 -0
- package/scss/components/_data.scss +190 -0
- package/scss/components/_feedback.scss +197 -0
- package/scss/components/_forms.scss +272 -0
- package/scss/components/_index.scss +17 -0
- package/scss/components/_navigation.scss +186 -0
- package/scss/components/_overlay.scss +259 -0
- package/scss/components/_stepper.scss +159 -0
- package/scss/components/_tabs.scss +72 -0
- package/scss/core.scss +54 -0
- package/scss/examples/_theming.scss +107 -0
- package/scss/examples/_usage.scss +317 -0
- package/scss/main.scss +64 -0
- package/scss/recipes/README.md +110 -0
- package/scss/recipes/_bare-tags.scss +232 -0
- package/scss/recipes/_recipe-template.md +119 -0
- package/scss/recipes/combobox.md +509 -0
- package/scss/recipes/dialog.md +265 -0
- package/scss/recipes/print-to-pdf.md +263 -0
- package/scss/theme/README.md +67 -0
- package/scss/theme/_brand.scss +18 -0
- package/scss/theme/_colors-dark.scss +68 -0
- package/scss/theme/_colors-light.scss +70 -0
- package/scss/theme/_components.scss +94 -0
- package/scss/theme/_icons.scss +104 -0
- package/scss/theme/_index.scss +62 -0
- package/scss/theme/_shadows.scss +65 -0
- package/scss/theme/_shape.scss +13 -0
- package/scss/theme/_typography.scss +9 -0
- package/scss/theme/registry.json +447 -0
- package/scss/themes/boilerplate-dark.scss +212 -0
- package/scss/themes/boilerplate-light.scss +209 -0
- package/scss/themes/boilerplate.scss +181 -0
- package/scss/themes/cupertino-dark.scss +238 -0
- package/scss/themes/cupertino-light.scss +266 -0
- package/scss/themes/cupertino.scss +194 -0
- package/scss/themes/glass-dark.scss +238 -0
- package/scss/themes/glass-light.scss +266 -0
- package/scss/themes/glass.scss +220 -0
- package/scss/themes/graphite-dark.scss +260 -0
- package/scss/themes/graphite-light.scss +228 -0
- package/scss/themes/graphite.scss +182 -0
- package/scss/themes/press-dark.scss +237 -0
- package/scss/themes/press-light.scss +273 -0
- package/scss/themes/press.scss +241 -0
- package/scss/themes/prism-dark.scss +217 -0
- package/scss/themes/prism-light.scss +220 -0
- package/scss/themes/prism.scss +190 -0
- package/scss/themes/sketchbook-dark.scss +231 -0
- package/scss/themes/sketchbook-light.scss +231 -0
- package/scss/themes/sketchbook.scss +178 -0
- package/scss/themes/terminal-dark.scss +267 -0
- package/scss/themes/terminal-light.scss +175 -0
- package/scss/themes/terminal.scss +185 -0
- package/scss/tokens.scss +23 -0
- package/scss/utilities-only.scss +4 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This project is **css-is-awesome**, a token-driven SCSS design system.
|
|
4
|
+
|
|
5
|
+
For all rules, install, examples, and gotchas, read **[`AGENTS.md`](./AGENTS.md)** at the package root.
|
|
6
|
+
|
|
7
|
+
The deep authoring reference is **[`css-is-awesome.instructions.md`](./css-is-awesome.instructions.md)**.
|
|
8
|
+
|
|
9
|
+
Both ship inside the npm package, so you can read them at `node_modules/css-is-awesome/AGENTS.md` when working in a consumer project.
|
package/CONTRACT.md
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
# css-is-awesome — Token Contract
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
- **Source of truth:** this document.
|
|
6
|
+
- **Reference implementation:** [`public/theme.css`](./public/theme.css) (Sketchbook).
|
|
7
|
+
- **Validate a theme:** `node scripts/theme-validator.js <path-to-theme.css>`
|
|
8
|
+
- **Validate every theme in the repo:** `npm run validate-themes`
|
|
9
|
+
|
|
10
|
+
A theme file is a single `:root { … }` block plus (optionally) an `@import` for fonts. No component CSS lives in a theme file. Tokens only.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## How tokens reach the library
|
|
15
|
+
|
|
16
|
+
Library mixins resolve every token through a `var(--token, fallback)` pattern, so:
|
|
17
|
+
|
|
18
|
+
| Mixin call | Emitted CSS | Required token |
|
|
19
|
+
| -------------------------------- | ---------------------------------------- | -------------------- |
|
|
20
|
+
| `m.color(surface-default)` | `var(--surface-default, #fff)` | `--surface-default` |
|
|
21
|
+
| `m.space(md)` | `var(--space-md, 1rem)` | `--space-md` |
|
|
22
|
+
| `m.radius(lg)` | `var(--radius-lg, 0.5rem)` | `--radius-lg` |
|
|
23
|
+
| `m.shadow(md)` | `var(--shadow-md, …)` | `--shadow-md` |
|
|
24
|
+
| `m.font-family(primary)` | `var(--font-primary, sans-serif)` | `--font-primary` |
|
|
25
|
+
| `m.font-size(base)` | `var(--font-size-base, 1rem)` | `--font-size-base` |
|
|
26
|
+
| `m.line-height(normal)` | `var(--line-height-normal, 1.5)` | `--line-height-normal` |
|
|
27
|
+
| `m.font-weight(medium)` | `var(--font-weight-medium, 500)` | `--font-weight-medium` |
|
|
28
|
+
| `m.z(modal)` | `var(--z-modal, 0)` | `--z-modal` |
|
|
29
|
+
|
|
30
|
+
If a token is missing from a theme the mixin silently falls back to a sensible SCSS default — which means the theme swap is no longer lossless. That is what the contract prevents.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Native Sketchbook palette
|
|
35
|
+
|
|
36
|
+
These are the raw pigment tokens. Semantic aliases below reference them. In other themes (Press, Graphite, Glass, …) the native names change; the aliases do not.
|
|
37
|
+
|
|
38
|
+
### Paper (surfaces)
|
|
39
|
+
|
|
40
|
+
| Token | Type | Example | Purpose |
|
|
41
|
+
| --------------- | ----- | ------------------------------- | ---------------------------------- |
|
|
42
|
+
| `--paper` | color | `#F7F3EA` | Page background — the "paper" |
|
|
43
|
+
| `--paper-raised`| color | `#FDFAF2` | Lifted panel / card background |
|
|
44
|
+
| `--paper-sunk` | color | `#ECE5D3` | Pressed / recessed surface |
|
|
45
|
+
| `--paper-glass` | color | `rgba(253, 250, 242, 0.75)` | Translucent surface (glass themes) |
|
|
46
|
+
|
|
47
|
+
### Ink (text hierarchy)
|
|
48
|
+
|
|
49
|
+
| Token | Type | Example | Purpose |
|
|
50
|
+
| ------------- | ----- | --------- | ---------------------------------- |
|
|
51
|
+
| `--ink` | color | `#2A241E` | Primary type — body copy, headings |
|
|
52
|
+
| `--ink-soft` | color | `#4A4037` | Secondary type |
|
|
53
|
+
| `--ink-faint` | color | `#726858` | Muted / hint type |
|
|
54
|
+
| `--graphite` | color | `#3A332B` | Emphasis stroke / chart ink |
|
|
55
|
+
| `--muted` | color | `#948977` | Captions, low-emphasis metadata |
|
|
56
|
+
|
|
57
|
+
### Construction lines
|
|
58
|
+
|
|
59
|
+
| Token | Type | Example | Purpose |
|
|
60
|
+
| -------------- | ----- | --------- | ---------------------- |
|
|
61
|
+
| `--guide` | color | `#C9BDA5` | Layout guide / grid line |
|
|
62
|
+
| `--guide-soft` | color | `#DDD4C0` | Secondary guide |
|
|
63
|
+
| `--hair` | color | `#D4CCBB` | Default border |
|
|
64
|
+
| `--hair-soft` | color | `#E8E2D4` | Subtle divider |
|
|
65
|
+
|
|
66
|
+
### Primary accent (indigo)
|
|
67
|
+
|
|
68
|
+
| Token | Type | Example | Purpose |
|
|
69
|
+
| ------------ | ----- | --------- | ---------------------------------- |
|
|
70
|
+
| `--ai` | color | `#1F3A5F` | Primary action / link / focus ring |
|
|
71
|
+
| `--ai-ink` | color | `#14263F` | Hover / active darker variant |
|
|
72
|
+
| `--ai-wash` | color | `#E5EBF1` | Wash tint for backgrounds |
|
|
73
|
+
|
|
74
|
+
### Seal (vermilion)
|
|
75
|
+
|
|
76
|
+
| Token | Type | Example | Purpose |
|
|
77
|
+
| ----------- | ----- | --------- | ----------------------------- |
|
|
78
|
+
| `--shu` | color | `#C1272D` | Secondary / editorial emphasis |
|
|
79
|
+
| `--shu-wash`| color | `#F6E3E1` | Wash tint |
|
|
80
|
+
|
|
81
|
+
### Draft / marginalia (ochre)
|
|
82
|
+
|
|
83
|
+
| Token | Type | Example | Purpose |
|
|
84
|
+
| ------------- | ----- | --------- | ------------------------- |
|
|
85
|
+
| `--ochre` | color | `#A37B30` | Tertiary / warning accent |
|
|
86
|
+
| `--ochre-wash`| color | `#F0E5CC` | Wash tint |
|
|
87
|
+
|
|
88
|
+
### Code panel
|
|
89
|
+
|
|
90
|
+
| Token | Type | Example | Purpose |
|
|
91
|
+
| --------------- | ----- | --------- | ----------------------------- |
|
|
92
|
+
| `--code-bg` | color | `#2B2420` | Code block background |
|
|
93
|
+
| `--code-ink` | color | `#F7F3EA` | Code body text |
|
|
94
|
+
| `--code-muted` | color | `#A39787` | Code comments |
|
|
95
|
+
| `--code-accent` | color | `#E5B660` | Literals / values |
|
|
96
|
+
| `--code-green` | color | `#A8B86C` | Keywords / properties |
|
|
97
|
+
| `--code-blue` | color | `#94AFC9` | Selectors / tags |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Semantic aliases (library mixins read these)
|
|
102
|
+
|
|
103
|
+
### Backgrounds (page-level)
|
|
104
|
+
|
|
105
|
+
| Token | Type | Purpose |
|
|
106
|
+
| ---------------------- | ----- | ------------------------------------ |
|
|
107
|
+
| `--background-default` | color | Default page background |
|
|
108
|
+
| `--background-subtle` | color | Alternate / striped section |
|
|
109
|
+
| `--background-navbar` | color | Dedicated navbar background |
|
|
110
|
+
|
|
111
|
+
### Surfaces (panel-level)
|
|
112
|
+
|
|
113
|
+
| Token | Type | Purpose |
|
|
114
|
+
| -------------------- | ----- | --------------------------------- |
|
|
115
|
+
| `--surface-default` | color | Card / panel default |
|
|
116
|
+
| `--surface-raised` | color | Lifted card (elevation) |
|
|
117
|
+
| `--surface-sunk` | color | Pressed / recessed |
|
|
118
|
+
| `--surface-muted` | color | Muted field / disabled panel |
|
|
119
|
+
| `--surface-subtle` | color | Subtle highlight |
|
|
120
|
+
| `--surface-emphasis` | color | Inverse / emphasis surface |
|
|
121
|
+
| `--surface-glass` | color | Translucent (glass themes) |
|
|
122
|
+
|
|
123
|
+
### Text
|
|
124
|
+
|
|
125
|
+
| Token | Type | Purpose |
|
|
126
|
+
| -------------------- | ----- | --------------------------------- |
|
|
127
|
+
| `--text-primary` | color | Body copy, headings |
|
|
128
|
+
| `--text-secondary` | color | Supporting copy |
|
|
129
|
+
| `--text-muted` | color | Hint / help / placeholder |
|
|
130
|
+
| `--text-tertiary` | color | Low-emphasis metadata |
|
|
131
|
+
| `--text-inverse` | color | Text on dark / colored surface |
|
|
132
|
+
| `--text-link` | color | Default anchor color |
|
|
133
|
+
| `--text-link-hover` | color | Anchor hover color |
|
|
134
|
+
|
|
135
|
+
### Borders
|
|
136
|
+
|
|
137
|
+
| Token | Type | Purpose |
|
|
138
|
+
| -------------------- | ----- | -------------------------------- |
|
|
139
|
+
| `--border-default` | color | Default border |
|
|
140
|
+
| `--border-subtle` | color | Subtle divider |
|
|
141
|
+
| `--border-emphasis` | color | Emphasized border |
|
|
142
|
+
| `--border-focus` | color | Focus ring color |
|
|
143
|
+
|
|
144
|
+
### Interactive (hover / active wash)
|
|
145
|
+
|
|
146
|
+
| Token | Type | Purpose |
|
|
147
|
+
| --------------------- | ----- | ---------------------------------- |
|
|
148
|
+
| `--interactive-hover` | color | Wash applied to interactive hover |
|
|
149
|
+
| `--interactive-active`| color | Wash applied to interactive active |
|
|
150
|
+
|
|
151
|
+
### Brand
|
|
152
|
+
|
|
153
|
+
| Token | Type | Purpose |
|
|
154
|
+
| ---------------------- | ----- | --------------------------------- |
|
|
155
|
+
| `--brand-primary` | color | Brand identity color |
|
|
156
|
+
| `--brand-primary-hover`| color | Brand hover color |
|
|
157
|
+
|
|
158
|
+
### Action — primary / secondary / tertiary
|
|
159
|
+
|
|
160
|
+
| Token | Type | Purpose |
|
|
161
|
+
| ----------------------------- | ----- | --------------------------- |
|
|
162
|
+
| `--action-primary-default` | color | Primary button / CTA |
|
|
163
|
+
| `--action-primary-hover` | color | Primary hover |
|
|
164
|
+
| `--action-primary-active` | color | Primary pressed |
|
|
165
|
+
| `--action-primary-wash` | color | Primary subtle background |
|
|
166
|
+
| `--action-secondary-default` | color | Secondary button |
|
|
167
|
+
| `--action-secondary-hover` | color | Secondary hover |
|
|
168
|
+
| `--action-secondary-active` | color | Secondary pressed |
|
|
169
|
+
| `--action-secondary-wash` | color | Secondary subtle background |
|
|
170
|
+
| `--action-tertiary-default` | color | Tertiary button |
|
|
171
|
+
| `--action-tertiary-hover` | color | Tertiary hover |
|
|
172
|
+
| `--action-tertiary-active` | color | Tertiary pressed |
|
|
173
|
+
| `--action-tertiary-wash` | color | Tertiary subtle background |
|
|
174
|
+
|
|
175
|
+
### Feedback (high-level semantic)
|
|
176
|
+
|
|
177
|
+
| Token | Type | Purpose |
|
|
178
|
+
| -------------------- | ----- | -------------------- |
|
|
179
|
+
| `--feedback-info` | color | Info / neutral cue |
|
|
180
|
+
| `--feedback-success` | color | Success cue |
|
|
181
|
+
| `--feedback-warning` | color | Warning cue |
|
|
182
|
+
| `--feedback-error` | color | Error / destructive |
|
|
183
|
+
|
|
184
|
+
### Status (three-part: default / subtle / text)
|
|
185
|
+
|
|
186
|
+
| Token | Type | Purpose |
|
|
187
|
+
| -------------------- | ----- | -------------------------------------------- |
|
|
188
|
+
| `--info-default` | color | Alert / badge strong tone |
|
|
189
|
+
| `--info-subtle` | color | Alert / badge wash background |
|
|
190
|
+
| `--info-text` | color | Alert / badge body copy |
|
|
191
|
+
| `--success-default` | color | Success alert strong tone |
|
|
192
|
+
| `--success-subtle` | color | Success wash |
|
|
193
|
+
| `--success-text` | color | Success body copy |
|
|
194
|
+
| `--warning-default` | color | Warning strong tone |
|
|
195
|
+
| `--warning-subtle` | color | Warning wash |
|
|
196
|
+
| `--warning-text` | color | Warning body copy |
|
|
197
|
+
| `--error-default` | color | Error strong tone |
|
|
198
|
+
| `--error-subtle` | color | Error wash |
|
|
199
|
+
| `--error-text` | color | Error body copy |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Typography
|
|
204
|
+
|
|
205
|
+
| Token | Type | Example | Purpose |
|
|
206
|
+
| -------------------- | ------------ | --------------------------------- | ------------------------------ |
|
|
207
|
+
| `--font-display` | font-family | `'DM Serif Display', …, serif` | Large display / hero type |
|
|
208
|
+
| `--font-serif` | font-family | `'Noto Serif JP', …, serif` | Body serif |
|
|
209
|
+
| `--font-sans` | font-family | `'Noto Sans JP', …, sans-serif` | Body sans |
|
|
210
|
+
| `--font-script` | font-family | `'Caveat', …, cursive` | Handwriting / marginalia |
|
|
211
|
+
| `--font-mono` | font-family | `'JetBrains Mono', …, monospace` | Code |
|
|
212
|
+
| `--font-primary` | font-family | `var(--font-sans)` | Default body — emitted by `m.font-family(primary)` |
|
|
213
|
+
| `--font-size-base` | length | `1rem` | Base body size |
|
|
214
|
+
| `--line-height-normal` | number | `1.5` | Default line-height |
|
|
215
|
+
| `--font-weight-medium` | number | `500` | Medium weight (used by buttons) |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Space scale
|
|
220
|
+
|
|
221
|
+
| Token | Type | Example | Purpose |
|
|
222
|
+
| ------------- | ------ | --------- | --------------------------- |
|
|
223
|
+
| `--space-2xs` | length | `0.25rem` | Hairline gap / 2xs padding |
|
|
224
|
+
| `--space-xs` | length | `0.5rem` | Tight gap / xs padding |
|
|
225
|
+
| `--space-sm` | length | `0.75rem` | Compact gap / sm padding |
|
|
226
|
+
| `--space-md` | length | `1rem` | Default gap / md padding |
|
|
227
|
+
| `--space-lg` | length | `1.5rem` | Comfortable gap / lg padding |
|
|
228
|
+
| `--space-xl` | length | `2rem` | Section gap / xl padding |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Radius
|
|
233
|
+
|
|
234
|
+
Sketchbook keeps native `--r-*` (drawn-on-paper feel) plus an alias set `--radius-*` that the library mixins emit. Other themes may set both to the same value.
|
|
235
|
+
|
|
236
|
+
| Token | Type | Example | Purpose |
|
|
237
|
+
| ------------- | ------ | ------------- | ------------------------------- |
|
|
238
|
+
| `--r-sm` | length | `2px` | Native small radius (Sketchbook) |
|
|
239
|
+
| `--r-md` | length | `3px` | Native medium radius |
|
|
240
|
+
| `--r-lg` | length | `6px` | Native large radius |
|
|
241
|
+
| `--radius-sm` | length | `var(--r-sm)` | Library alias (mixins emit this) |
|
|
242
|
+
| `--radius-md` | length | `var(--r-md)` | Library alias |
|
|
243
|
+
| `--radius-lg` | length | `var(--r-lg)` | Library alias |
|
|
244
|
+
| `--radius-xl` | length | `0.75rem` | Modals / large panels |
|
|
245
|
+
| `--radius-full` | length | `9999px` | Pills, avatars, circles |
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Shadow
|
|
250
|
+
|
|
251
|
+
| Token | Type | Example | Purpose |
|
|
252
|
+
| ------------- | ---------- | --------------------------------------- | ---------------------------- |
|
|
253
|
+
| `--shadow-sm` | box-shadow | `0 1px 2px rgba(…, .06)` | Card-level lift |
|
|
254
|
+
| `--shadow-md` | box-shadow | `0 4px 18px rgba(…, .08)` | Dropdowns, popovers |
|
|
255
|
+
| `--shadow-lg` | box-shadow | `0 12px 40px rgba(…, .12)` | Toasts, floating panels |
|
|
256
|
+
| `--shadow-xl` | box-shadow | `0 20px 50px rgba(…, .16)` | High-elevation surfaces |
|
|
257
|
+
| `--shadow-2xl`| box-shadow | `0 28px 70px rgba(…, .22)` | Modal backdrops |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Blur / Glow
|
|
262
|
+
|
|
263
|
+
Paper themes declare these as `none` / `transparent` so a swap to a glass or phosphor theme is lossless.
|
|
264
|
+
|
|
265
|
+
| Token | Type | Example | Purpose |
|
|
266
|
+
| ------------ | ------ | ------------------- | -------------------------------------- |
|
|
267
|
+
| `--blur-sm` | length | `none` | Glass surface subtle blur |
|
|
268
|
+
| `--blur-md` | length | `none` | Glass medium blur |
|
|
269
|
+
| `--blur-lg` | length | `none` | Glass heavy blur |
|
|
270
|
+
| `--glow-sm` | shadow | `0 0 0 transparent` | Subtle glow (phosphor / emphasis themes) |
|
|
271
|
+
| `--glow-md` | shadow | `0 0 0 transparent` | Medium glow |
|
|
272
|
+
| `--glow-lg` | shadow | `0 0 0 transparent` | Heavy glow |
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Motion
|
|
277
|
+
|
|
278
|
+
| Token | Type | Example | Purpose |
|
|
279
|
+
| ------------------- | -------- | ------------------------------ | ------------------------- |
|
|
280
|
+
| `--duration-fast` | duration | `180ms` | Fast interactions (hover) |
|
|
281
|
+
| `--duration-normal` | duration | `240ms` | Default transitions |
|
|
282
|
+
| `--duration-slow` | duration | `380ms` | Deliberate motion |
|
|
283
|
+
| `--ease` | timing | `cubic-bezier(.33,.66,.33,1)` | Default easing curve |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Z-index layers
|
|
288
|
+
|
|
289
|
+
| Token | Type | Example | Purpose |
|
|
290
|
+
| -------------- | ------ | ------- | ---------------------- |
|
|
291
|
+
| `--z-sticky` | number | `1020` | Sticky headers |
|
|
292
|
+
| `--z-dropdown` | number | `1030` | Dropdown menus |
|
|
293
|
+
| `--z-backdrop` | number | `1040` | Modal backdrop |
|
|
294
|
+
| `--z-modal` | number | `1050` | Modal surface |
|
|
295
|
+
| `--z-popover` | number | `1060` | Popover / detached panel |
|
|
296
|
+
| `--z-tooltip` | number | `1070` | Tooltips (always top) |
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Component overrides (optional)
|
|
301
|
+
|
|
302
|
+
These are per-component tokens a theme MAY override to change how a single family of components renders (buttons, cards, inputs, etc.) without touching the library or rebuilding SCSS. They are **optional** — the library emits every one of them on `:root` with a sensible default, and every component mixin reads them via `var(--<key>, <library-default>)`. A theme that sets none of them renders exactly the same as today.
|
|
303
|
+
|
|
304
|
+
To override, declare the variable inside your theme's `:root { … }` block, e.g.:
|
|
305
|
+
|
|
306
|
+
```css
|
|
307
|
+
:root {
|
|
308
|
+
--btn-radius: 0; /* Terminal — zero radii everywhere */
|
|
309
|
+
--card-shadow: none; /* Press — editorial flat */
|
|
310
|
+
--input-radius: var(--r-sm); /* Cupertino — AppKit text field */
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Buttons
|
|
315
|
+
|
|
316
|
+
| Token | Type | Default | Purpose |
|
|
317
|
+
| -------------------- | ---------- | ------------------------------- | -------------------------------------- |
|
|
318
|
+
| `--btn-padding-y` | length | `var(--space-1, 0.5rem)` | Vertical padding on `btn-base` |
|
|
319
|
+
| `--btn-padding-x` | length | `var(--space-4, 1rem)` | Horizontal padding on `btn-base` |
|
|
320
|
+
| `--btn-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
321
|
+
| `--btn-font-weight` | number | `var(--font-weight-medium, 500)`| Type weight |
|
|
322
|
+
| `--btn-font-size` | length | `var(--font-size-base, 1rem)` | Font size (used when size is explicit) |
|
|
323
|
+
| `--btn-border-width` | length | `1px` | Border stroke (outline / ghost) |
|
|
324
|
+
|
|
325
|
+
### Cards
|
|
326
|
+
|
|
327
|
+
| Token | Type | Default | Purpose |
|
|
328
|
+
| ---------------- | ---------- | ------------------------------------ | ----------------------------- |
|
|
329
|
+
| `--card-padding` | length | `var(--space-4, 1rem)` | Inner padding |
|
|
330
|
+
| `--card-radius` | length | `var(--radius-lg, 0.5rem)` | Corner radius |
|
|
331
|
+
| `--card-shadow` | box-shadow | `var(--shadow-sm, …)` | Elevation (set `none` to flatten) |
|
|
332
|
+
| `--card-border` | border | `1px solid var(--border-default)` | Edge treatment (when enabled) |
|
|
333
|
+
|
|
334
|
+
### Inputs
|
|
335
|
+
|
|
336
|
+
| Token | Type | Default | Purpose |
|
|
337
|
+
| ---------------------- | ------ | --------------------------- | ------------------ |
|
|
338
|
+
| `--input-padding-y` | length | `var(--space-1, 0.5rem)` | Vertical padding |
|
|
339
|
+
| `--input-padding-x` | length | `var(--space-2, 0.75rem)` | Horizontal padding |
|
|
340
|
+
| `--input-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
341
|
+
| `--input-border-width` | length | `1px` | Border stroke |
|
|
342
|
+
|
|
343
|
+
### Alerts
|
|
344
|
+
|
|
345
|
+
| Token | Type | Default | Purpose |
|
|
346
|
+
| ------------------- | ------ | --------------------------- | ------------------ |
|
|
347
|
+
| `--alert-padding-y` | length | `var(--space-2, 0.75rem)` | Vertical padding |
|
|
348
|
+
| `--alert-padding-x` | length | `var(--space-4, 1rem)` | Horizontal padding |
|
|
349
|
+
| `--alert-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
350
|
+
|
|
351
|
+
### Badges
|
|
352
|
+
|
|
353
|
+
| Token | Type | Default | Purpose |
|
|
354
|
+
| ------------------- | ------ | --------------------------- | ------------------ |
|
|
355
|
+
| `--badge-padding-y` | length | `var(--space-1, 0.5rem)` | Vertical padding |
|
|
356
|
+
| `--badge-padding-x` | length | `var(--space-1, 0.5rem)` | Horizontal padding |
|
|
357
|
+
| `--badge-radius` | length | `var(--radius-full, 9999px)`| Corner radius |
|
|
358
|
+
|
|
359
|
+
### Tags / Chips
|
|
360
|
+
|
|
361
|
+
| Token | Type | Default | Purpose |
|
|
362
|
+
| ----------------- | ------ | ---------------------------- | ------------------ |
|
|
363
|
+
| `--tag-padding-y` | length | `var(--space-2xs, 0.25rem)` | Vertical padding |
|
|
364
|
+
| `--tag-padding-x` | length | `var(--space-2, 0.75rem)` | Horizontal padding |
|
|
365
|
+
| `--tag-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
366
|
+
|
|
367
|
+
### Modals
|
|
368
|
+
|
|
369
|
+
| Token | Type | Default | Purpose |
|
|
370
|
+
| ----------------- | ---------- | ------------------------------- | --------------- |
|
|
371
|
+
| `--modal-padding` | length | `var(--space-5, 1.5rem)` | Inner padding |
|
|
372
|
+
| `--modal-radius` | length | `var(--radius-xl, 0.75rem)` | Corner radius |
|
|
373
|
+
| `--modal-shadow` | box-shadow | `var(--shadow-2xl, …)` | Elevation |
|
|
374
|
+
|
|
375
|
+
### Popovers
|
|
376
|
+
|
|
377
|
+
| Token | Type | Default | Purpose |
|
|
378
|
+
| ------------------- | ---------- | ------------------------------ | ------------- |
|
|
379
|
+
| `--popover-padding` | length | `var(--space-4, 1rem)` | Inner padding |
|
|
380
|
+
| `--popover-radius` | length | `var(--radius-lg, 0.5rem)` | Corner radius |
|
|
381
|
+
| `--popover-shadow` | box-shadow | `var(--shadow-lg, …)` | Elevation |
|
|
382
|
+
|
|
383
|
+
### Tooltips
|
|
384
|
+
|
|
385
|
+
| Token | Type | Default | Purpose |
|
|
386
|
+
| --------------------- | ------ | --------------------------- | ------------------ |
|
|
387
|
+
| `--tooltip-padding-y` | length | `var(--space-1, 0.5rem)` | Vertical padding |
|
|
388
|
+
| `--tooltip-padding-x` | length | `var(--space-1, 0.5rem)` | Horizontal padding |
|
|
389
|
+
| `--tooltip-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
390
|
+
|
|
391
|
+
### Dropdowns
|
|
392
|
+
|
|
393
|
+
| Token | Type | Default | Purpose |
|
|
394
|
+
| -------------------- | ---------- | --------------------------- | ------------- |
|
|
395
|
+
| `--dropdown-radius` | length | `var(--radius-md, 0.25rem)` | Corner radius |
|
|
396
|
+
| `--dropdown-shadow` | box-shadow | `var(--shadow-md, …)` | Elevation |
|
|
397
|
+
|
|
398
|
+
Total: 34 optional component tokens. None are validated — a theme that omits all of them still passes `npm run validate-themes`.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## A11y contrast (WCAG 2.2 AA)
|
|
403
|
+
|
|
404
|
+
Every PR runs `npm run validate-themes`, which now also audits the most
|
|
405
|
+
common contrast pairs in each theme block against the
|
|
406
|
+
[WCAG 2.2 §1.4.3 / §1.4.11](https://www.w3.org/TR/WCAG22/#contrast-minimum)
|
|
407
|
+
ratios. The audit is implemented in `scripts/theme-a11y.js` (zero deps —
|
|
408
|
+
sRGB linearisation + relative-luminance ratio). Translucent foregrounds
|
|
409
|
+
are alpha-composited onto the background before the ratio is computed, and
|
|
410
|
+
translucent backgrounds (status `--*-subtle` washes) are first composited
|
|
411
|
+
onto `--paper` so the math reflects what users actually see.
|
|
412
|
+
|
|
413
|
+
| Pair | Required | Kind |
|
|
414
|
+
| ----------------------------------------------------- | -------- | -------- |
|
|
415
|
+
| `--text-primary` on `--paper` | 4.5 : 1 | text |
|
|
416
|
+
| `--text-secondary` on `--paper` | 4.5 : 1 | text |
|
|
417
|
+
| `--text-tertiary` on `--paper` | 3.0 : 1 | large |
|
|
418
|
+
| `--text-muted` on `--paper` | 4.5 : 1 | text |
|
|
419
|
+
| `--ink` / `--ink-soft` on `--paper` | 4.5 : 1 | text |
|
|
420
|
+
| `--ink-faint` on `--paper` | 3.0 : 1 | large |
|
|
421
|
+
| `--text-link` on `--paper` | 4.5 : 1 | text |
|
|
422
|
+
| `--text-inverse` on `--action-primary-default` | 4.5 : 1 | text |
|
|
423
|
+
| `--text-inverse` on `--ai` | 4.5 : 1 | text |
|
|
424
|
+
| `--success-text` on `--success-subtle` | 4.5 : 1 | text |
|
|
425
|
+
| `--warning-text` on `--warning-subtle` | 4.5 : 1 | text |
|
|
426
|
+
| `--error-text` on `--error-subtle` | 4.5 : 1 | text |
|
|
427
|
+
| `--info-text` on `--info-subtle` | 4.5 : 1 | text |
|
|
428
|
+
| `--border-default` on `--paper` | 3.0 : 1 | non-text |
|
|
429
|
+
| `--border-focus` on `--paper` | 3.0 : 1 | non-text |
|
|
430
|
+
| `--shu` on `--paper` | 3.0 : 1 | non-text |
|
|
431
|
+
|
|
432
|
+
Each pair is reported as **PASS**, **WARN** (close to threshold; `--text-tertiary`
|
|
433
|
+
and `--ink-faint` warn when they pass the 3:1 large-text bar but fall below the
|
|
434
|
+
4.5:1 body threshold), or **FAIL** (red, exits non-zero). CI fails on any FAIL.
|
|
435
|
+
|
|
436
|
+
Pass `--no-a11y` to `node scripts/theme-validator.js` (or set it in
|
|
437
|
+
`package.json`) to skip the audit — the contract check still runs. Color
|
|
438
|
+
formats supported: `#rgb`, `#rrggbb`, `#rrggbbaa`, `rgb()`, `rgba()`,
|
|
439
|
+
`hsl()`, `hsla()`, the 148 named colors and `transparent`. Modern color
|
|
440
|
+
spaces (`oklch()`, `oklab()`, `color-mix()`, `lab()`, `lch()`, `hwb()`)
|
|
441
|
+
are reported as **SKIP** with a reason rather than silently passing.
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Versioning
|
|
447
|
+
|
|
448
|
+
The contract is versioned via `scripts/theme-contract.json` (`version: "1"`).
|
|
449
|
+
|
|
450
|
+
- **Minor bump** (`"1" → "1.1"`): adds OPTIONAL tokens. Existing themes remain valid.
|
|
451
|
+
- **Major bump** (`"1" → "2"`): renames or removes REQUIRED tokens. Existing themes must migrate.
|
|
452
|
+
|
|
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 `public/theme.css` and `public/themes/*/theme.css`. The `npm run validate-themes` check in CI will block the merge otherwise.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Icons contract
|
|
458
|
+
|
|
459
|
+
The icon system is a parallel contract to the token contract. The
|
|
460
|
+
machine-readable companion is [`scripts/icon-contract.json`](./scripts/icon-contract.json);
|
|
461
|
+
the validator is `scripts/icon-validator.js` (run `npm run validate-icons`,
|
|
462
|
+
or per pack with `node scripts/icon-validator.js core`). A pack that
|
|
463
|
+
omits any contract glyph fails the build.
|
|
464
|
+
|
|
465
|
+
### Packs and on-disk layout
|
|
466
|
+
|
|
467
|
+
Icons are organized into named **packs**. The default pack `core` ships
|
|
468
|
+
49 UI-essential glyphs vendored from Lucide (see
|
|
469
|
+
[`LICENSE-third-party`](./LICENSE-third-party)). Additional packs (e.g.
|
|
470
|
+
`files`, `editor`) follow the same layout when added.
|
|
471
|
+
|
|
472
|
+
```
|
|
473
|
+
public/icons/<pack>/<glyph>.svg ← bundled defaults
|
|
474
|
+
public/themes/<theme>/icons/<pack>/<glyph>.svg ← per-theme override
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
The SCSS configuration lives in `scss/theme/_icons.scss`:
|
|
478
|
+
|
|
479
|
+
| Variable | Default | Purpose |
|
|
480
|
+
| -------------------------- | ----------- | -------------------------------------------- |
|
|
481
|
+
| `$icon-path` | `/icons` | Public root that hosts every pack directory |
|
|
482
|
+
| `$icon-pack` | `core` | Pack folder appended to `$icon-path` |
|
|
483
|
+
| `$icon-size` | `24px` | Default host element size |
|
|
484
|
+
| `$icon-svg-alias` | small map | Compile-time semantic name → filename map |
|
|
485
|
+
|
|
486
|
+
Re-exported from `scss/theme/_index.scss` as `$theme-icon-path`,
|
|
487
|
+
`$theme-icon-pack`, etc.
|
|
488
|
+
|
|
489
|
+
### Resolution order (per glyph)
|
|
490
|
+
|
|
491
|
+
`m.svg(name)` (and the `svg-bg` / `svg-text` variants) emits a CSS
|
|
492
|
+
custom-property lookup with the bundled URL as fallback:
|
|
493
|
+
|
|
494
|
+
```scss
|
|
495
|
+
@include m.svg(check);
|
|
496
|
+
// → mask: var(--cia-icon-check, url('/icons/core/check.svg')) center / contain no-repeat;
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
The resolution order at the browser is therefore:
|
|
500
|
+
|
|
501
|
+
1. **Per-theme override.** A theme that ships a replacement glyph
|
|
502
|
+
declares `--cia-icon-<glyph>: url('/themes/<theme>/icons/<pack>/<glyph>.svg')`
|
|
503
|
+
on `:root` (or inside its `[data-theme="<name>"]` block in the
|
|
504
|
+
consolidated bundle). Browser uses that URL.
|
|
505
|
+
2. **Core pack fallback.** If no override is declared, the browser
|
|
506
|
+
resolves the URL baked into the second `var()` argument
|
|
507
|
+
(`/icons/<pack>/<glyph>.svg`).
|
|
508
|
+
3. **404.** If the file doesn't exist on disk the browser silently
|
|
509
|
+
renders nothing — the host element keeps its size, no error in the
|
|
510
|
+
layout.
|
|
511
|
+
|
|
512
|
+
Aliases (`$theme-icon-svg-alias`) resolve at compile time *before* the
|
|
513
|
+
override lookup, so the override key matches the canonical filename, not
|
|
514
|
+
the call-site alias. With the default alias `close → x`:
|
|
515
|
+
|
|
516
|
+
```scss
|
|
517
|
+
@include m.svg(close); // call site uses the semantic name
|
|
518
|
+
// → mask: var(--cia-icon-x, url('/icons/core/x.svg')) ...;
|
|
519
|
+
// → theme override key is --cia-icon-x
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Naming conventions
|
|
523
|
+
|
|
524
|
+
- **Kebab-case glyph names** — `arrow-right`, `chevron-down`, `more-horizontal`.
|
|
525
|
+
- **Category prefix groups related glyphs alphabetically** in directory
|
|
526
|
+
listings — `arrow-*`, `chevron-*`, `file-*`.
|
|
527
|
+
- **One glyph per file.** Multi-color art uses `m.svg-bg` and lives
|
|
528
|
+
outside the contract.
|
|
529
|
+
- **Override custom property:** `--cia-icon-<filename>` (the resolved
|
|
530
|
+
filename after aliases, not the call-site name).
|
|
531
|
+
|
|
532
|
+
### File-format expectations
|
|
533
|
+
|
|
534
|
+
Every glyph in a contract pack MUST:
|
|
535
|
+
|
|
536
|
+
- Be a valid SVG document — start with `<?xml version="1.0" ...?>` or
|
|
537
|
+
`<svg ...>`.
|
|
538
|
+
- Use `viewBox="0 0 24 24"` (or scale equivalently). The mixin sizes
|
|
539
|
+
the host element; the SVG just needs a square viewBox.
|
|
540
|
+
- Paint via `stroke="currentColor"` / `fill="currentColor"` (or no
|
|
541
|
+
paint attribute). The mixin renders the SVG as a CSS mask, so any
|
|
542
|
+
hardcoded color is discarded — but currentColor keeps the file
|
|
543
|
+
reusable in `m.svg-bg` too.
|
|
544
|
+
- Omit `width` / `height` attributes on `<svg>`.
|
|
545
|
+
- Omit Lucide / Heroicons / Feather author-class hooks
|
|
546
|
+
(`class="lucide ..."`, etc.) — they're noise the mixin doesn't use.
|
|
547
|
+
|
|
548
|
+
The `vendor-lucide-core.mjs` script normalizes Lucide output to match
|
|
549
|
+
this format. Hand-authored glyphs should follow it directly.
|
|
550
|
+
|
|
551
|
+
### Canonical `core` pack glyph names
|
|
552
|
+
|
|
553
|
+
Every pack listed in `scripts/icon-contract.json → packs.core.glyphs`
|
|
554
|
+
must exist at `public/icons/core/<name>.svg`. The current contract is:
|
|
555
|
+
|
|
556
|
+
| Group | Glyphs |
|
|
557
|
+
| --------------- | --------------------------------------------------------------------------------------------------- |
|
|
558
|
+
| Already shipped | `arrow-right`, `check`, `chevron-down`, `close`, `download`, `edit`, `menu`, `search` |
|
|
559
|
+
| Navigation | `arrow-left`, `arrow-up`, `arrow-down`, `chevron-up`, `chevron-left`, `chevron-right`, `external-link`, `home` |
|
|
560
|
+
| Actions | `upload`, `copy`, `share`, `trash`, `save`, `refresh`, `settings`, `filter`, `sort`, `plus`, `minus`, `more-horizontal` |
|
|
561
|
+
| Status | `info`, `warning`, `error`, `success`, `help`, `loading` |
|
|
562
|
+
| Communication | `mail`, `bell`, `calendar`, `clock`, `message` |
|
|
563
|
+
| User / security | `user`, `users`, `lock`, `unlock`, `eye`, `eye-off` |
|
|
564
|
+
| Media | `play`, `pause`, `star`, `heart` |
|
|
565
|
+
|
|
566
|
+
Total: **49 glyphs.** Pack 2 (`files`) and Pack 3 (`editor`) are
|
|
567
|
+
proposed but not yet under contract — see [`roadmap/icons-proposal.md`](./roadmap/icons-proposal.md).
|
|
568
|
+
|
|
569
|
+
### Adding to the contract
|
|
570
|
+
|
|
571
|
+
A PR that adds a new contract glyph must:
|
|
572
|
+
|
|
573
|
+
1. Add the glyph name to `scripts/icon-contract.json → packs.<pack>.glyphs`.
|
|
574
|
+
2. Drop the SVG at `public/icons/<pack>/<glyph>.svg`.
|
|
575
|
+
3. Update this section's table.
|
|
576
|
+
4. Pass `npm run validate-icons`.
|
|
577
|
+
|
|
578
|
+
Per-theme override glyphs are NEVER required by the contract — themes
|
|
579
|
+
opt in glyph-by-glyph by declaring `--cia-icon-<name>` and shipping the
|
|
580
|
+
replacement file alongside.
|
package/GEMINI.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# GEMINI.md
|
|
2
|
+
|
|
3
|
+
This project is **css-is-awesome**, a token-driven SCSS design system.
|
|
4
|
+
|
|
5
|
+
For all rules, install, examples, and gotchas, read **[`AGENTS.md`](./AGENTS.md)** at the package root.
|
|
6
|
+
|
|
7
|
+
The deep authoring reference is **[`css-is-awesome.instructions.md`](./css-is-awesome.instructions.md)**.
|
|
8
|
+
|
|
9
|
+
Both ship inside the npm package, so you can read them at `node_modules/css-is-awesome/AGENTS.md` when working in a consumer project.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jerry2d3d
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|