Repository navigation
Conversation
- Ran the color-roles codemod on gamut, then resolved every leftover (splits, retired and pending names, old palette colors, runtime names) from design's component map in colorSystem/migration.ts. - Buttons follow design's button map: action families per variant, interface merges into primary, text-inverse labels, one action-primary focus ring, state veils for StrokeButton and TextButton, disabled knockout, CTAButton's offset shadow on action-neutral. - Card variants become surfaces, with the brand gradient for yellow and hyper; Alert's gradient layer moves to utils/gradientLayer for both. - Stories that painted old palette colors use roles or mode scopes. - BREAKING: old themes don't define the roles, so components lose their colors on core, admin, platform, percipio and lxStudio until they're rebuilt as brands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mponents Picks up #50's tokensCss injection in GamutProvider and the merge of main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mponents Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s brands Each old theme becomes a brand of the generated color system, so every theme defines every role and components on roles work under all of them. - Hues come from what the old theme rendered in each job, including what it inherited from core. Page backgrounds, text and yellow are pinned. Percipio and lxStudio keep core's yellow accent and dark mode. - Fonts, weights, elevation and lxStudio's radii are unchanged. createBrandTheme takes `borderRadii` and `initialMode`; platform starts in dark mode and adds its editor-* colors with their old values. - The two-color gradient pairs primary with accent-alt for every brand with a yellow accent, as design asked for Original Codecademy. - validate-tokens treats a polished rounding tie as agreement with the content-mode table and reports it (percipio primary-600). - The styling contract test only reads the blocks of the brand it tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design's card map (Interactive) puts a `state-hover` veil over the card's own fill and darkens the edge to `border-strong` on hover. The veil is a layer behind the content, so it tints the fill and a brand gradient but not the text, and it keys off the same wrapper hover as the elevation lift. The theme's elevation hover stays until elevation tokens exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ran the color-roles codemod over packages/styleguide and resolved every split, retirement and old palette color it flagged, following design's migration map and the choices gamut's components already made. Stories and docs that list color names now show roles, MDX examples included. The Storybook provider sets the page surface from the selected theme's `background-current` instead of a white/navy palette pair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…olor-components Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ption Every theme in the toolbar is now a brand of the generated color system. Old core has no roles, so components on roles render without color under it; Original Codecademy is its rebuild. The core theme docs page shows Original Codecademy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
packages/.storybook is the config Storybook runs; the theme default change only belongs there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gacy-brands Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design feedback on the comparison page (2026-10-29): pinned navy-800 carries much more chroma than the generated surfaces beside it. As for Original Codecademy (#52), lxStudio uses the generated step at navy's hue. Admin and platform inherit Original Codecademy's pins, so they follow; platform's blue-0 and the near-white pages are nearly achromatic and stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…olor-components Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design feedback on the comparison page (2026-10-29): selection and navigation tags shouldn't have a fill. - Navigation and suggestion tags rest on a transparent fill instead of surface-raised, so they don't show as a white box on beige or paper pages. Hover and press stay veils. - A disabled tag drops the action-disabled fill. With nothing under it, the knockout label becomes the action-disabled ink; a disabled selection chip keeps an inset border-default edge so it doesn't resize. - The selection chip at rest stays a text-subtle chip, per design's map. - Adds Tag's first unit tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dreamwasp
left a comment
There was a problem hiding this comment.
Fix from design feedback on the components comparison page (2026-10-29).
| */ | ||
| navigation: { | ||
| bg: 'background-current', | ||
| bg: 'transparent', |
There was a problem hiding this comment.
Design feedback (2026-10-29): selection and navigation tags shouldn't have a fill. Navigation and suggestion tags were surface-raised, which shows as a white box on beige or paper pages. They're transparent now, so they sit on whatever surface they're on; hover and press stay state-hover / state-pressed veils. The selection chip at rest stays text-subtle behind text-inverse, per design's map.
| * a knockout label to sit on. The label takes the disabled ink instead, | ||
| * and the chip keeps an edge, inset so disabling it doesn't resize it. | ||
| */ | ||
| selectionDisabled: { |
There was a problem hiding this comment.
Disabled tags lose the action-disabled fill too. A knockout label (surface-raised) needs a fill under it, so the label becomes the action-disabled ink instead. This is contrast-exempt as an inactive control. The chip keeps a border-default edge as an inset shadow, so disabling it doesn't change its size. Navigation, suggestion and the dismiss button get the same treatment below.
Overview
Moves every gamut component onto the color system's roles, following design's component map (gamut-sandbox PR #34, Migration → Components, head
ef1272a). Stacked on #52. Draft, for showing the team what the components look like on the new colors.Screenshots: today's core next to this branch on
skillsoftandoriginalCodecademy, light and dark, 37 stories: https://claude.ai/artifact/QJ836yQVQ6ghKHwawDqE5m (private; ask for access).How it was made
color-rolespreset from feat(gamut-codemods): add a color-roles preset #53 onpackages/gamut/src: 60 files, 273 lines. A second run changes nothing.Buttons (
Button/shared/variants.ts)variantvalues don't change.primary,secondaryanddangermap toaction-primary,action-neutralandaction-danger, each with its own hover and pressed step;interfacemerges into primary (TextButton's interface label istext-default).text-inverse; every variant gets oneaction-primaryfocus ring; disabled fill labels are a knockout.state-hover/state-pressedveils instead of a gray fill and a full inversion.action-neutraluntil there's a shadow role.Components, by design's map
Alert,Toast,Popover,Menu,Tip,Modals,Flyout,Overlay— floating surfaces aresurface-raisedwith aborder-defaultedge; the scrim isbackdrop. Tooltips are no longer black.Form,GridForm,ConnectedForm,Toggle— fields onsurface-raised, hover darkens the outline (border-strong) so blue only means focus; a checked Radio isaction-primary; Toggle disabled isaction-disabledinstead of 50% opacity.Card— yellow and hyper become a featured card on the brand gradient (Alert's gradient layer moved toutils/gradientLayer.tsso both use it); navy is a dark-mode scope; every card gets aborder-subtlehairline.Badge,Tag— filled badges aretext-default/text-subtlebehindtext-inverse; accent issurface-brandwith aborder-defaultedge.Tabs,Disclosure,Pagination,Anchor— block Tabs follow the page's mode instead of forcing dark; Disclosure focus is a ring, not a fill.ProgressBar,DataList,List,BarChart,Markdown,Video,Loading,Typographyand the rest — mapped by the closest documented rule; see "Choices" below.Choices where design has no exact mapping (each has a
/* */comment at the spot)background-currentstays in List, Drawer, DataList empty rows, Card's offset shadow, RadialProgress and Text fade. Design describes asurface-currentalias that every surface sets; that rename belongs in gamut-styles, as a follow-up.surface-brand, not the gradient: the gradient is sized incqw, and a content-sized badge can't be its own container.text-subtle, todayaction-primary, selected day a dark chip withtext-inverse, rangestate-selected, disabledaction-disabled.text-subtle/text-inverse). Design's slot sayssurface-sunkenbut its note says "follows the selection Tag", so this needs design to pick.primary-inverse(Text highlight) →action-primary, flagged for design.whiteandblack.viz-*is a follow-up.Added 2026-10-29
coreThemestill has no roles; Original Codecademy is its rebuild.styleguide: its stories and docs are on roles (52 files). The type check has no color errors left; the 23 remaining errors exist on the base branch too (argTypes alias, InfoTip, BarChart, Tabs types).Card: an interactive card gets design's hover. The border goes toborder-strong, and astate-hoverveil sits under the content, on the same trigger as the existing lift. 4 new tests.Tag(design feedback, 2026-10-29): navigation and suggestion tags have no fill of their own, so they sit on the surface they're on. Disabled tags drop theaction-disabledfill, takeaction-disabledink, and keep their edge. The selection chip at rest stays a dark chip, per design's map. Adds Tag's first tests.background-selectedas a resting panel →surface-sunkentext-disabledas muted helper text →text-subtlebackground-contrastas a label on a fill →text-inversedangeras red text →text-errorsurface-brandKnown gaps
undefined.viz-*is a follow-up.PR Checklist
.changeset/color-roles-components.md)Testing Instructions
npx jest -c packages/gamut/jest.config.ts→ 1208 of 1208 pass. On feat(gamut-styles)!: brands, overrides and Original Codecademy on the color system #52, 48 BarChart and Modal tests fail because they expect old names.npx jest -c packages/gamut-styles/jest.config.ts→ 280 of 280;yarn workspace @skillsoft/gamut-styles validate:tokens→ every check passes for both brands.🤖 Generated with Claude Code