@codecademy/gamut 68.6.0 → 68.6.1-alpha.edab62.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 (35) hide show
  1. package/agent-tools/.claude-plugin/marketplace.json +16 -0
  2. package/agent-tools/.claude-plugin/plugin.json +7 -0
  3. package/agent-tools/.cursor-plugin/plugin.json +7 -0
  4. package/agent-tools/DESIGN.Codecademy.md +643 -0
  5. package/agent-tools/DESIGN.LXStudio.md +444 -0
  6. package/agent-tools/DESIGN.Percipio.md +435 -0
  7. package/agent-tools/DESIGN.md +1 -0
  8. package/agent-tools/agents/.gitkeep +0 -0
  9. package/agent-tools/commands/gamut-review.md +170 -0
  10. package/agent-tools/guidelines/components/buttons.md +44 -0
  11. package/agent-tools/guidelines/components/overview.md +44 -0
  12. package/agent-tools/guidelines/foundations/color.md +86 -0
  13. package/agent-tools/guidelines/foundations/modes.md +45 -0
  14. package/agent-tools/guidelines/foundations/spacing.md +66 -0
  15. package/agent-tools/guidelines/foundations/typography.md +50 -0
  16. package/agent-tools/guidelines/overview.md +35 -0
  17. package/agent-tools/guidelines/setup.md +42 -0
  18. package/agent-tools/rules/accessibility.mdc +69 -0
  19. package/agent-tools/skills/gamut-accessibility/SKILL.md +239 -0
  20. package/agent-tools/skills/gamut-color-mode/SKILL.md +99 -0
  21. package/agent-tools/skills/gamut-system-props/SKILL.md +173 -0
  22. package/agent-tools/skills/gamut-testing/SKILL.md +181 -0
  23. package/agent-tools/skills/gamut-theming/SKILL.md +113 -0
  24. package/agent-tools/skills/gamut-typography/SKILL.md +123 -0
  25. package/bin/commands/plugin/install.mjs +173 -0
  26. package/bin/commands/plugin/list.mjs +105 -0
  27. package/bin/commands/plugin/remove.mjs +116 -0
  28. package/bin/commands/plugin/update.mjs +49 -0
  29. package/bin/gamut.mjs +92 -0
  30. package/bin/lib/claude.mjs +52 -0
  31. package/bin/lib/cursor.mjs +40 -0
  32. package/bin/lib/figma.mjs +49 -0
  33. package/bin/lib/resolve-plugin-dir.mjs +38 -0
  34. package/bin/lib/run-command.mjs +22 -0
  35. package/package.json +11 -8
