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
package/package.json ADDED
@@ -0,0 +1,199 @@
1
+ {
2
+ "name": "css-is-awesome",
3
+ "version": "1.1.0",
4
+ "description": "A token-driven SCSS design system with light/dark theming, semantic color tokens, and a 800+ LOC mixin API.",
5
+ "homepage": "https://github.com/Jerry2d3d/css-is-awesome#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/Jerry2d3d/css-is-awesome/issues"
8
+ },
9
+ "main": "dist/css-is-awesome.css",
10
+ "style": "dist/css-is-awesome.css",
11
+ "sass": "scss/main.scss",
12
+ "bin": {
13
+ "css-is-awesome-mcp": "mcp/server.cjs",
14
+ "cia": "bin/cia.cjs"
15
+ },
16
+ "sideEffects": [
17
+ "**/*.css",
18
+ "**/*.scss"
19
+ ],
20
+ "exports": {
21
+ ".": {
22
+ "sass": "./scss/main.scss",
23
+ "style": "./dist/css-is-awesome.css",
24
+ "default": "./dist/css-is-awesome.css"
25
+ },
26
+ "./api": {
27
+ "sass": "./scss/api.scss"
28
+ },
29
+ "./api.scss": "./scss/api.scss",
30
+ "./core": "./dist/css-is-awesome.core.css",
31
+ "./core.css": "./dist/css-is-awesome.core.css",
32
+ "./tokens": "./dist/tokens.css",
33
+ "./tokens.css": "./dist/tokens.css",
34
+ "./tokens.d.ts": "./dist/tokens.d.ts",
35
+ "./utilities": "./dist/css-is-awesome.utilities.css",
36
+ "./utilities.css": "./dist/css-is-awesome.utilities.css",
37
+ "./min": "./dist/css-is-awesome.min.css",
38
+ "./min.css": "./dist/css-is-awesome.min.css",
39
+ "./css": "./dist/css-is-awesome.css",
40
+ "./css.css": "./dist/css-is-awesome.css",
41
+ "./scss": "./scss/main.scss",
42
+ "./scss/main": "./scss/main.scss",
43
+ "./scss/tokens": "./scss/tokens.scss",
44
+ "./scss/mixins": "./scss/_mixins.scss",
45
+ "./scss/generator": "./scss/_generator.scss",
46
+ "./scss/utilities": "./scss/_utilities.scss",
47
+ "./scss/animations": "./scss/_animations.scss",
48
+ "./scss/icons": "./scss/_icons.scss",
49
+ "./scss/layout": "./scss/_layout.scss",
50
+ "./scss/system": "./scss/_system.scss",
51
+ "./scss/theme": "./scss/theme/_index.scss",
52
+ "./scss/theme/*": "./scss/theme/_*.scss",
53
+ "./scss/components": "./scss/components/_index.scss",
54
+ "./scss/components/*": "./scss/components/_*.scss",
55
+ "./scss/recipes/*": "./scss/recipes/_*.scss",
56
+ "./scss/*": "./scss/*.scss",
57
+ "./theme": "./public/theme.css",
58
+ "./theme.css": "./public/theme.css",
59
+ "./themes/*": "./public/themes/*/theme.css",
60
+ "./figma-tokens": "./figma-tokens/tokens.json",
61
+ "./figma-tokens/*": "./figma-tokens/*",
62
+ "./package.json": "./package.json"
63
+ },
64
+ "files": [
65
+ "scss",
66
+ "api.scss",
67
+ "_index.scss",
68
+ "dist",
69
+ "figma-tokens",
70
+ "mcp",
71
+ "scripts/theme-contract.json",
72
+ "scripts/theme-validator.js",
73
+ "scripts/theme-a11y.js",
74
+ "scripts/icon-validator.js",
75
+ "scripts/icon-contract.json",
76
+ "bin",
77
+ "public/theme.css",
78
+ "public/themes",
79
+ "public/icons",
80
+ "README.md",
81
+ "CHANGELOG.md",
82
+ "LICENSE",
83
+ "LICENSE-third-party",
84
+ "css-is-awesome.instructions.md",
85
+ "AGENTS.md",
86
+ "CLAUDE.md",
87
+ "GEMINI.md",
88
+ "llm.txt",
89
+ "THREE-TIERS.md",
90
+ "THEMING.md",
91
+ "MIGRATION.md",
92
+ "CONTRACT.md",
93
+ "ROADMAP.md",
94
+ "VERSIONING.md",
95
+ "scripts/prepare-dist.mjs"
96
+ ],
97
+ "scripts": {
98
+ "dev": "next dev -p 5173",
99
+ "build": "next build",
100
+ "start": "next start -p 5173",
101
+ "lint": "next lint",
102
+ "lint:fix": "next lint --fix",
103
+ "lint:scss": "stylelint \"scss/**/*.scss\"",
104
+ "lint:scss:fix": "stylelint \"scss/**/*.scss\" --fix",
105
+ "build:css": "sass scss/main.scss dist/css-is-awesome.css --no-source-map",
106
+ "build:css:core": "sass scss/core.scss dist/css-is-awesome.core.css --no-source-map",
107
+ "build:css:tokens": "sass scss/tokens.scss dist/tokens.css --no-source-map",
108
+ "build:css:themes": "node scripts/build-themes.mjs && node scripts/build-theme-bundle.mjs",
109
+ "build:css:utilities": "sass scss/utilities-only.scss dist/css-is-awesome.utilities.css --no-source-map",
110
+ "build:css:min": "sass scss/main.scss dist/css-is-awesome.min.css --style=compressed --no-source-map && sass scss/core.scss dist/css-is-awesome.core.min.css --style=compressed --no-source-map && sass scss/tokens.scss dist/tokens.min.css --style=compressed --no-source-map && sass scss/utilities-only.scss dist/css-is-awesome.utilities.min.css --style=compressed --no-source-map",
111
+ "build:token-types": "node scripts/generate-token-types.mjs",
112
+ "dtcg-to-scss": "node scripts/dtcg-to-scss.mjs",
113
+ "build:css:all": "npm run build:css && npm run build:css:core && npm run build:css:tokens && npm run build:css:utilities && npm run build:css:themes && npm run build:css:min && npm run build:token-types",
114
+ "watch:css": "sass scss/main.scss dist/css-is-awesome.css --watch",
115
+ "validate-themes": "node scripts/theme-validator.js --all",
116
+ "validate-icons": "node scripts/icon-validator.js",
117
+ "validate-api": "node scripts/validate-api.mjs",
118
+ "validate-package": "node scripts/validate-package.mjs",
119
+ "validate-recipes": "node scripts/validate-recipes.mjs",
120
+ "size-budget": "node scripts/size-budget.mjs",
121
+ "size-report": "node scripts/size-budget.mjs --report",
122
+ "coverage:api": "node scripts/api-coverage.mjs",
123
+ "coverage:mcp": "node scripts/mcp-coverage.mjs",
124
+ "coverage": "npm run coverage:api && npm run coverage:mcp",
125
+ "pack:consumer": "node scripts/pack-to-consumer.mjs",
126
+ "test": "playwright test",
127
+ "test:update-snapshots": "playwright test --update-snapshots",
128
+ "playwright:install": "playwright install --with-deps",
129
+ "prepare": "node scripts/prepare-dist.mjs",
130
+ "prepublishOnly": "npm run build:css:all",
131
+ "check:theme-drift": "node scripts/check-theme-drift.mjs"
132
+ },
133
+ "keywords": [
134
+ "css",
135
+ "scss",
136
+ "sass",
137
+ "design-system",
138
+ "design-tokens",
139
+ "theming",
140
+ "dark-mode"
141
+ ],
142
+ "author": "Jerry2d3d",
143
+ "license": "MIT",
144
+ "repository": {
145
+ "type": "git",
146
+ "url": "git+https://github.com/Jerry2d3d/css-is-awesome.git"
147
+ },
148
+ "publishConfig": {
149
+ "access": "public"
150
+ },
151
+ "engines": {
152
+ "node": ">=20"
153
+ },
154
+ "peerDependencies": {
155
+ "@modelcontextprotocol/sdk": "^1.29.0",
156
+ "sass": "^1.77.0",
157
+ "zod": "^3.25.0 || ^4.0.0"
158
+ },
159
+ "peerDependenciesMeta": {
160
+ "sass": {
161
+ "optional": true
162
+ },
163
+ "@modelcontextprotocol/sdk": {
164
+ "optional": true
165
+ },
166
+ "zod": {
167
+ "optional": true
168
+ }
169
+ },
170
+ "devDependencies": {
171
+ "@axe-core/playwright": "^4.11.2",
172
+ "@eslint/eslintrc": "^3.2.0",
173
+ "@modelcontextprotocol/sdk": "^1.29.0",
174
+ "@playwright/test": "^1.59.1",
175
+ "@semantic-release/changelog": "^6.0.3",
176
+ "@semantic-release/commit-analyzer": "^13.0.0",
177
+ "@semantic-release/git": "^10.0.1",
178
+ "@semantic-release/github": "^11.0.0",
179
+ "@semantic-release/npm": "^12.0.1",
180
+ "@semantic-release/release-notes-generator": "^14.0.1",
181
+ "@types/node": "^22.0.0",
182
+ "@types/react": "^19.0.0",
183
+ "@types/react-dom": "^19.0.0",
184
+ "eslint": "^9.17.0",
185
+ "eslint-config-next": "^15.0.0",
186
+ "jiti": "^2.7.0",
187
+ "marked": "^15.0.12",
188
+ "next": "^15.0.0",
189
+ "react": "^19.0.0",
190
+ "react-dom": "^19.0.0",
191
+ "sass": "^1.97.1",
192
+ "semantic-release": "^24.2.0",
193
+ "serve": "^14.2.6",
194
+ "stylelint": "^17.8.0",
195
+ "stylelint-config-standard-scss": "^17.0.0",
196
+ "typescript": "^5.7.0",
197
+ "zod": "^3.25.0"
198
+ }
199
+ }
@@ -0,0 +1,278 @@
1
+ # Icons
2
+
3
+ The css-is-awesome icon system is mixin-first and pack-based. The
4
+ default `core` pack ships at `public/icons/core/` (49 Lucide-vendored
5
+ glyphs — see `LICENSE-third-party` for attribution).
6
+
7
+ ## The 30-second version
8
+
9
+ 1. Drop an SVG file into a pack folder (`public/icons/core/foo.svg`).
10
+ 2. Reference it anywhere: `@include m.svg(foo);`
11
+ 3. Style it with CSS. `currentColor` means it reskins automatically with `color:`.
12
+
13
+ That's the whole system. No registry file, no build step, no import list.
14
+
15
+ The full contract (resolution order, naming rules, override mechanism)
16
+ lives in [`CONTRACT.md` → Icons contract](../../CONTRACT.md#icons-contract).
17
+
18
+ ## Mixins
19
+
20
+ All mixins live in `scss/_icons.scss`. Bring them in via the `m.` namespace
21
+ (`@use 'mixins' as m;`) that the rest of the system uses.
22
+
23
+ ### `m.svg($name, $size: t.$theme-icon-size, $color: currentColor)`
24
+
25
+ Inline single-color icon. Renders via CSS `mask` + `background: currentColor`,
26
+ so the icon inherits the parent's `color`. Use for UI glyphs that should
27
+ tint with text.
28
+
29
+ ```scss
30
+ .btn-close {
31
+ @include m.svg(close);
32
+ color: var(--color-danger);
33
+ }
34
+ ```
35
+
36
+ Compiled CSS:
37
+
38
+ ```css
39
+ .btn-close {
40
+ display: inline-flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ width: 24px;
44
+ height: 24px;
45
+ color: var(--color-danger);
46
+ }
47
+ .btn-close::before {
48
+ content: '';
49
+ display: block;
50
+ width: 100%;
51
+ height: 100%;
52
+ background: currentColor;
53
+ mask: var(--cia-icon-x, url('/icons/core/x.svg')) center / contain no-repeat;
54
+ }
55
+ ```
56
+
57
+ ### `m.svg-bg($name, $size: t.$icon-size)`
58
+
59
+ SVG rendered as a plain `background-image`. No mask, no tint — the source
60
+ SVG's colors are preserved. Use for multi-color illustrations and brand
61
+ marks that should NOT become monochrome.
62
+
63
+ ```scss
64
+ .logo {
65
+ @include m.svg-bg(brand-mark, 48px);
66
+ }
67
+ ```
68
+
69
+ ### `m.svg-text($name, $size: 1em, $gap: 0.5em, $position: before)`
70
+
71
+ Icon + label in one flex row. The icon goes in `::before` (default) or
72
+ `::after`, with `gap` between them. `$size: 1em` means the icon scales
73
+ with the element's `font-size`.
74
+
75
+ ```scss
76
+ .btn-save {
77
+ @include m.svg-text(check); // icon-then-text, 0.5em gap
78
+ }
79
+
80
+ .btn-next {
81
+ @include m.svg-text(arrow-right, 1em, 0.5em, after);
82
+ }
83
+ ```
84
+
85
+ ## Config
86
+
87
+ All config lives in `scss/theme/_icons.scss` and is re-exported from
88
+ `scss/theme/_index.scss` as `t.$theme-*`.
89
+
90
+ ### Icon folder path
91
+
92
+ `$theme-icon-path` defaults to `/icons` and `$theme-icon-pack` defaults
93
+ to `core`, so `m.svg(foo)` resolves to `/icons/core/foo.svg` by default.
94
+ Each theme can override individual glyphs via `--cia-icon-<name>` custom
95
+ properties (preferred) or swap the entire pack folder by changing
96
+ `$theme-icon-path` / `$theme-icon-pack` — see "Per-theme icon packs"
97
+ below and `CONTRACT.md → Icons contract`.
98
+
99
+ ### Default icon size
100
+
101
+ `$theme-icon-size` defaults to `24px`. Used by `svg` and `fa-icon` when
102
+ you don't pass an explicit `$size`.
103
+
104
+ ### Alias map
105
+
106
+ `$theme-icon-svg-alias` remaps semantic names to real filenames. Ships
107
+ with a small default set:
108
+
109
+ ```scss
110
+ $icon-svg-alias: (
111
+ delete: 'trash',
112
+ close: 'x',
113
+ );
114
+ ```
115
+
116
+ With that map in place, `@include m.svg(delete);` resolves to
117
+ `/icons/trash.svg`. Add your own entries to keep call sites semantic
118
+ without renaming files.
119
+
120
+ ## Sizing
121
+
122
+ Two ways to size an icon:
123
+
124
+ 1. **Implicit (recommended for text-paired icons).** `svg-text` defaults
125
+ `$size` to `1em`, so the icon scales with `font-size`.
126
+
127
+ ```scss
128
+ .btn { font-size: 1.125rem; @include m.svg-text(check); } // icon is 18px
129
+ ```
130
+
131
+ 2. **Explicit.** Pass a `$size`:
132
+
133
+ ```scss
134
+ .nav-toggle { @include m.svg(menu, 32px); }
135
+ ```
136
+
137
+ ## Coloring
138
+
139
+ Set `color:` on the element (or any ancestor) and the icon follows. This
140
+ works because `svg` / `svg-text` render the glyph as a mask over
141
+ `background: currentColor`.
142
+
143
+ ```scss
144
+ .btn-danger { color: #e11; @include m.svg(delete); } // red trash icon
145
+ .btn-danger:hover { color: #a00; } // hover darkens
146
+ ```
147
+
148
+ If an icon isn't picking up the color, see Troubleshooting.
149
+
150
+ ## Mask vs background (svg vs svg-bg)
151
+
152
+ | Use case | Mixin |
153
+ |------------------------------------------|-------------|
154
+ | Single-color UI glyph that tints | `svg` |
155
+ | Multi-color illustration / brand mark | `svg-bg` |
156
+ | Icon paired with a text label | `svg-text` |
157
+
158
+ The `svg` path requires the source SVG to have no hardcoded `fill=` (or
159
+ have `fill="currentColor"`). If the SVG has baked-in colors, `svg` will
160
+ discard them (mask only cares about shape). Use `svg-bg` to keep them.
161
+
162
+ ## Aliases
163
+
164
+ `$theme-icon-svg-alias` is a `name → filename` map. It lets call sites
165
+ use semantic names while the file on disk stays neutral:
166
+
167
+ ```scss
168
+ // scss/theme/_icons.scss
169
+ $icon-svg-alias: (
170
+ delete: 'trash',
171
+ close: 'x',
172
+ primary-action: 'star-filled',
173
+ );
174
+ ```
175
+
176
+ ```scss
177
+ .btn-remove { @include m.svg(delete); } // loads /icons/trash.svg
178
+ ```
179
+
180
+ ## Per-theme icon packs
181
+
182
+ There are two ways a theme overrides icons. Pick whichever matches the
183
+ scope of the change.
184
+
185
+ ### Per-glyph (preferred — runtime CSS, no SCSS rebuild)
186
+
187
+ Drop replacement SVGs at `public/themes/<theme>/icons/<pack>/<name>.svg`
188
+ and declare a custom property in that theme's `:root` (or
189
+ `[data-theme="<theme>"]`) block:
190
+
191
+ ```css
192
+ [data-theme="sketchbook-light"] {
193
+ --cia-icon-search: url('/themes/sketchbook-light/icons/core/search.svg');
194
+ --cia-icon-x: url('/themes/sketchbook-light/icons/core/x.svg');
195
+ }
196
+ ```
197
+
198
+ Glyphs you don't override fall back to the bundled `core` pack
199
+ automatically. The mixin emits `var(--cia-icon-<name>, url(<core>))` —
200
+ the second argument is the fallback.
201
+
202
+ ### Pack-wide (compile-time SCSS swap)
203
+
204
+ If a theme replaces every glyph, override `$theme-icon-path` once and
205
+ ship the full set in the new folder:
206
+
207
+ ```scss
208
+ // themes/corporate/_icons.scss
209
+ $icon-path: '/themes/corporate/icons';
210
+ $icon-pack: 'core'; // keep the contract pack name
211
+ $icon-svg-alias: (
212
+ delete: 'bin',
213
+ close: 'dismiss',
214
+ );
215
+ ```
216
+
217
+ Drop the SVGs at `public/themes/corporate/icons/core/` and every
218
+ `@include m.svg(...)` in that theme's bundle resolves against the
219
+ corporate pack.
220
+
221
+ ## Font Awesome integration
222
+
223
+ Use the FA mixins when your project is already on Font Awesome (you have
224
+ a Pro license, a brand kit, or need thousands of glyphs you don't want to
225
+ curate by hand). Configure `$theme-fa-path`, `$theme-fa-style`, and
226
+ `$theme-icon-fa-map` in `scss/theme/_icons.scss`.
227
+
228
+ ### Self-hosted
229
+
230
+ Drop `fa-solid-900.woff2`, `fa-regular-400.woff2`, and
231
+ `fa-brands-400.woff2` into your `$theme-fa-path` folder (default
232
+ `/webfonts`), then call `fa-load` once:
233
+
234
+ ```scss
235
+ // main.scss
236
+ @include m.fa-load;
237
+ ```
238
+
239
+ ### CDN / kit
240
+
241
+ Skip `fa-load` entirely. Include FA's stylesheet in your HTML as normal;
242
+ the mixins below will pick up the already-registered font families.
243
+
244
+ ### FA mixins at a glance
245
+
246
+ ```scss
247
+ .icon-search { @include m.fa-icon(search); }
248
+ .btn-download { @include m.fa-text(download); }
249
+ .loader { @include m.fa-spin(spinner); }
250
+ ```
251
+
252
+ ## Authoring tips
253
+
254
+ - **Single-color glyph.** Export with `fill="currentColor"` (or no `fill`
255
+ at all). Use `m.svg` / `m.svg-text`. Drive the color from the parent's
256
+ `color:`.
257
+ - **Multi-color illustration.** Export with fills baked in. Use `m.svg-bg`.
258
+ `color:` has no effect.
259
+ - **Adding a new icon.** Save the file as `public/icons/<name>.svg` and
260
+ reference it with `@include m.svg(<name>);`. No manifest update needed.
261
+
262
+ ## Troubleshooting
263
+
264
+ - **Icon doesn't render.** Check `$theme-icon-path` resolves to a real URL
265
+ and the file exists (e.g. open `/icons/foo.svg` in the browser).
266
+ - **Icon renders black and won't pick up `color`.** The SVG has a hardcoded
267
+ `fill` attribute. Either remove the `fill` from the source, change it to
268
+ `currentColor`, or switch to `m.svg-bg`.
269
+ - **Icon is stretched or cropped.** `svg` / `svg-text` set `width` and
270
+ `height` to the same value. If your source SVG isn't square, wrap it in
271
+ a `<svg viewBox="...">` with matching width/height, or size it via
272
+ `svg-bg` with an explicit `background-size`.
273
+ - **Icon looks fuzzy on high-DPI.** Bump `$size`, or confirm the source is
274
+ a real SVG (not a rasterized PNG exported as `.svg`).
275
+ - **FA icon shows a box / wrong glyph.** `$theme-icon-fa-map` doesn't have
276
+ that name, or the FA font file for that style (solid/regular/brands)
277
+ isn't loaded. Check `fa-load` was called, or that your CDN include is
278
+ present.
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
3
+ <path d="M5 12h14m-6-6 6 6-6 6"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
3
+ <path d="M4 12l5 5L20 6"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
3
+ <path d="M6 9l6 6 6-6"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round">
3
+ <path d="M6 6l12 12M18 6L6 18"/>
4
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="M12 5v14" />
12
+ <path d="m19 12-7 7-7-7" />
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m12 19-7-7 7-7" />
12
+ <path d="M19 12H5" />
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="M5 12h14" />
12
+ <path d="m12 5 7 7-7 7" />
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m5 12 7-7 7 7" />
12
+ <path d="M12 19V5" />
13
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="M10.268 21a2 2 0 0 0 3.464 0" />
12
+ <path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" />
13
+ </svg>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="M8 2v4" />
12
+ <path d="M16 2v4" />
13
+ <rect width="18" height="18" x="3" y="4" rx="2" />
14
+ <path d="M3 10h18" />
15
+ </svg>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="M20 6 9 17l-5-5" />
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m6 9 6 6 6-6" />
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m15 18-6-6 6-6" />
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m9 18 6-6-6-6" />
12
+ </svg>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <path d="m18 15-6-6-6 6" />
12
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="2"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ >
11
+ <circle cx="12" cy="12" r="10" />
12
+ <path d="M12 6v6l4 2" />
13
+ </svg>