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.
Files changed (198) hide show
  1. package/AGENTS.md +343 -0
  2. package/CHANGELOG.md +1036 -0
  3. package/CLAUDE.md +9 -0
  4. package/CONTRACT.md +580 -0
  5. package/GEMINI.md +9 -0
  6. package/LICENSE +21 -0
  7. package/LICENSE-third-party +88 -0
  8. package/MIGRATION.md +312 -0
  9. package/README.md +380 -0
  10. package/ROADMAP.md +714 -0
  11. package/THEMING.md +290 -0
  12. package/THREE-TIERS.md +158 -0
  13. package/VERSIONING.md +200 -0
  14. package/_index.scss +34 -0
  15. package/api.scss +16 -0
  16. package/bin/README.md +57 -0
  17. package/bin/cia.cjs +114 -0
  18. package/bin/migrate-bootstrap.cjs +427 -0
  19. package/bin/migrate-tailwind.cjs +832 -0
  20. package/css-is-awesome.instructions.md +533 -0
  21. package/dist/css-is-awesome.core.css +598 -0
  22. package/dist/css-is-awesome.core.min.css +1 -0
  23. package/dist/css-is-awesome.css +3733 -0
  24. package/dist/css-is-awesome.min.css +1 -0
  25. package/dist/css-is-awesome.utilities.css +2445 -0
  26. package/dist/css-is-awesome.utilities.min.css +1 -0
  27. package/dist/tokens.css +508 -0
  28. package/dist/tokens.d.ts +266 -0
  29. package/dist/tokens.min.css +1 -0
  30. package/figma-tokens/README.md +57 -0
  31. package/figma-tokens/primitives-brand.scss +121 -0
  32. package/figma-tokens/semantic-dark.scss +61 -0
  33. package/figma-tokens/semantic-light.scss +61 -0
  34. package/figma-tokens/tokens.json +144 -0
  35. package/llm.txt +183 -0
  36. package/mcp/server.cjs +1495 -0
  37. package/package.json +199 -0
  38. package/public/icons/README.md +278 -0
  39. package/public/icons/arrow-right.svg +4 -0
  40. package/public/icons/check.svg +4 -0
  41. package/public/icons/chevron-down.svg +4 -0
  42. package/public/icons/close.svg +4 -0
  43. package/public/icons/core/arrow-down.svg +13 -0
  44. package/public/icons/core/arrow-left.svg +13 -0
  45. package/public/icons/core/arrow-right.svg +13 -0
  46. package/public/icons/core/arrow-up.svg +13 -0
  47. package/public/icons/core/bell.svg +13 -0
  48. package/public/icons/core/calendar.svg +15 -0
  49. package/public/icons/core/check.svg +12 -0
  50. package/public/icons/core/chevron-down.svg +12 -0
  51. package/public/icons/core/chevron-left.svg +12 -0
  52. package/public/icons/core/chevron-right.svg +12 -0
  53. package/public/icons/core/chevron-up.svg +12 -0
  54. package/public/icons/core/clock.svg +13 -0
  55. package/public/icons/core/close.svg +13 -0
  56. package/public/icons/core/copy.svg +13 -0
  57. package/public/icons/core/download.svg +14 -0
  58. package/public/icons/core/edit.svg +13 -0
  59. package/public/icons/core/error.svg +14 -0
  60. package/public/icons/core/external-link.svg +14 -0
  61. package/public/icons/core/eye-off.svg +15 -0
  62. package/public/icons/core/eye.svg +13 -0
  63. package/public/icons/core/filter.svg +12 -0
  64. package/public/icons/core/heart.svg +12 -0
  65. package/public/icons/core/help.svg +14 -0
  66. package/public/icons/core/home.svg +13 -0
  67. package/public/icons/core/info.svg +14 -0
  68. package/public/icons/core/loading.svg +12 -0
  69. package/public/icons/core/lock.svg +13 -0
  70. package/public/icons/core/mail.svg +13 -0
  71. package/public/icons/core/menu.svg +14 -0
  72. package/public/icons/core/message.svg +12 -0
  73. package/public/icons/core/minus.svg +12 -0
  74. package/public/icons/core/more-horizontal.svg +14 -0
  75. package/public/icons/core/pause.svg +13 -0
  76. package/public/icons/core/play.svg +12 -0
  77. package/public/icons/core/plus.svg +13 -0
  78. package/public/icons/core/refresh.svg +15 -0
  79. package/public/icons/core/save.svg +14 -0
  80. package/public/icons/core/search.svg +13 -0
  81. package/public/icons/core/settings.svg +13 -0
  82. package/public/icons/core/share.svg +14 -0
  83. package/public/icons/core/sort.svg +15 -0
  84. package/public/icons/core/star.svg +12 -0
  85. package/public/icons/core/success.svg +13 -0
  86. package/public/icons/core/trash.svg +16 -0
  87. package/public/icons/core/unlock.svg +13 -0
  88. package/public/icons/core/upload.svg +14 -0
  89. package/public/icons/core/user.svg +13 -0
  90. package/public/icons/core/users.svg +15 -0
  91. package/public/icons/core/warning.svg +14 -0
  92. package/public/icons/download.svg +4 -0
  93. package/public/icons/edit.svg +4 -0
  94. package/public/icons/menu.svg +4 -0
  95. package/public/icons/search.svg +4 -0
  96. package/public/theme.css +4179 -0
  97. package/public/themes/README.md +102 -0
  98. package/public/themes/boilerplate/theme.css +154 -0
  99. package/public/themes/boilerplate-dark/theme.css +171 -0
  100. package/public/themes/boilerplate-light/theme.css +171 -0
  101. package/public/themes/cupertino/theme.css +165 -0
  102. package/public/themes/cupertino-dark/theme.css +200 -0
  103. package/public/themes/cupertino-light/theme.css +227 -0
  104. package/public/themes/glass/theme.css +190 -0
  105. package/public/themes/glass-dark/theme.css +201 -0
  106. package/public/themes/glass-light/theme.css +229 -0
  107. package/public/themes/graphite/theme.css +155 -0
  108. package/public/themes/graphite-dark/theme.css +223 -0
  109. package/public/themes/graphite-light/theme.css +191 -0
  110. package/public/themes/press/theme.css +189 -0
  111. package/public/themes/press-dark/theme.css +199 -0
  112. package/public/themes/press-light/theme.css +235 -0
  113. package/public/themes/prism/theme.css +159 -0
  114. package/public/themes/prism-dark/theme.css +185 -0
  115. package/public/themes/prism-light/theme.css +188 -0
  116. package/public/themes/sketchbook/theme.css +152 -0
  117. package/public/themes/sketchbook-dark/theme.css +194 -0
  118. package/public/themes/sketchbook-light/theme.css +188 -0
  119. package/public/themes/terminal/theme.css +159 -0
  120. package/public/themes/terminal-dark/theme.css +229 -0
  121. package/public/themes/terminal-light/theme.css +152 -0
  122. package/scripts/README.md +70 -0
  123. package/scripts/icon-contract.json +67 -0
  124. package/scripts/icon-validator.js +205 -0
  125. package/scripts/prepare-dist.mjs +65 -0
  126. package/scripts/theme-a11y.js +415 -0
  127. package/scripts/theme-contract.json +171 -0
  128. package/scripts/theme-validator.js +674 -0
  129. package/scss/README.md +55 -0
  130. package/scss/_animations-utilities.scss +107 -0
  131. package/scss/_animations.scss +248 -0
  132. package/scss/_app-styles.scss +15 -0
  133. package/scss/_generator.scss +174 -0
  134. package/scss/_icons.scss +475 -0
  135. package/scss/_index.scss +17 -0
  136. package/scss/_layout.scss +597 -0
  137. package/scss/_mixins.scss +1036 -0
  138. package/scss/_system.scss +291 -0
  139. package/scss/_utilities.scss +377 -0
  140. package/scss/api.scss +61 -0
  141. package/scss/components/_accordion.scss +72 -0
  142. package/scss/components/_buttons.scss +171 -0
  143. package/scss/components/_copy-button.scss +69 -0
  144. package/scss/components/_data.scss +190 -0
  145. package/scss/components/_feedback.scss +197 -0
  146. package/scss/components/_forms.scss +272 -0
  147. package/scss/components/_index.scss +17 -0
  148. package/scss/components/_navigation.scss +186 -0
  149. package/scss/components/_overlay.scss +259 -0
  150. package/scss/components/_stepper.scss +159 -0
  151. package/scss/components/_tabs.scss +72 -0
  152. package/scss/core.scss +54 -0
  153. package/scss/examples/_theming.scss +107 -0
  154. package/scss/examples/_usage.scss +317 -0
  155. package/scss/main.scss +64 -0
  156. package/scss/recipes/README.md +110 -0
  157. package/scss/recipes/_bare-tags.scss +232 -0
  158. package/scss/recipes/_recipe-template.md +119 -0
  159. package/scss/recipes/combobox.md +509 -0
  160. package/scss/recipes/dialog.md +265 -0
  161. package/scss/recipes/print-to-pdf.md +263 -0
  162. package/scss/theme/README.md +67 -0
  163. package/scss/theme/_brand.scss +18 -0
  164. package/scss/theme/_colors-dark.scss +68 -0
  165. package/scss/theme/_colors-light.scss +70 -0
  166. package/scss/theme/_components.scss +94 -0
  167. package/scss/theme/_icons.scss +104 -0
  168. package/scss/theme/_index.scss +62 -0
  169. package/scss/theme/_shadows.scss +65 -0
  170. package/scss/theme/_shape.scss +13 -0
  171. package/scss/theme/_typography.scss +9 -0
  172. package/scss/theme/registry.json +447 -0
  173. package/scss/themes/boilerplate-dark.scss +212 -0
  174. package/scss/themes/boilerplate-light.scss +209 -0
  175. package/scss/themes/boilerplate.scss +181 -0
  176. package/scss/themes/cupertino-dark.scss +238 -0
  177. package/scss/themes/cupertino-light.scss +266 -0
  178. package/scss/themes/cupertino.scss +194 -0
  179. package/scss/themes/glass-dark.scss +238 -0
  180. package/scss/themes/glass-light.scss +266 -0
  181. package/scss/themes/glass.scss +220 -0
  182. package/scss/themes/graphite-dark.scss +260 -0
  183. package/scss/themes/graphite-light.scss +228 -0
  184. package/scss/themes/graphite.scss +182 -0
  185. package/scss/themes/press-dark.scss +237 -0
  186. package/scss/themes/press-light.scss +273 -0
  187. package/scss/themes/press.scss +241 -0
  188. package/scss/themes/prism-dark.scss +217 -0
  189. package/scss/themes/prism-light.scss +220 -0
  190. package/scss/themes/prism.scss +190 -0
  191. package/scss/themes/sketchbook-dark.scss +231 -0
  192. package/scss/themes/sketchbook-light.scss +231 -0
  193. package/scss/themes/sketchbook.scss +178 -0
  194. package/scss/themes/terminal-dark.scss +267 -0
  195. package/scss/themes/terminal-light.scss +175 -0
  196. package/scss/themes/terminal.scss +185 -0
  197. package/scss/tokens.scss +23 -0
  198. package/scss/utilities-only.scss +4 -0
