From 80c6ccfffbe2901ffb4fbcaa488c192b3e42e850 Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 20 Apr 2026 15:34:51 -0400 Subject: [PATCH 01/19] ci: one alpha dist-tag per PR --- .github/workflows/publish-alpha.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-alpha.yml b/.github/workflows/publish-alpha.yml index b1d926c845..b9d24aec5a 100644 --- a/.github/workflows/publish-alpha.yml +++ b/.github/workflows/publish-alpha.yml @@ -50,13 +50,11 @@ jobs: - name: Publish alpha packages id: publish-alpha - run: | - SHORT_SHA=${GITHUB_SHA:0:6} - PREID="alpha.${SHORT_SHA}" - npx nx run gamut-release:alpha --preid="${PREID}" --manifest + run: npx nx run gamut-release:alpha --preid="alpha.${PR_NUMBER}" --manifest env: GH_TOKEN: ${{ secrets.ACTIONS_GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} + PR_NUMBER: ${{ github.event.number }} - name: List alpha packages versions id: published From 98c9590dcbabf3d466e9f6ce85016ff686fc659a Mon Sep 17 00:00:00 2001 From: Evan Yamanishi Date: Mon, 20 Apr 2026 15:35:37 -0400 Subject: [PATCH 02/19] agent tooling proof of concept --- package.json | 1 + .../.claude-plugin/marketplace.json | 16 + .../agent-tools/.claude-plugin/plugin.json | 7 + .../agent-tools/.cursor-plugin/plugin.json | 6 + packages/gamut/agent-tools/DESIGN.md | 276 ++++++++++++++++++ packages/gamut/agent-tools/agents/.gitkeep | 0 .../agent-tools/commands/gamut-review.md | 141 +++++++++ .../gamut/agent-tools/rules/accessibility.mdc | 40 +++ .../skills/gamut-accessibility/SKILL.md | 160 ++++++++++ .../skills/gamut-color-mode/SKILL.md | 99 +++++++ .../skills/gamut-system-props/SKILL.md | 173 +++++++++++ .../agent-tools/skills/gamut-theming/SKILL.md | 113 +++++++ .../skills/gamut-typography/SKILL.md | 121 ++++++++ .../gamut/bin/commands/plugin/install.mjs | 147 ++++++++++ packages/gamut/bin/commands/plugin/list.mjs | 89 ++++++ packages/gamut/bin/commands/plugin/remove.mjs | 115 ++++++++ packages/gamut/bin/commands/plugin/update.mjs | 49 ++++ packages/gamut/bin/gamut.mjs | 92 ++++++ packages/gamut/bin/lib/claude.mjs | 52 ++++ packages/gamut/bin/lib/cursor.mjs | 40 +++ packages/gamut/bin/lib/resolve-plugin-dir.mjs | 38 +++ packages/gamut/bin/lib/run-command.mjs | 22 ++ packages/gamut/package.json | 7 +- packages/gamut/tsconfig.bin.json | 13 + yarn.lock | 5 +- 25 files changed, 1819 insertions(+), 3 deletions(-) create mode 100644 packages/gamut/agent-tools/.claude-plugin/marketplace.json create mode 100644 packages/gamut/agent-tools/.claude-plugin/plugin.json create mode 100644 packages/gamut/agent-tools/.cursor-plugin/plugin.json create mode 100644 packages/gamut/agent-tools/DESIGN.md create mode 100644 packages/gamut/agent-tools/agents/.gitkeep create mode 100644 packages/gamut/agent-tools/commands/gamut-review.md create mode 100644 packages/gamut/agent-tools/rules/accessibility.mdc create mode 100644 packages/gamut/agent-tools/skills/gamut-accessibility/SKILL.md create mode 100644 packages/gamut/agent-tools/skills/gamut-color-mode/SKILL.md create mode 100644 packages/gamut/agent-tools/skills/gamut-system-props/SKILL.md create mode 100644 packages/gamut/agent-tools/skills/gamut-theming/SKILL.md create mode 100644 packages/gamut/agent-tools/skills/gamut-typography/SKILL.md create mode 100644 packages/gamut/bin/commands/plugin/install.mjs create mode 100644 packages/gamut/bin/commands/plugin/list.mjs create mode 100644 packages/gamut/bin/commands/plugin/remove.mjs create mode 100644 packages/gamut/bin/commands/plugin/update.mjs create mode 100755 packages/gamut/bin/gamut.mjs create mode 100644 packages/gamut/bin/lib/claude.mjs create mode 100644 packages/gamut/bin/lib/cursor.mjs create mode 100644 packages/gamut/bin/lib/resolve-plugin-dir.mjs create mode 100644 packages/gamut/bin/lib/run-command.mjs create mode 100644 packages/gamut/tsconfig.bin.json diff --git a/package.json b/package.json index 4f1b3f1f73..52b5b04d11 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@babel/preset-react": "^7.24.7", "@babel/preset-typescript": "^7.24.7", "@codecademy/eslint-config": "8.0.0", + "@codecademy/gamut": "workspace:*", "@codecademy/prettier-config": "^0.2.0", "@codecademy/tsconfig": "^0.3.0", "@commander-js/extra-typings": "^14.0.0", diff --git a/packages/gamut/agent-tools/.claude-plugin/marketplace.json b/packages/gamut/agent-tools/.claude-plugin/marketplace.json new file mode 100644 index 0000000000..87094b8619 --- /dev/null +++ b/packages/gamut/agent-tools/.claude-plugin/marketplace.json @@ -0,0 +1,16 @@ +{ + "name": "gamut-agent-tools", + "owner": { + "name": "Codecademy" + }, + "metadata": { + "description": "Local marketplace for @codecademy/gamut agent tools." + }, + "plugins": [ + { + "name": "codecademy-gamut", + "source": "./", + "description": "Gamut design system agent tools: skills and rules for AI-assisted development." + } + ] +} diff --git a/packages/gamut/agent-tools/.claude-plugin/plugin.json b/packages/gamut/agent-tools/.claude-plugin/plugin.json new file mode 100644 index 0000000000..5b07aa0782 --- /dev/null +++ b/packages/gamut/agent-tools/.claude-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "codecademy-gamut", + "version": "0.0.1", + "description": "Gamut design system agent tools: skills and rules for AI-assisted development.", + "license": "MIT", + "keywords": ["codecademy", "gamut", "design-system", "agent-skills"] +} diff --git a/packages/gamut/agent-tools/.cursor-plugin/plugin.json b/packages/gamut/agent-tools/.cursor-plugin/plugin.json new file mode 100644 index 0000000000..4b0b630e23 --- /dev/null +++ b/packages/gamut/agent-tools/.cursor-plugin/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "@codecademy/gamut", + "version": "0.0.1", + "description": "Gamut design system agent tools: skills and rules for AI-assisted development.", + "keywords": ["codecademy", "gamut", "design-system", "agent-skills"] +} diff --git a/packages/gamut/agent-tools/DESIGN.md b/packages/gamut/agent-tools/DESIGN.md new file mode 100644 index 0000000000..6ef2b34531 --- /dev/null +++ b/packages/gamut/agent-tools/DESIGN.md @@ -0,0 +1,276 @@ +# Gamut Design System + +Gamut is the Codecademy / Skillsoft design system. It ships a React component library (`@codecademy/gamut`), design tokens (`@codecademy/gamut-styles`), and Figma components with live code previews via Figma Code Connect. + +**Figma file**: https://www.figma.com/design/ReGfRNillGABAj5SlITalN/πŸ“-Gamut +**Component library**: 52 components have Figma ↔ code mappings in `packages/code-connect/`. +**Storybook**: Run `yarn start:storybook` in the repo for interactive docs. + +--- + +## Themes + +Five themes are available. All extend the Core theme. Components work across all themes without modification β€” token aliases resolve to the right values per theme. + +| Theme | Use case | Dark mode | +|---|---|---| +| **Core** | Codecademy (default) | βœ“ light + dark | +| **Admin** | Codecademy admin tools | βœ“ light + dark | +| **Platform** | Codecademy learning environment | βœ“ light + dark | +| **LX Studio** | LX Studio application | light only | +| **Percipio** | Skillsoft Percipio platform | light only | + +The active theme is set at the app root via ``. When designing, know which theme your screen targets β€” it affects primary colors, font families, and available color weights. + +--- + +## Semantic Color Aliases + +Use these token names when specifying colors in designs. They resolve to the correct raw value for the active theme and color mode automatically. **Never hardcode hex values** for anything that needs to adapt across modes. + +### Text + +| Token | Light | Dark | Use for | +|---|---|---|---| +| `text` | navy-800 `#10162F` at 100% | white `#ffffff` | Default body and UI text | +| `text-accent` | navy-900 `#0A0D1C` | beige `#FFF0E5` | Stronger emphasis text | +| `text-secondary` | navy-800 at 75% | white at 65% | Supporting / secondary copy | +| `text-disabled` | navy-800 at 63% | white at 50% | Disabled state labels | + +### Background + +| Token | Light | Dark | Use for | +|---|---|---|---| +| `background` | white `#ffffff` | navy-800 `#10162F` | Default page/component background | +| `background-primary` | beige `#FFF0E5` | navy-900 `#0A0D1C` | Slightly elevated surfaces | +| `background-contrast` | white | black `#000000` | Maximum contrast surface | +| `background-selected` | navy-800 at 4% | white at 4% | Selected row / item | +| `background-hover` | navy-800 at 12% | white at 9% | Hover state overlay | +| `background-disabled` | navy-800 at 12% | white at 9% | Disabled surface | +| `background-success` | green-0 `#F5FFE3` | green-900 `#151C07` | Success state container | +| `background-warning` | yellow-0 `#FFFAE5` | yellow-900 `#211B00` | Warning state container | +| `background-error` | red-0 `#FBF1F0` | red-900 `#280503` | Error state container | + +### Interactive + +| Token | Light | Dark | Use for | +|---|---|---|---| +| `primary` | hyper-500 `#3A10E5` | yellow-500 `#FFD300` | Primary CTA, links, focus rings | +| `primary-hover` | hyper-400 `#5533FF` | yellow-400 `#CCA900` | Hover state of primary interactive | +| `primary-inverse` | yellow-500 `#FFD300` | hyper-500 `#3A10E5` | Primary on a colored background | +| `secondary` | navy-800 `#10162F` | white `#ffffff` | Secondary CTA, ghost buttons | +| `secondary-hover` | navy-800 at 86% | white at 80% | Hover state of secondary interactive | +| `interface` | hyper-500 `#3A10E5` | yellow-500 `#FFD300` | UI affordances (checkboxes, toggles, sliders) | +| `interface-hover` | hyper-400 `#5533FF` | yellow-400 `#CCA900` | Hover on interface elements | +| `danger` | red-500 `#E91C11` | red-300 `#E85D7F` | Destructive actions, error states | +| `danger-hover` | red-600 `#BE1809` | red-400 `#DC5879` | Hover on danger interactive | + +### Border + +| Token | Light | Dark | Use for | +|---|---|---|---| +| `border-primary` | navy-800 `#10162F` | white `#ffffff` | Strong borders, dividers | +| `border-secondary` | navy-800 at 75% | white at 65% | Medium-weight borders | +| `border-tertiary` | navy-800 at 28% | white at 20% | Subtle borders, separators | +| `border-disabled` | navy-800 at 63% | white at 50% | Disabled input borders | + +### Feedback + +| Token | Light | Dark | Use for | +|---|---|---|---| +| `feedback-error` | red-600 `#BE1809` | red-300 `#E85D7F` | Error messages, validation | +| `feedback-success` | green-700 `#008A27` | green-400 `#AEE938` | Success messages, confirmations | +| `feedback-warning` | yellow `#FFD300` | yellow-0 `#FFFAE5` | Warning messages, caution states | + +### Shadow + +| Token | Light | Dark | +|---|---|---| +| `shadow-primary` | navy-800 | white | +| `shadow-secondary` | navy-800 at 75% | white at 65% | + +--- + +## Raw Color Palette + +All colors available as static tokens regardless of color mode. Use these only when a color should be **fixed** and not adapt to dark mode. + +### Core Palette + +| Name | Weights available | Notes | +|---|---|---| +| `navy` | 100–900 | 100–700 are rgba transparencies of `#10162F`; 800 = `#10162F`; 900 = `#0A0D1C` | +| `white` | 100–700 | rgba transparencies of `#ffffff` (no solid white weight β€” use `white` for `#fff`) | +| `blue` | 0, 100, 300, 400, 500, 800 | 500 = `#1557FF` | +| `hyper` | 400, 500 | 500 = `#3A10E5` (purple-blue), 400 = `#5533FF` | +| `green` | 0, 100, 400, 700, 900 | 700 = `#008A27` | +| `yellow` | 0, 400, 500, 900 | 500 = `#FFD300` | +| `red` | 0, 300, 400, 500, 600, 900 | 500 = `#E91C11` | +| `gray` | 100, 200, 300, 600, 800, 900 | | +| `pink` | 0, 400 | 400 = `#F966FF` | +| `orange` | 100, 500 | 500 = `#FF8C00` | +| `beige` | 100 (alias: `beige`) | `#FFF0E5` | +| `black` | β€” | `#000000` | +| `white` (solid) | β€” | `#ffffff` | + +**Named aliases** (shorthand for common weights): +`beige`, `blue`, `green`, `hyper`, `lightBlue`, `lightGreen`, `navy`, `orange`, `paleBlue`, `paleGreen`, `palePink`, `paleRed`, `paleYellow`, `pink`, `red`, `yellow`, `black`, `white` + +### Platform-only additions +`lightBeige` (`#FFFBF8`), `gold` (`#8A7300`), `teal` (`#006D82`), `purple` (`#B3CCFF`) + +### LX Studio additions +`lxStudioPurple` (`#5628FE`), `lxStudioPurpleHover` (`#7955FC`), `lxStudioSuccess` (`#06844F`) + +--- + +## Typography + +### Typefaces + +| Token | Font | Use for | +|---|---|---| +| `base` | AperΓ§u Pro (fallback: system sans-serif) | All default UI text, headlines, body copy | +| `accent` | Suisse Int'l Mono (fallback: system sans-serif) | Code, captions, labels, lists, technical context | +| `monospace` | Monaco / Menlo | Code editor contexts | +| `system` | System UI fonts | Performance-critical surfaces | + +**Percipio theme overrides all families to Roboto.** +**LX Studio theme uses Hanken Grotesk for `base`.** + +### Rules + +- **AperΓ§u Family** can only be used for codecademy.com. Don't use for any other product. +- **AperΓ§u Bold** for headlines, sub-headlines, CTAs, and buttons. +- **AperΓ§u Regular** for body text, UI labels, and menu items. +- **AperΓ§u Italic** to emphasize text within a Regular paragraph β€” not Bold. +- **Suisse** sparingly: code snippets, enumerated items, quotations, captions. Reads 10–15% large for its point size β€” size down relative to AperΓ§u (14px Suisse β‰ˆ 16px AperΓ§u visually). +- Text is **left-aligned** by default. Center-align only for short marketing headlines. Never right-align. +- Do not adjust letter-spacing. + +### Font size scale + +| Token key | Size | Common use | +|---|---|---| +| `64` | 64px | Hero / display | +| `44` | 44px | Page titles | +| `34` | 34px | Section titles | +| `26` | 26px | Sub-section titles | +| `22` | 22px | Card titles, large UI labels | +| `20` | 20px | Secondary titles | +| `18` | 18px | Large body, intro text | +| `16` | 16px | Default body text | +| `14` | 14px | Small body, captions, labels | + +### Font weight scale + +| Token | Value | Use | +|---|---|---| +| `base` | 400 | Body text, UI labels | +| `title` | 700 | Headlines, CTAs, buttons | + +### Line height scale + +| Token | Value | Use | +|---|---|---| +| `base` | 1.5 | Body text (150% β€” aim for 150–175% of font size) | +| `spacedTitle` | 1.3 | Sub-headlines and medium titles | +| `title` | 1.2 | Large headlines (aim for 100–110% of font size) | + +### Line length + +Target 45–85 characters per line; 66 characters is ideal for web body text. Max 50 characters for multi-column layouts. + +--- + +## Spacing Scale + +All spacing is multiples of 4px, placed on an 8px grid. + +| Token | Value | +|---|---| +| `0` | 0 | +| `4` | 4px | +| `8` | 8px | +| `12` | 12px | +| `16` | 16px | +| `24` | 24px | +| `32` | 32px | +| `40` | 40px | +| `48` | 48px | +| `64` | 64px | +| `96` | 96px | + +--- + +## Border Radius Scale + +| Token | Value | Use | +|---|---|---| +| `none` | 0px | Square elements | +| `sm` | 2px | Subtle rounding, tags | +| `md` | 4px | Default buttons, inputs | +| `lg` | 8px | Cards, panels | +| `xl` | 16px | Large cards, modals | +| `full` | 999px | Pills, avatars, circular elements | + +--- + +## Breakpoints + +Mobile-first. Apply styles from the named breakpoint and up. + +| Token | Min-width | Typical target | +|---|---|---| +| _(base)_ | 0 | Mobile | +| `xs` | 480px | Large mobile | +| `sm` | 768px | Tablet | +| `md` | 1024px | Small desktop | +| `lg` | 1200px | Desktop | +| `xl` | 1440px | Large desktop | + +Container query variants (`c_xs` through `c_xl`) mirror these values but trigger on component container size, not viewport. + +**Content widths**: max content width is `1200px` (md) or `1440px` (max). + +--- + +## Component Library + +Components are organized into three tiers: + +### Atoms β€” foundational, single-purpose +Badge, Button, ButtonBase, Card, Checkbox, CodeBlock, ColorMode, Drawer, FlexBox, FormGroup, GridBox, HiddenText, Icon, Input, Label, Loader, Radio, Select, Spinner, Tag, TextArea, Toggle, Tooltip + +### Molecules β€” composed of atoms, handle a discrete task +Alert, Anchor, Breadcrumbs, Coachmark, Disclosure, GridForm, Markdown, Menu, Modal, Pagination, Popover, ProgressBar, Table, Tabs, TextButton, Toast, Toaster, Video + +### Organisms β€” page-level compositions +ContentContainer, GridContainer, Layout, LayoutGrid + +### Key color-aware components + +- **``** β€” wraps a subtree in an explicit color mode. +- **``** β€” applies a background color and automatically switches the color mode inside to maintain accessible contrast. Use this instead of raw `bg` for any content-bearing surface. + +--- + +## Global Elements + +| Token | Value | Use | +|---|---|---| +| `headerHeight` | 4rem (64px) base, 5rem (80px) at `md`+ | Global page header height | +| `headerZ` | 15 | Z-index for global page headers | + +--- + +## Figma ↔ Code Mapping + +52 components have Code Connect entries in `packages/code-connect/`. These appear as live code snippets in Figma's inspect panel when you select a component. + +Figma layer names use emojis as visual shorthand (e.g. `✏️ label`, `πŸ‘ leading icon`, `↳ trailing icon`). These map to named props in the React components. + +To publish updated code snippets after changing a component: +``` +npx figma connect publish --token +``` diff --git a/packages/gamut/agent-tools/agents/.gitkeep b/packages/gamut/agent-tools/agents/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/gamut/agent-tools/commands/gamut-review.md b/packages/gamut/agent-tools/commands/gamut-review.md new file mode 100644 index 0000000000..054c7bc32f --- /dev/null +++ b/packages/gamut/agent-tools/commands/gamut-review.md @@ -0,0 +1,141 @@ +--- +description: Review a project's Gamut design system setup β€” checks dependencies, GamutProvider wiring, import patterns, and hardcoded hex colors with token suggestions. +argument-hint: [path] +allowed-tools: Read Glob Grep +--- + +Review the Gamut setup for the project at **`$ARGUMENTS`** (default: current working directory). Run all four checks below, then print a single consolidated report using the format at the end of this file. + +--- + +## Check 1 β€” Dependencies + +Read `package.json` (and `package.json` in `$ARGUMENTS` if a path was given). Inspect `dependencies`, `devDependencies`, and `peerDependencies` combined. + +| Package | Expectation | +|---|---| +| `@codecademy/gamut` | **Required** β€” core component library | +| `@codecademy/gamut-styles` | Recommended β€” design tokens and theme primitives | +| `@codecademy/variance` | Recommended β€” style-prop system used by Gamut internals | + +--- + +## Check 2 β€” Setup + +Search source files (`.ts`, `.tsx`, `.js`, `.jsx`) for these symbols. Skip `node_modules`, `dist`, `.next`, `build`, `.turbo`. + +| Symbol | Expectation | +|---|---| +| `GamutProvider` | **Required** β€” must appear at least once (app root wrapper) | +| `ColorMode` | Recommended β€” enables semantic light/dark theming | +| `Background` | Recommended β€” semantic surface color via `@codecademy/gamut` | + +For each found symbol report the first file path where it appears. + +--- + +## Check 3 β€” Import patterns + +Grep source files for any of these patterns. Each match is an error. + +| Pattern | Reason | +|---|---| +| `@codecademy/gamut/dist/` | Deep dist import β€” bypasses public API and breaks on internal refactors | +| `@codecademy/gamut/src/` | Deep src import β€” not part of the published package | +| `@codecademy/gamut-styles/src/` | Deep src import β€” use the package root | +| `@codecademy/variance/src/` | Deep src import β€” use the package root | + +Report each violation as `file:line`. + +--- + +## Check 4 β€” Hardcoded colors + +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): + +| Hex | Token | +|---|---| +| `#000000` | `black` | +| `#ffffff` | `white` | +| `#10162f` | `navy` / `navy-800` | +| `#0a0d1c` | `navy-900` | +| `#fff0e5` | `beige-100` | +| `#f5fcff` | `blue-0` | +| `#d3f2ff` | `blue-100` | +| `#66c4ff` | `blue-300` | +| `#3388ff` | `blue-400` | +| `#1557ff` | `blue-500` | +| `#1d2340` | `blue-800` | +| `#f5ffe3` | `green-0` | +| `#eafdc6` | `green-100` | +| `#aee938` | `green-400` / `lightGreen` | +| `#008a27` | `green-700` | +| `#151c07` | `green-900` | +| `#fffae5` | `yellow-0` | +| `#cca900` | `yellow-400` | +| `#ffd300` | `yellow-500` / `yellow` | +| `#211b00` | `yellow-900` | +| `#fff5ff` | `pink-0` | +| `#f966ff` | `pink-400` / `pink` | +| `#fbf1f0` | `red-0` | +| `#e85d7f` | `red-300` | +| `#dc5879` | `red-400` / `paleRed` | +| `#e91c11` | `red-500` / `red` | +| `#be1809` | `red-600` | +| `#280503` | `red-900` | +| `#ffe8cc` | `orange-100` | +| `#ff8c00` | `orange-500` / `orange` | +| `#5533ff` | `hyper-400` | +| `#3a10e5` | `hyper-500` / `hyper` | +| `#f5f5f5` | `gray-100` | +| `#eeeeee` | `gray-200` | +| `#e0e0e0` | `gray-300` | +| `#9e9e9e` | `gray-600` | +| `#616161` | `gray-800` | +| `#424242` | `gray-900` | +| `#fffbf8` | `beige-0` | +| `#8a7300` | `gold-800` / `gold` | +| `#d14900` | `orange-800` | +| `#ca00d1` | `pink-800` | +| `#006d82` | `teal-500` / `teal` | +| `#b3ccff` | `purple-300` / `purple` | + +Ignore hex values inside design token definition files themselves (e.g. `variables/colors.ts`, `_colors.scss`) β€” those are the source of truth, not violations. + +For each match outside token files report: `file:line 'HEX' β†’ token` (or `β†’ no Gamut token` if unknown). + +--- + +## Output format + +``` +Gamut Review β€” +══════════════════════════════════════════════════ + +Dependencies + βœ“ @codecademy/gamut + ⚠ @codecademy/gamut-styles not found β€” recommended + βœ— @codecademy/variance not found β€” recommended + +Setup + βœ“ GamutProvider found (src/App.tsx) + ⚠ ColorMode not found β€” use ColorMode for light/dark theming + ⚠ Background not found β€” use for semantic surfaces + +Import patterns + βœ“ Deep dist imports none found + βœ— Deep src imports 2 occurrences + src/Thing.tsx:7 + src/Other.tsx:12 + +Hardcoded colors + ⚠ src/Hero.tsx:14 '#1557FF' β†’ blue-500 + ⚠ src/Nav.tsx:8 '#BADA55' β†’ no Gamut token + +══════════════════════════════════════════════════ + error(s), warning(s) found. (or "All checks passed." if none) +``` + +Icons: `βœ“` = pass, `⚠` = warning (recommended, not required), `βœ—` = error (required). + +After printing the report, offer one sentence of prioritized next-step advice based on what was found. diff --git a/packages/gamut/agent-tools/rules/accessibility.mdc b/packages/gamut/agent-tools/rules/accessibility.mdc new file mode 100644 index 0000000000..fe4a1acbb0 --- /dev/null +++ b/packages/gamut/agent-tools/rules/accessibility.mdc @@ -0,0 +1,40 @@ +--- +description: Accessibility guardrails for Gamut-based UI. Enforces semantic HTML, accessible names, ARIA discipline, and contrast. +alwaysApply: true +globs: ["*.tsx", "*.ts", "*.jsx", "*.js"] +--- + +# Gamut Accessibility Rules + +## Use Gamut components β€” don't reimplement what they already solve + +Gamut wraps `react-aria-components` and `@react-aria/interactions`. Keyboard navigation, focus management, and ARIA attribute management come for free: + +- `