@@ -0,0 +1,435 @@
1
+ ---
2
+ version: alpha
3
+ name: Percipio Design System
4
+ description: Design tokens for the Skillsoft Percipio platform.
5
+ colors:
6
+ # palette — raw swatches; set once on :root and then always reference by token name, never use hex values directly in code
7
+ percipioTextPrimary: "#222325"
8
+ percipioTextSecondary: "#595A5C"
9
+ percipioTextDisabled: "#AFB6C2"
10
+ percipioActionPrimary: "#0073C4"
11
+ percipioActionPrimaryHover: "#141C36"
12
+ percipioActionSecondary: "#6A6E75"
13
+ percipioActionSecondaryHover: "#7F8288"
14
+ percipioActionDangerHover: "#A52020"
15
+ percipioDanger: "#B83C3C"
16
+ percipioFeedbackSuccess: "#1B8057"
17
+ percipioFeedbackWarning: "#EF5B0D"
18
+ percipioBgPrimary: "#FAFBFC"
19
+ percipioBgSuccess: "#EEF7F3"
20
+ percipioBgWarning: "#FFF7E0"
21
+ percipioBgError: "#FFF1F5"
22
+ navy-800: "#10162F"
23
+ navy-400: "#8F919D"
24
+ navy-300: "#BCBEC5"
25
+ navy-200: "#E2E3E6"
26
+ navy-100: "#F5F6F7"
27
+ white: "#ffffff"
28
+ # semantic aliases — use these in code, not palette swatches or hex values
29
+ text: "{colors.percipioTextPrimary}"
30
+ text-accent: "{colors.percipioTextPrimary}"
31
+ text-secondary: "{colors.percipioTextSecondary}"
32
+ text-disabled: "{colors.percipioTextDisabled}"
33
+ background: "{colors.white}"
34
+ background-primary: "{colors.percipioBgPrimary}"
35
+ background-selected: "{colors.navy-100}"
36
+ background-hover: "{colors.navy-200}"
37
+ background-disabled: "{colors.navy-200}"
38
+ background-success: "{colors.percipioBgSuccess}"
39
+ background-warning: "{colors.percipioBgWarning}"
40
+ background-error: "{colors.percipioBgError}"
41
+ primary: "{colors.percipioActionPrimary}"
42
+ primary-hover: "{colors.percipioActionPrimaryHover}"
43
+ primary-inverse: "{colors.white}"
44
+ secondary: "{colors.percipioActionSecondary}"
45
+ secondary-hover: "{colors.percipioActionSecondaryHover}"
46
+ interface: "{colors.percipioActionPrimary}"
47
+ interface-hover: "{colors.percipioActionPrimaryHover}"
48
+ danger: "{colors.percipioDanger}"
49
+ danger-hover: "{colors.percipioActionDangerHover}"
50
+ feedback-error: "{colors.percipioDanger}"
51
+ feedback-success: "{colors.percipioFeedbackSuccess}"
52
+ feedback-warning: "{colors.percipioFeedbackWarning}"
53
+ border-primary: "{colors.navy-400}"
54
+ border-secondary: "{colors.navy-200}"
55
+ border-tertiary: "{colors.navy-800}"
56
+ border-disabled: "{colors.navy-300}"
57
+ shadow-primary: "{colors.navy-200}"
58
+ shadow-secondary: "{colors.navy-400}"
59
+ typography:
60
+ base:
61
+ fontFamily: '"Roboto", sans-serif'
62
+ fontSize: "1rem"
63
+ fontWeight: "400"
64
+ lineHeight: "1.5"
65
+ accent:
66
+ fontFamily: '"Roboto", sans-serif'
67
+ fontSize: "0.875rem"
68
+ fontWeight: "400"
69
+ lineHeight: "1.5"
70
+ title:
71
+ fontFamily: '"Roboto", sans-serif'
72
+ fontSize: "2.125rem"
73
+ fontWeight: "500"
74
+ lineHeight: "1.2"
75
+ monospace:
76
+ fontFamily: '"Roboto Mono", monospace'
77
+ components:
78
+ FillButton:
79
+ backgroundColor: "{colors.primary}"
80
+ textColor: "{colors.primary-inverse}"
81
+ rounded: "{rounded.md}"
82
+ FillButton-hover:
83
+ backgroundColor: "{colors.primary-hover}"
84
+ textColor: "{colors.primary-inverse}"
85
+ FillButton-danger:
86
+ backgroundColor: "{colors.danger}"
87
+ textColor: "{colors.white}"
88
+ rounded: "{rounded.md}"
89
+ FillButton-danger-hover:
90
+ backgroundColor: "{colors.danger-hover}"
91
+ textColor: "{colors.white}"
92
+ StrokeButton:
93
+ backgroundColor: "transparent"
94
+ textColor: "{colors.secondary}"
95
+ rounded: "{rounded.md}"
96
+ Input:
97
+ backgroundColor: "{colors.background}"
98
+ textColor: "{colors.text}"
99
+ rounded: "{rounded.md}"
100
+ borderColor: "{colors.border-primary}"
101
+ Checkbox:
102
+ backgroundColor: "{colors.interface}"
103
+ rounded: "{rounded.sm}"
104
+ Checkbox-hover:
105
+ backgroundColor: "{colors.interface-hover}"
106
+ Alert-error:
107
+ backgroundColor: "{colors.background-error}"
108
+ textColor: "{colors.feedback-error}"
109
+ Alert-success:
110
+ backgroundColor: "{colors.background-success}"
111
+ textColor: "{colors.text}"
112
+ Alert-warning:
113
+ backgroundColor: "{colors.background-warning}"
114
+ textColor: "{colors.text}"
115
+ ---
116
+
117
+ # Percipio
118
+
119
+ This file defines the visual design tokens for the Skillsoft Percipio platform, implemented using the Gamut design system (`@codecademy/gamut`, `@codecademy/gamut-styles`). Percipio uses a dedicated Gamut theme that applies its own colors and typography — all Gamut components work without modification.
120
+
121
+ **Storybook**: https://gamut.codecademy.com
122
+
123
+ ---
124
+
125
+ ## Visual Theme & Atmosphere
126
+
127
+ Percipio communicates **professional clarity** — clean, trustworthy, and enterprise-ready. The design voice is more neutral and corporate than Codecademy: less playful, more functional. Primary blue drives interactive affordances; neutral grays define text and structure.
128
+
129
+ **Density**: Medium. Consistent with Codecademy layouts but with softer shadows and a lighter overall feel due to the muted neutral palette.
130
+
131
+ **Design philosophy**:
132
+ - Light mode only — no dark mode support
133
+ - Primary blue (`percipioActionPrimary`) replaces Codecademy's `hyper-500` for all interactive elements
134
+ - Text is near-black dark gray rather than navy
135
+ - Shadows are soft and minimal (navy at low opacity) rather than hard borders
136
+ - Title font weight is 500 (medium) rather than 700 (bold) — Percipio headlines are less heavy
137
+
138
+ ---
139
+
140
+ ## Themes
141
+
142
+ Percipio uses a single Gamut theme — light mode only.
143
+
144
+ | Theme | Use case | Base font | Dark mode |
145
+ |---|---|---|---|
146
+ | **Percipio** | Skillsoft Percipio platform | Roboto | light only |
147
+
148
+ The active theme is set at the app root via `<GamutProvider theme={percipioTheme}>`.
149
+
150
+ ---
151
+
152
+ ## Semantic Color Aliases
153
+
154
+ Use these token names when specifying colors. Percipio is light mode only — there are no dark mode counterparts.
155
+
156
+ ### Text
157
+
158
+ | Token | Value | Use for |
159
+ |---|---|---|
160
+ | `text` | `#222325` | Default body and UI text |
161
+ | `text-accent` | `#222325` | Emphasis text (same value as `text` in Percipio) |
162
+ | `text-secondary` | `#595A5C` | Supporting / secondary copy |
163
+ | `text-disabled` | `#AFB6C2` | Disabled state labels |
164
+
165
+ ### Background
166
+
167
+ | Token | Value | Use for |
168
+ |---|---|---|
169
+ | `background` | `#ffffff` | Default page/component background |
170
+ | `background-primary` | `#FAFBFC` | Slightly elevated surfaces |
171
+ | `background-selected` | `#F5F6F7` (navy-100) | Selected row / item |
172
+ | `background-hover` | `#E2E3E6` (navy-200) | Hover state overlay |
173
+ | `background-disabled` | `#E2E3E6` (navy-200) | Disabled surface |
174
+ | `background-success` | `#EEF7F3` | Success state container |
175
+ | `background-warning` | `#FFF7E0` | Warning state container |
176
+ | `background-error` | `#FFF1F5` | Error state container |
177
+
178
+ ### Interactive
179
+
180
+ | Token | Value | Use for |
181
+ |---|---|---|
182
+ | `primary` | `#0073C4` | Primary CTA, links, focus rings |
183
+ | `primary-hover` | `#141C36` | Hover state of primary interactive |
184
+ | `primary-inverse` | `#ffffff` | Primary on a colored background |
185
+ | `secondary` | `#6A6E75` | Secondary CTA, ghost buttons |
186
+ | `secondary-hover` | `#7F8288` | Hover state of secondary interactive |
187
+ | `interface` | `#0073C4` | UI affordances (checkboxes, toggles, sliders) |
188
+ | `interface-hover` | `#141C36` | Hover on interface elements |
189
+ | `danger` | `#B83C3C` | Destructive actions, error states |
190
+ | `danger-hover` | `#A52020` | Hover on danger interactive |
191
+
192
+ ### Border
193
+
194
+ Percipio's border weights use a non-standard order: `primary` is mid-weight, `secondary` is very light, `tertiary` is the strongest (solid navy). Use them for their semantic intent, not their numeric rank.
195
+
196
+ | Token | Value | Use for |
197
+ |---|---|---|
198
+ | `border-primary` | `#8F919D` (navy-400) | Standard input and card borders |
199
+ | `border-secondary` | `#E2E3E6` (navy-200) | Subtle dividers, section separators |
200
+ | `border-tertiary` | `#10162F` (navy-800) | Strong structural borders |
201
+ | `border-disabled` | `#BCBEC5` (navy-300) | Disabled input borders |
202
+
203
+ ### Feedback
204
+
205
+ | Token | Value | Use for |
206
+ |---|---|---|
207
+ | `feedback-error` | `#B83C3C` | Error messages, validation |
208
+ | `feedback-success` | `#1B8057` | Success messages, confirmations |
209
+ | `feedback-warning` | `#EF5B0D` | Warning messages, caution states |
210
+
211
+ ### Shadow
212
+
213
+ | Token | Value |
214
+ |---|---|
215
+ | `shadow-primary` | `#E2E3E6` (navy-200) |
216
+ | `shadow-secondary` | `#8F919D` (navy-400) |
217
+
218
+ Percipio shadows are softer than Codecademy's — use `shadow-primary` for standard elevated surfaces.
219
+
220
+ ---
221
+
222
+ ## Percipio Color Palette
223
+
224
+ Percipio introduces its own named semantic colors. These are the source values behind the aliases above. Use the semantic aliases in designs, not the raw named colors.
225
+
226
+ | Named color | Value | Mapped to |
227
+ |---|---|---|
228
+ | `percipioTextPrimary` | `#222325` | `text`, `text-accent` |
229
+ | `percipioTextSecondary` | `#595A5C` | `text-secondary` |
230
+ | `percipioTextDisabled` | `#AFB6C2` | `text-disabled` |
231
+ | `percipioActionPrimary` | `#0073C4` | `primary`, `interface` |
232
+ | `percipioActionPrimaryHover` | `#141C36` | `primary-hover`, `interface-hover` |
233
+ | `percipioActionSecondary` | `#6A6E75` | `secondary` |
234
+ | `percipioActionSecondaryHover` | `#7F8288` | `secondary-hover` |
235
+ | `percipioActionDangerHover` | `#A52020` | `danger-hover` |
236
+ | `percipioDanger` | `#B83C3C` | `danger`, `feedback-error` |
237
+ | `percipioFeedbackSuccess` | `#1B8057` | `feedback-success` |
238
+ | `percipioFeedbackWarning` | `#EF5B0D` | `feedback-warning` |
239
+ | `percipioBgPrimary` | `#FAFBFC` | `background-primary` |
240
+ | `percipioBgSuccess` | `#EEF7F3` | `background-success` |
241
+ | `percipioBgWarning` | `#FFF7E0` | `background-warning` |
242
+ | `percipioBgError` | `#FFF1F5` | `background-error` |
243
+
244
+ The full core swatch palette (navy, blue, green, yellow, red, etc.) is also available, but the semantic aliases above are how Percipio maps them. Raw swatches should only be used for fixed colors that must not adapt (illustrations, data viz, etc.).
245
+
246
+ ---
247
+
248
+ ## Typography
249
+
250
+ ### Typefaces
251
+
252
+ All font families in Percipio use **Roboto**. There is no separate accent or display typeface.
253
+
254
+ | Token | Font | Use for |
255
+ |---|---|---|
256
+ | `base` | `"Roboto", sans-serif` | All default UI text, headlines, body copy |
257
+ | `accent` | `"Roboto", sans-serif` | Labels, captions (same as base in Percipio) |
258
+ | `monospace` | `"Roboto Mono", monospace` | Code editor contexts |
259
+ | `system` | `"Roboto", sans-serif` | Performance-critical surfaces |
260
+
261
+ ### Rules
262
+
263
+ - **Roboto Medium (500)** for headlines, sub-headlines, CTAs, and buttons — not Bold (700).
264
+ - **Roboto Regular (400)** for body text, UI labels, and menu items.
265
+ - Text is **left-aligned** by default. Center-align only for short marketing headlines. Never right-align.
266
+ - Do not adjust letter-spacing.
267
+
268
+ ### Font weight scale
269
+
270
+ Percipio overrides the title weight from Core's 700 to 500 (medium). This gives Percipio a lighter, less heavy headline style.
271
+
272
+ | Token | Value | Use |
273
+ |---|---|---|
274
+ | `base` | 400 | Body text, UI labels |
275
+ | `title` | **500** | Headlines, CTAs, buttons _(differs from Codecademy's 700)_ |
276
+
277
+ ### Font size scale
278
+
279
+ Shared with Core — all sizes are identical.
280
+
281
+ | Token key | Size | Common use |
282
+ |---|---|---|
283
+ | `64` | 64px | Hero / display |
284
+ | `44` | 44px | Page titles |
285
+ | `34` | 34px | Section titles |
286
+ | `26` | 26px | Sub-section titles |
287
+ | `22` | 22px | Card titles, large UI labels |
288
+ | `20` | 20px | Secondary titles |
289
+ | `18` | 18px | Large body, intro text |
290
+ | `16` | 16px | Default body text |
291
+ | `14` | 14px | Small body, captions, labels |
292
+
293
+ ### Line height scale
294
+
295
+ Shared with Core.
296
+
297
+ | Token | Value | Use |
298
+ |---|---|---|
299
+ | `base` | 1.5 | Body text |
300
+ | `spacedTitle` | 1.3 | Sub-headlines and medium titles |
301
+ | `title` | 1.2 | Large headlines |
302
+
303
+ ### Line length
304
+
305
+ Target 45–85 characters per line; 66 characters is ideal. Max 50 for multi-column layouts.
306
+
307
+ ---
308
+
309
+ ## Spacing Scale
310
+
311
+ Identical to Core. All spacing is multiples of 4px on an 8px grid.
312
+
313
+ | Token | Value |
314
+ |---|---|
315
+ | `0` | 0 |
316
+ | `4` | 4px |
317
+ | `8` | 8px |
318
+ | `12` | 12px |
319
+ | `16` | 16px |
320
+ | `24` | 24px |
321
+ | `32` | 32px |
322
+ | `40` | 40px |
323
+ | `48` | 48px |
324
+ | `64` | 64px |
325
+ | `96` | 96px |
326
+
327
+ ---
328
+
329
+ ## Border Radius Scale
330
+
331
+ Identical to Core.
332
+
333
+ | Token | Value | Use |
334
+ |---|---|---|
335
+ | `none` | 0px | Square / non-interactive elements |
336
+ | `sm` | 2px | Subtle rounding, tags |
337
+ | `md` | 4px | Default buttons, inputs, interactive cards |
338
+ | `lg` | 8px | Cards, panels |
339
+ | `xl` | 16px | Large cards, modals |
340
+ | `full` | 999px | Pills, avatars, circular elements |
341
+
342
+ ---
343
+
344
+ ## Responsive Behavior
345
+
346
+ Identical to Core. Mobile-first, apply styles from the named breakpoint up.
347
+
348
+ | Token | Min-width | Max content |
349
+ |---|---|---|
350
+ | _(base)_ | 0 | 288px |
351
+ | `xs` | 480px | 448px |
352
+ | `sm` | 768px | 704px |
353
+ | `md` | 1024px | 896px |
354
+ | `lg` | 1200px | 1072px |
355
+ | `xl` | 1440px | 1248px |
356
+
357
+ 12-column grid at all breakpoints.
358
+
359
+ | Usage | Recommended values |
360
+ |---|---|
361
+ | Horizontal margins | 64px (lg+), 48px (md), 32px (sm/xs), 16px (base) |
362
+ | Column gaps (gutters) | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
363
+ | Row gaps | 32px (lg+), 24px (md), 16px (sm/xs), 8px (base) |
364
+
365
+ Minimum interactive touch target: **44×44px** on mobile breakpoints.
366
+
367
+ ---
368
+
369
+ ## Component Library
370
+
371
+ Same component library as Codecademy — all atoms, molecules, and organisms apply. Token values resolve differently per theme automatically.
372
+
373
+ Key Percipio-specific visual differences:
374
+ - `FillButton` uses `#0073C4` (blue) instead of hyper-purple
375
+ - `FillButton` hover shifts to near-black `#141C36` rather than a lighter purple
376
+ - `Checkbox` / `Toggle` use the same blue `#0073C4`
377
+ - `Card` has softer shadows (navy-200 vs navy-800 in Codecademy light mode)
378
+ - Card shadow patterns (`patternLeft`, `patternRight`) are available but rarely used in Percipio UIs
379
+
380
+ ---
381
+
382
+ ## Do's and Don'ts
383
+
384
+ ### Colors
385
+
386
+ - **Do** use semantic color aliases (`primary`, `text`, `background`, etc.) — never hardcode hex values.
387
+ - **Do** use `#0073C4` blue as the only primary interactive color.
388
+ - **Don't** use Codecademy's hyper-purple or yellow in Percipio contexts.
389
+ - **Don't** attempt dark mode — Percipio is light only.
390
+
391
+ ### Typography
392
+
393
+ - **Do** use title weight (500) for headlines, CTAs, and buttons — not 700.
394
+ - **Do** keep body text at 150–175% line height for readability.
395
+ - **Don't** use a separate accent typeface — Roboto is used uniformly for base and accent.
396
+ - **Don't** right-align or center-align body paragraphs.
397
+ - **Don't** adjust letter-spacing.
398
+
399
+ ### Layout & Spacing
400
+
401
+ - **Do** use multiples of 8px for block-element spacing (4px only for inline / typographic relationships).
402
+ - **Do** begin design work at 1440px (XL), then adapt down.
403
+ - **Do** align elements to the 12-column grid.
404
+
405
+ ---
406
+
407
+ ## Agent Prompt Guide
408
+
409
+ Quick color/token reference for generating or specifying Percipio UI:
410
+
411
+ | Scenario | Tokens |
412
+ |---|---|
413
+ | Primary button | `bg: primary (#0073C4)`, `color: white`, `hover: primary-hover (#141C36)` |
414
+ | Body text | `color: text (#222325)`, `font: Roboto`, `size: 16px`, `weight: 400`, `lineHeight: base (1.5)` |
415
+ | Headline | `color: text (#222325)`, `font: Roboto`, `size: 34–64px`, `weight: title (500)`, `lineHeight: title (1.2)` |
416
+ | Secondary text | `color: text-secondary (#595A5C)` |
417
+ | Disabled text | `color: text-disabled (#AFB6C2)` |
418
+ | Elevated surface | `bg: background-primary (#FAFBFC)` |
419
+ | Card default | `bg: background (#ffffff)`, `borderRadius: none` — add `isInteractive` for hover shadow + `borderRadius: md` |
420
+ | Error state | `color: feedback-error (#B83C3C)`, `bg: background-error (#FFF1F5)`, `border: danger` |
421
+ | Success state | `color: feedback-success (#1B8057)`, `bg: background-success (#EEF7F3)` |
422
+ | Warning state | `color: feedback-warning (#EF5B0D)`, `bg: background-warning (#FFF7E0)` |
423
+ | Disabled state | `color: text-disabled (#AFB6C2)`, `bg: background-disabled (#E2E3E6, navy-200)`, `border: border-disabled` |
424
+
425
+ ### Component token cheatsheet
426
+
427
+ ```
428
+ FillButton → bg: primary (#0073C4), color: white, hover: primary-hover (#141C36)
429
+ StrokeButton → bg: transparent, border: secondary (#6A6E75)
430
+ Checkbox/Toggle → interface (#0073C4), hover: interface-hover (#141C36)
431
+ Card → bg: background, shadow: shadow-primary (#E2E3E6, navy-200, soft)
432
+ Alert (error) → uses feedback-error + background-error
433
+ Alert (success) → uses feedback-success + background-success
434
+ Alert (warning) → uses feedback-warning + background-warning
435
+ ```
@@ -0,0 +1 @@
1
+ DEPRECATED. Use the appropriate DESIGN.*.md from https://github.com/Codecademy/gamut/pull/3329 instead.
File without changes
@@ -0,0 +1,170 @@
1
+ ---
2
+ description: Use this command when auditing existing code for Gamut usage — dependencies, GamutProvider, deep imports, hardcoded hex colors, and test patterns — and you need a consolidated report with pointers to the matching Gamut skills.
3
+ argument-hint: [path]
4
+ allowed-tools: Read Glob Grep
5
+ ---
6
+
7
+ This is an audit of **existing code** at **`$ARGUMENTS`** (default: current working directory). Your job is to find violations and misuse, not to generate new code.
8
+
9
+ Use `DESIGN.md` at the project root as the authoritative reference for the product's design intent, token names, and component patterns. This file is distributed as `DESIGN.Codecademy.md` or `DESIGN.Percipio.md` from the `@codecademy/gamut` agent-tools package and renamed to `DESIGN.md` by the consuming project. When a finding maps to a skill, note it in the report so the developer knows where to get remediation guidance.
10
+
11
+ Run all five checks below, then print a single consolidated report using the format at the end of this file.
12
+
13
+ ---
14
+
15
+ ## Check 1 — Dependencies
16
+
17
+ Read `package.json` (and `package.json` in `$ARGUMENTS` if a path was given). Inspect `dependencies`, `devDependencies`, and `peerDependencies` combined.
18
+
19
+ | Package | Expectation |
20
+ |---|---|
21
+ | `@codecademy/gamut` | **Required** — core component library |
22
+ | `@codecademy/gamut-styles` | Recommended — design tokens and theme primitives |
23
+ | `@codecademy/variance` | Recommended — style-prop system used by Gamut internals |
24
+
25
+ ---
26
+
27
+ ## Check 2 — Setup
28
+
29
+ Search source files (`.ts`, `.tsx`, `.js`, `.jsx`) for these symbols. Skip `node_modules`, `dist`, `.next`, `build`, `.turbo`.
30
+
31
+ | Symbol | Expectation |
32
+ |---|---|
33
+ | `GamutProvider` | **Required** — must appear at least once (app root wrapper) |
34
+ | `ColorMode` | Recommended — enables semantic light/dark theming |
35
+ | `Background` | Recommended — semantic surface color via `@codecademy/gamut-styles` |
36
+
37
+ For each found symbol report the first file path where it appears.
38
+
39
+ ---
40
+
41
+ ## Check 3 — Import patterns
42
+
43
+ Grep source files for any of these patterns. Each match is an error.
44
+
45
+ | Pattern | Reason |
46
+ |---|---|
47
+ | `@codecademy/gamut/dist/` | Deep dist import — bypasses public API and breaks on internal refactors |
48
+ | `@codecademy/gamut/src/` | Deep src import — not part of the published package |
49
+ | `@codecademy/gamut-styles/src/` | Deep src import — use the package root |
50
+ | `@codecademy/variance/src/` | Deep src import — use the package root |
51
+
52
+ Report each violation as `file:line`.
53
+
54
+ ---
55
+
56
+ ## Check 4 — Hardcoded colors
57
+
58
+ Grep source files (`.ts`, `.tsx`, `.js`, `.jsx`, `.css`, `.scss`, `.less`) for inline hex color literals (`#RGB` or `#RRGGBB`). For each match, suggest the Gamut token name using this table (case-insensitive comparison):
59
+
60
+ | Hex | Token |
61
+ |---|---|
62
+ | `#000000` | `black` |
63
+ | `#ffffff` | `white` |
64
+ | `#10162f` | `navy` / `navy-800` |
65
+ | `#0a0d1c` | `navy-900` |
66
+ | `#fff0e5` | `beige-100` |
67
+ | `#f5fcff` | `blue-0` |
68
+ | `#d3f2ff` | `blue-100` |
69
+ | `#66c4ff` | `blue-300` |
70
+ | `#3388ff` | `blue-400` |
71
+ | `#1557ff` | `blue-500` |
72
+ | `#1d2340` | `blue-800` |
73
+ | `#f5ffe3` | `green-0` |
74
+ | `#eafdc6` | `green-100` |
75
+ | `#aee938` | `green-400` / `lightGreen` |
76
+ | `#008a27` | `green-700` |
77
+ | `#151c07` | `green-900` |
78
+ | `#fffae5` | `yellow-0` |
79
+ | `#cca900` | `yellow-400` |
80
+ | `#ffd300` | `yellow-500` / `yellow` |
81
+ | `#211b00` | `yellow-900` |
82
+ | `#fff5ff` | `pink-0` |
83
+ | `#f966ff` | `pink-400` / `pink` |
84
+ | `#fbf1f0` | `red-0` |
85
+ | `#e85d7f` | `red-300` |
86
+ | `#dc5879` | `red-400` / `paleRed` |
87
+ | `#e91c11` | `red-500` / `red` |
88
+ | `#be1809` | `red-600` |
89
+ | `#280503` | `red-900` |
90
+ | `#ffe8cc` | `orange-100` |
91
+ | `#ff8c00` | `orange-500` / `orange` |
92
+ | `#5533ff` | `hyper-400` |
93
+ | `#3a10e5` | `hyper-500` / `hyper` |
94
+ | `#f5f5f5` | `gray-100` |
95
+ | `#eeeeee` | `gray-200` |
96
+ | `#e0e0e0` | `gray-300` |
97
+ | `#9e9e9e` | `gray-600` |
98
+ | `#616161` | `gray-800` |
99
+ | `#424242` | `gray-900` |
100
+ | `#fffbf8` | `beige-0` |
101
+ | `#8a7300` | `gold-800` / `gold` |
102
+ | `#d14900` | `orange-800` |
103
+ | `#ca00d1` | `pink-800` |
104
+ | `#006d82` | `teal-500` / `teal` |
105
+ | `#b3ccff` | `purple-300` / `purple` |
106
+
107
+ Ignore hex values inside design token definition files themselves (e.g. `variables/colors.ts`, `_colors.scss`) — those are the source of truth, not violations.
108
+
109
+ For each match outside token files report: `file:line 'HEX' → token` (or `→ no Gamut token` if unknown).
110
+
111
+ ---
112
+
113
+ ## Check 5 — Test setup
114
+
115
+ Grep test files (`**/__tests__/**/*.{ts,tsx}`, `**/*.test.{ts,tsx}`, `**/*.spec.{ts,tsx}`) for these patterns. Skip `node_modules`, `dist`.
116
+
117
+ | Pattern | Verdict | Reason |
118
+ |---|---|---|
119
+ | `jest.mock\(.*@codecademy/gamut` | **Error** | Manual mocking bypasses theme context and produces false-positive tests; use `setupRtl` or `MockGamutProvider` instead |
120
+ | `jest.mock\(.*@codecademy/gamut-styles` | **Error** | Same issue as above — mocking gamut-styles breaks token resolution |
121
+ | `from '@codecademy/gamut-tests'` | Good — report count of files using it | Correct import for `setupRtl` and `MockGamutProvider` |
122
+ | `from 'component-test-setup'` (without gamut-tests) | **Warning** | Should import `setupRtl` from `@codecademy/gamut-tests`, not directly from `component-test-setup` — the gamut-tests wrapper adds `MockGamutProvider` automatically |
123
+ | `new GamutProvider` or `<GamutProvider` in test files | **Warning** | Tests should use `MockGamutProvider` (sets `useCache={false}`, `useGlobals={false}`), not `GamutProvider` directly |
124
+
125
+ Skill reference for remediation: `gamut-testing`
126
+
127
+ ---
128
+
129
+ ## Output format
130
+
131
+ ```
132
+ Gamut Review — <absolute path>
133
+ ══════════════════════════════════════════════════
134
+
135
+ Dependencies
136
+ ✓ @codecademy/gamut <version>
137
+ ⚠ @codecademy/gamut-styles not found — recommended
138
+ ✗ @codecademy/variance not found — recommended
139
+
140
+ Setup
141
+ ✓ GamutProvider found (src/App.tsx)
142
+ ⚠ ColorMode not found — use ColorMode for light/dark theming [→ gamut-color-mode]
143
+ ⚠ Background not found — use <Background> for semantic surfaces [→ gamut-color-mode]
144
+
145
+ Import patterns
146
+ ✓ Deep dist imports none found
147
+ ✗ Deep src imports 2 occurrences
148
+ src/Thing.tsx:7
149
+ src/Other.tsx:12
150
+
151
+ Hardcoded colors [→ gamut-color-mode]
152
+ ⚠ src/Hero.tsx:14 '#1557FF' → blue-500
153
+ ⚠ src/Nav.tsx:8 '#BADA55' → no Gamut token
154
+
155
+ Test setup [→ gamut-testing]
156
+ ✓ @codecademy/gamut-tests used in 12 test files
157
+ ✗ jest.mock(@codecademy/gamut) 2 occurrences — remove and use setupRtl instead
158
+ src/components/Foo/__tests__/Foo.test.tsx:3
159
+ src/components/Bar/__tests__/Bar.test.tsx:5
160
+ ⚠ direct component-test-setup import 1 occurrence — import from @codecademy/gamut-tests
161
+ src/components/Baz/__tests__/Baz.test.tsx:2
162
+
163
+ ══════════════════════════════════════════════════
164
+ <N> error(s), <N> warning(s) found. (or "All checks passed." if none)
165
+ ```
166
+
167
+ Icons: `✓` = pass, `⚠` = warning (recommended, not required), `✗` = error (required).
168
+ `[→ skill-name]` annotations indicate which Gamut skill has remediation guidance for that category.
169
+
170
+ After printing the report, offer one sentence of prioritized next-step advice based on what was found.
@@ -0,0 +1,44 @@
1
+ # Buttons
2
+
3
+ ## Variants
4
+
5
+ | Component | Use for | Background | Text |
6
+ |---|---|---|---|
7
+ | `FillButton` | Primary CTA, high-emphasis actions | `primary` | `white` |
8
+ | `StrokeButton` | Secondary actions, outlined style | transparent | `secondary` |
9
+ | `CTAButton` | High-visibility marketing promotions | `primary` | `white` |
10
+ | `CTAButton` (inverse) | CTA on a colored surface | `primary-inverse` | `secondary` |
11
+ | `TextButton` | Low-emphasis, inline text actions | transparent | `primary` |
12
+ | `IconButton` | Compact icon-only actions | — | — |
13
+
14
+ ## Sizes
15
+
16
+ `small` | `normal` (default) | `large`
17
+
18
+ ## Key props
19
+
20
+ | Prop | Type | Effect |
21
+ |---|---|---|
22
+ | `size` | `"small" \| "normal" \| "large"` | Controls padding and font size |
23
+ | `icon` | Icon component | Leading or trailing icon |
24
+ | `iconPosition` | `"left" \| "right"` | Defaults to left |
25
+ | `disabled` | boolean | Disabled state styling |
26
+ | `href` | string | Renders as `<a>` tag |
27
+
28
+ ## States
29
+
30
+ `default` → `hover` (`primary-hover` / `secondary-hover`) → `active` → `disabled` (`text-disabled` + `background-disabled`)
31
+
32
+ ## Token cheatsheet
33
+
34
+ ```
35
+ FillButton → bg: primary (#3A10E5 light / #FFD300 dark), color: white, hover: primary-hover
36
+ StrokeButton → bg: transparent, border: secondary (#10162F / #fff), hover: secondary-hover
37
+ TextButton → bg: transparent, color: primary, hover: primary-hover
38
+ ```
39
+
40
+ ## Rules
41
+
42
+ - Use `FillButton` for primary actions and `StrokeButton` for secondary — do not use both at equal weight.
43
+ - Reserve `CTAButton` for marketing / high-visibility promotions; do not use it for standard UI actions.
44
+ - Every interactive `Card` wrapped in `<Anchor>` should have `isInteractive` — not a button inside.