@@ -0,0 +1,317 @@
1
+ // ============================================================================
2
+ // EXAMPLES - Icon Systems + Core Mixins
3
+ // ============================================================================
4
+ @use '../mixins' as m;
5
+ @use '../icons' as i;
6
+ @use '../theme' as t;
7
+
8
+ // ============================================================================
9
+ // SVG ICONS - Folder Based (No Config Needed!)
10
+ // ============================================================================
11
+ // Just drop .svg files into your $icon-path folder
12
+ // Filename = icon name
13
+ //
14
+ // Folder: /assets/icons/
15
+ // arrow.svg → @include i.svg(arrow)
16
+ // search.svg → @include i.svg(search)
17
+ // my-custom.svg → @include i.svg(my-custom)
18
+ //
19
+ // That's it. No map to update. Just add files and rebuild.
20
+ // ============================================================================
21
+
22
+ // Basic icons - uses filename directly
23
+ .icon-search { @include i.svg(search); }
24
+ .icon-arrow { @include i.svg(arrow); }
25
+ .icon-menu { @include i.svg(menu, 28px); }
26
+ .icon-close { @include i.svg(close, 20px, m.color(text-muted)); }
27
+
28
+ // Custom size and color
29
+ .icon-large { @include i.svg(settings, 48px, m.color(brand-primary)); }
30
+
31
+ // Multi-color SVG (as background, not colorable)
32
+ .logo { @include i.svg-bg(logo, 120px); }
33
+
34
+ // Icon with text (buttons, links)
35
+ .btn-download { @include i.svg-text(download); }
36
+ .btn-next { @include i.svg-text(arrow-right, $position: after); }
37
+
38
+ // ALIASING (optional - only when filename ≠ desired name)
39
+ // In _theme.scss:
40
+ // $icon-svg-alias: (
41
+ // delete: 'trash', // @include i.svg(delete) → uses trash.svg
42
+ // close: 'x', // @include i.svg(close) → uses x.svg
43
+ // );
44
+ //
45
+ // Most of the time you don't need aliases.
46
+ // Just name your SVG files what you want to call them.
47
+
48
+ // ============================================================================
49
+ // FONT AWESOME ICONS
50
+ // ============================================================================
51
+ // Configure $fa-path and $icon-fa-map in _theme.scss
52
+ // Load fonts with @include i.fa-load; in main.scss (if self-hosting)
53
+
54
+ // Basic FA icon (use inside ::before or ::after)
55
+ .fa-example::before {
56
+ @include i.fa(check);
57
+ }
58
+
59
+ // With size
60
+ .fa-large::before {
61
+ @include i.fa(star, solid, 24px);
62
+ }
63
+
64
+ // Different styles
65
+ .fa-outline::before {
66
+ @include i.fa(heart, regular); // Outline style
67
+ }
68
+
69
+ .fa-brand::before {
70
+ @include i.fa(github, brands); // Brand icon
71
+ }
72
+
73
+ // FA as standalone element
74
+ .icon-user { @include i.fa-icon(user); }
75
+ .icon-bell { @include i.fa-icon(bell, 20px); }
76
+ .icon-warning { @include i.fa-icon(warning, 24px, solid, m.color(warning-default)); }
77
+
78
+ // FA icon with text (buttons, links)
79
+ .btn-save { @include i.fa-text(save); }
80
+ .btn-external { @include i.fa-text(external, $position: after); }
81
+ .btn-delete { @include i.fa-text(delete, $size: 0.875em, $gap: 0.5em); }
82
+
83
+ // Spinning loader
84
+ .loading { @include i.fa-spin(spinner); }
85
+ .loading-large { @include i.fa-spin(spinner, 32px); }
86
+
87
+ // Adding custom FA icons:
88
+ // 1. Find unicode at https://fontawesome.com/search
89
+ // 2. Add to $icon-fa-map in _theme.scss:
90
+ // my-icon: '\f123',
91
+ // 3. Use it:
92
+ // @include i.fa(my-icon);
93
+
94
+ // ============================================================================
95
+ // REAL COMPONENT EXAMPLES
96
+ // ============================================================================
97
+
98
+ // Button with SVG icon
99
+ .btn-primary {
100
+ @include m.btn-base;
101
+ @include i.svg-text(arrow-right, $position: after);
102
+ background: m.color(brand-primary);
103
+ color: m.color(text-inverse);
104
+
105
+ &:hover { background: m.color(brand-primary-hover); }
106
+ }
107
+
108
+ // Button with FA icon
109
+ .btn-secondary {
110
+ @include m.btn-base;
111
+ @include i.fa-text(download);
112
+ background: transparent;
113
+ @include m.border;
114
+
115
+ &:hover { background: m.color(interactive-hover); }
116
+ }
117
+
118
+ // Icon-only button (SVG)
119
+ .btn-icon {
120
+ @include m.button-reset;
121
+ @include m.flex($justify: center);
122
+ @include i.svg(close, 20px);
123
+ width: 40px;
124
+ height: 40px;
125
+ border-radius: m.radius(full);
126
+ @include m.transition(background-color);
127
+
128
+ &:hover { background: m.color(interactive-hover); }
129
+ }
130
+
131
+ // Icon-only button (FA)
132
+ .btn-icon-fa {
133
+ @include m.button-reset;
134
+ @include m.flex($justify: center);
135
+ @include i.fa-icon(settings, 20px);
136
+ width: 40px;
137
+ height: 40px;
138
+ border-radius: m.radius(full);
139
+ @include m.transition(background-color);
140
+
141
+ &:hover { background: m.color(interactive-hover); }
142
+ }
143
+
144
+ // Alert with FA icon — single-class router pattern (no BEM modifiers).
145
+ // Variant lives in the class name, not as a `--modifier`. The base mixin
146
+ // stays a base; status-specific styling is its own standalone class.
147
+ .alert {
148
+ @include m.card-base($p: sm);
149
+ @include m.flex($gap: sm);
150
+ }
151
+
152
+ .alert-info {
153
+ background: m.color(info-subtle);
154
+ @include m.border(3px, solid, info-default, left);
155
+
156
+ &::before {
157
+ @include i.fa(info, solid, 1.25em);
158
+ color: m.color(info-default);
159
+ }
160
+ }
161
+
162
+ .alert-success {
163
+ background: m.color(success-subtle);
164
+ @include m.border(3px, solid, success-default, left);
165
+
166
+ &::before {
167
+ @include i.fa(check, solid, 1.25em);
168
+ color: m.color(success-default);
169
+ }
170
+ }
171
+
172
+ .alert-warning {
173
+ background: m.color(warning-subtle);
174
+ @include m.border(3px, solid, warning-default, left);
175
+
176
+ &::before {
177
+ @include i.fa(warning, solid, 1.25em);
178
+ color: m.color(warning-default);
179
+ }
180
+ }
181
+
182
+ .alert-error {
183
+ background: m.color(error-subtle);
184
+ @include m.border(3px, solid, error-default, left);
185
+
186
+ &::before {
187
+ @include i.fa(error, solid, 1.25em);
188
+ color: m.color(error-default);
189
+ }
190
+ }
191
+
192
+ // Input with icon
193
+ .input-search {
194
+ position: relative;
195
+
196
+ input {
197
+ @include m.input-base;
198
+ padding-left: m.space(xl);
199
+ }
200
+
201
+ &::before {
202
+ content: '';
203
+ position: absolute;
204
+ left: m.space(sm);
205
+ top: 50%;
206
+ transform: translateY(-50%);
207
+ @include i.svg(search, 20px);
208
+ color: m.color(text-muted);
209
+ pointer-events: none;
210
+ }
211
+ }
212
+
213
+ // Navbar with icons — single-class child elements, not BEM `__element`.
214
+ // Author-side code names its own classes (`navbar-logo`, `navbar-menu-btn`).
215
+ .navbar {
216
+ @include m.flex($justify: between);
217
+ @include m.pad-y(sm);
218
+ @include m.pad-x(md);
219
+ @include m.border(1px, solid, border-default, bottom);
220
+ }
221
+
222
+ .navbar-logo {
223
+ @include i.svg-bg(logo, 32px);
224
+ }
225
+
226
+ .navbar-menu-btn {
227
+ @include m.button-reset;
228
+ @include i.svg(menu, 24px);
229
+
230
+ @include m.tablet {
231
+ display: none;
232
+ }
233
+ }
234
+
235
+ // Social links with FA brands
236
+ .social-links {
237
+ @include m.flex($gap: md);
238
+
239
+ a {
240
+ @include m.button-reset;
241
+ color: m.color(text-secondary);
242
+ @include m.hover(color, m.color(text-primary));
243
+
244
+ &.github::before { @include i.fa(github, brands, 24px); }
245
+ &.twitter::before { @include i.fa(twitter, brands, 24px); }
246
+ &.linkedin::before { @include i.fa(linkedin, brands, 24px); }
247
+ }
248
+ }
249
+
250
+ // ============================================================================
251
+ // CORE MIXINS EXAMPLES
252
+ // ============================================================================
253
+
254
+ // Font - tokens or values
255
+ .heading { @include m.font(bold, xl, tight); }
256
+ .body { @include m.font(reg, base, normal); }
257
+ .custom { @include m.font(semibold, 1.5rem, 1.4, -0.01em); }
258
+
259
+ // Spacing
260
+ .section {
261
+ @include m.pad(lg);
262
+ @include m.flex($direction: column, $gap: md);
263
+ }
264
+
265
+ // Borders
266
+ .bordered { @include m.border; }
267
+ .underlined { @include m.border(2px, solid, brand-primary, bottom); }
268
+
269
+ // Breakpoints
270
+ .responsive {
271
+ @include m.mobile-only { font-size: 14px; }
272
+ @include m.tablet { font-size: 16px; }
273
+ @include m.desktop { font-size: 18px; }
274
+ }
275
+
276
+ // Component bases
277
+ .btn { @include m.btn-base; }
278
+ .card { @include m.card-base; }
279
+ .input { @include m.input-base; }
280
+ .badge { @include m.badge-base; }
281
+
282
+ // ============================================================================
283
+ // CHEAT SHEET
284
+ // ============================================================================
285
+
286
+ /*
287
+ SVG ICONS (folder-based):
288
+ 1. Drop file in /assets/icons/ folder
289
+ 2. Use filename as icon name:
290
+ arrow.svg → @include i.svg(arrow)
291
+
292
+ @include i.svg(name, size?, color?)
293
+ @include i.svg-bg(name, size?) → Multi-color SVGs
294
+ @include i.svg-text(name, size?, gap?, position?)
295
+
296
+ Optional alias (in _theme.scss):
297
+ $icon-svg-alias: (delete: 'trash') → delete uses trash.svg
298
+
299
+ FONT AWESOME:
300
+ @include i.fa(name, style?, size?) → Inside ::before/::after
301
+ @include i.fa-icon(name, size?, style?, color?)
302
+ @include i.fa-text(name, size?, gap?, style?, position?)
303
+ @include i.fa-spin(name, size?, style?)
304
+ @include i.fa-load → Load fonts (self-hosted)
305
+
306
+ FA STYLES:
307
+ solid → Filled (default)
308
+ regular → Outline
309
+ brands → Logos (github, twitter)
310
+
311
+ CORE MIXINS:
312
+ m.color(name) m.space(n) m.radius(size)
313
+ m.font(type, ...) m.border(...) m.elevation(level)
314
+ m.transition(...) m.flex($justify, $gap, $direction, ...)
315
+ m.pad(size) m.pad-asym(y, x)
316
+ m.btn-base(...) m.card-base(...) m.input-base(...)
317
+ */
package/scss/main.scss ADDED
@@ -0,0 +1,64 @@
1
+ // ============================================================================
2
+ // MAIN - Entry Point
3
+ // ============================================================================
4
+ // This generates the actual CSS output.
5
+ // Import this once at your app's root.
6
+ // ============================================================================
7
+ @use './generator';
8
+ @use './mixins' as m;
9
+ @use './animations';
10
+ @use './animations-utilities';
11
+ @use './utilities';
12
+
13
+ // ----------------------------------------------------------------------------
14
+ // GENERATE CSS VARIABLES
15
+ // ----------------------------------------------------------------------------
16
+ @include generator.generate-theme;
17
+
18
+ // ----------------------------------------------------------------------------
19
+ // BASE STYLES (Optional - include what you need)
20
+ // ----------------------------------------------------------------------------
21
+ *,
22
+ *::before,
23
+ *::after {
24
+ box-sizing: border-box;
25
+ }
26
+
27
+ html {
28
+ -webkit-font-smoothing: antialiased;
29
+ -moz-osx-font-smoothing: grayscale;
30
+ }
31
+
32
+ body {
33
+ margin: 0;
34
+ font-family: m.font-family(primary);
35
+ font-size: m.font-size(base);
36
+ line-height: m.line-height(normal);
37
+ color: m.color(text-primary);
38
+ background: m.color(surface-default);
39
+ }
40
+
41
+ // Resets
42
+ @include m.header-reset;
43
+ @include m.form-reset;
44
+
45
+ // Links
46
+ a {
47
+ color: m.color(text-link);
48
+ text-decoration: none;
49
+ @include m.transition(color);
50
+
51
+ &:hover {
52
+ color: m.color(text-link-hover);
53
+ }
54
+ }
55
+
56
+ // Focus visible
57
+ :focus-visible {
58
+ outline: 2px solid m.color(border-focus);
59
+ outline-offset: 2px;
60
+ }
61
+
62
+ :focus:not(:focus-visible) {
63
+ outline: none;
64
+ }
@@ -0,0 +1,110 @@
1
+ # cia Recipes — Format + Authoring Guide
2
+
3
+ Recipes are cia's framework-agnostic patterns for building components. Each recipe is a single markdown file under `scss/recipes/`. Recipes ship in the npm package and are exposed to AI agents via the MCP server (`list_recipes`, `get_recipe`, `assemble_prompt`).
4
+
5
+ > **The recipe IS the deliverable.** cia does not ship a component library. Recipes give consumers (and AI agents) the pattern — they generate or copy the component in their own framework + selector vocabulary.
6
+
7
+ ## File naming
8
+
9
+ - **Real recipes:** `<slug>.md` — kebab-case slug becomes the URL at `/docs/recipes/<slug>` and the MCP `get_recipe(slug)` key
10
+ - **Template / not-renderable:** `_<name>.md` — underscore prefix; catalog page + MCP loader skip these
11
+
12
+ ## Required frontmatter
13
+
14
+ Every recipe begins with YAML frontmatter:
15
+
16
+ ```yaml
17
+ ---
18
+ name: dialog
19
+ description: Accessible modal dialog built on <dialog>.
20
+ category: overlay
21
+ complexity: medium
22
+ cia-version: ">=1.0.0"
23
+ ---
24
+ ```
25
+
26
+ | Field | Type | Notes |
27
+ |---|---|---|
28
+ | `name` | string | Must match the filename slug |
29
+ | `description` | string | One sentence — what this recipe builds, no more |
30
+ | `category` | enum | One of: `overlay`, `input`, `data`, `navigation`, `feedback`, `layout`, `auth` |
31
+ | `complexity` | enum | One of: `simple`, `medium`, `complex` |
32
+ | `cia-version` | semver range | Minimum cia version this recipe targets |
33
+
34
+ ## Required H2 sections (in this order)
35
+
36
+ ```markdown
37
+ ## Use this when
38
+ ## Structure (raw HTML)
39
+ ## Styling (cia mixins)
40
+ ## Interactivity
41
+ ## A11y checklist
42
+ ## Framework examples
43
+ ```
44
+
45
+ Each section's purpose:
46
+
47
+ - **Use this when** — 1-3 sentences describing the consumer scenario. If the reader's situation doesn't match, they should bail and look elsewhere.
48
+ - **Structure (raw HTML)** — the markup with `data-cia-recipe` / `data-slot` attributes. Framework-agnostic; consumer adapts to JSX / template / Svelte syntax.
49
+ - **Styling (cia mixins)** — SCSS using `cia.X` mixin calls against consumer-chosen class names, opened with `@use 'css-is-awesome/api' as cia;` (see [Import convention](#import-convention)). Show the minimum to make it work; cross-link to mixin docs for parameter detail.
50
+ - **Interactivity** — native browser behavior first (`<dialog>.showModal()`, popover API, etc.). JS only where the native primitive can't do the job.
51
+ - **A11y checklist** — concrete, testable items. Each item references the WCAG SC or ARIA pattern it satisfies.
52
+ - **Framework examples** — minimum **4 subsections**: React, Vue, Svelte, vanilla (Web Component preferred for vanilla). Each is runnable code, not pseudocode.
53
+
54
+ ## Optional H2 sections
55
+
56
+ - **Variants** — common adaptations (size, density, position). One sub-block per variant with the styling delta.
57
+ - **Pitfalls** — known gotchas (SSR, browser compat, focus management edge cases). One bullet per pitfall.
58
+ - **Related recipes** — cross-link to other recipes in the catalog.
59
+
60
+ ## Import convention
61
+
62
+ **Two imports, two jobs.** A recipe's `scss` blocks are component-level styling, so they open with the **zero-emit authoring barrel**:
63
+
64
+ ```scss
65
+ @use 'css-is-awesome/api' as cia;
66
+ ```
67
+
68
+ `/api` forwards the entire mixin + function API and emits **zero CSS** until a mixin is called, which makes it safe inside a `.module.scss` under Next.js CSS Modules pure mode.
69
+
70
+ - ❌ **Never** `@use 'css-is-awesome'` in a component styling block. That is the emitting bundle — it prints `:root` tokens, resets and base rules, and a top-level `:root` is a hard build error in CSS Modules pure mode.
71
+ - ✅ `@use 'css-is-awesome'` is only correct in a **root/global** stylesheet, where the tokens are emitted exactly once. If a recipe demonstrates a global stylesheet, label the block with a filename comment (`// app/globals.scss`) so the reader can tell which half of the model they're looking at.
72
+ - Some mixins emit at the root themselves — `cia.print-base` emits a `:root` block plus `@page`. They are still imported from `/api`; what changes is *placement*. Say in prose that they belong at the top level of a global stylesheet, never in a component module. See [`print-to-pdf.md`](./print-to-pdf.md) for the worked example.
73
+ - Recipes stay on `/api` on every toolchain, Turbopack included — the barrel works there. Setup notes for Next.js live in the root [`README.md`](../../README.md).
74
+
75
+ ## Code-block standards
76
+
77
+ - Fenced blocks with language tag — `html`, `scss`, `tsx`, `vue`, `svelte`, `js`
78
+ - Component styling blocks open with `@use 'css-is-awesome/api' as cia;` — see [Import convention](#import-convention)
79
+ - Use the cia mixin API verbatim — never inline raw token values
80
+ - Class names in examples use the convention `my-<thing>` (signals "your selector here") — never `cia-<thing>` (that prefix is library-owned)
81
+ - Each framework example targets a single component, not a full app
82
+
83
+ ## Forbidden in recipes
84
+
85
+ - ❌ `@use 'css-is-awesome'` (the emitting bundle) in a component styling block — use `css-is-awesome/api`, see [Import convention](#import-convention)
86
+ - ❌ `cia-` class names (that prefix belongs to the library, not consumer code)
87
+ - ❌ BEM (`__element` / `--modifier`) — see [`feedback_no_bem.md`](../../README.md) project rule
88
+ - ❌ Hard-coded `#hex`, `1rem`, `8px` — use `m.color()`, `m.space()`, `m.radius()`
89
+ - ❌ Inline `style=""` for **appearance** — colour, spacing, type, borders. That defeats the cia mixin pitch, and a reader copying it learns the wrong lesson.
90
+ - ✅ Allowed for **structural layout-neutralising** only, where an element is required by the HTML contract but must not create a box. The canonical case is `<form method="dialog" style="display: contents">` in `dialog.md`: the form has to wrap the buttons for dialog-close to work, but it must not become a layout box. There is no token or mixin involved and no appearance is being set. `validate-recipes` warns on every inline `style=` so each one stays a conscious decision.
91
+ - ❌ Pseudo-code framework examples ("// import your stuff here")
92
+
93
+ ## How a recipe gets rendered + consumed
94
+
95
+ - **Humans:** The cia website's `/docs/recipes/[slug]` page reads `scss/recipes/<slug>.md`, parses the markdown, renders with syntax highlighting + copy buttons. Catalog page at `/docs/recipes` lists every recipe filtered by category + complexity.
96
+ - **AI agents:** The MCP server exposes `list_recipes`, `get_recipe(slug)`, and `assemble_prompt({ intent: "recipe:<slug>" })`. AI reads the recipe + relevant mixin signatures and generates the consumer's component in their stack.
97
+
98
+ ## Validation
99
+
100
+ `npm run validate-recipes` (US-01.1.3 in v1.0 EPIC-01) walks `scss/recipes/*.md`, checks frontmatter against the schema, asserts required H2s exist, and verifies no forbidden patterns appear. Wired into CI for v1.0.
101
+
102
+ ## Template
103
+
104
+ Copy `_recipe-template.md` to `<your-slug>.md` and fill in. The template includes every required section with comments explaining what to write.
105
+
106
+ ## Where to read next
107
+
108
+ - [`_recipe-template.md`](./_recipe-template.md) — copyable stub
109
+ - [`dialog.md`](./dialog.md) — first shipped recipe; reference example
110
+ - [`../../roadmap/epics/v1-0/EPIC-01-recipes-book.md`](../../roadmap/epics/v1-0/EPIC-01-recipes-book.md) — v1.0 backlog for the first 5 recipes + catalog + MCP exposure