Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
4728ba1
feat(gamut-codemods): add the codemods CLI and an empty scope-swap pr…
dreamwasp Oct 20, 2026
5a91398
feat(gamut-codemods): rename packages and replace gamut-kit in scope-…
dreamwasp Oct 20, 2026
b3a27cd
feat(gamut-codemods): move Video imports and add Markdown video overr…
dreamwasp Oct 20, 2026
195e6d6
feat(gamut)!: promote deep imports to the root, renaming Menu and Sel…
dreamwasp Oct 20, 2026
161242f
feat(gamut-codemods): rename the ESLint plugin prefix in scope-swap
dreamwasp Oct 20, 2026
b39bd0c
feat(gamut-codemods): warn about esmExternals: false in next.config
dreamwasp Oct 20, 2026
3f2e1bd
Merge branch 'cass-gmt-1790-deep-imports' into cass-gmt-1790-scope-sw…
dreamwasp Oct 20, 2026
c44953d
Merge branch 'cass-gmt-1790-eslint' into cass-gmt-1790-scope-swap-skill
dreamwasp Oct 20, 2026
199d30f
Merge branch 'cass-gmt-1790-next-config' into cass-gmt-1790-scope-swa…
dreamwasp Oct 20, 2026
4a7dfb6
feat(gamut-agent-tools): add the gamut-scope-swap skill
dreamwasp Oct 20, 2026
e6923f5
fix(gamut-codemods): rename FileMigration.match to appliesTo
dreamwasp Oct 20, 2026
961c09b
Merge branch 'cass-gmt-1790-scaffold' into cass-gmt-1790-scope-rename
dreamwasp Oct 20, 2026
97d492c
fix(gamut-codemods): rename match to appliesTo in this branch's file …
dreamwasp Oct 20, 2026
6673ca8
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-video-ma…
dreamwasp Oct 20, 2026
34ad6a1
fix(gamut-codemods): rename match to appliesTo in this branch's file …
dreamwasp Oct 20, 2026
1436118
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-deep-imp…
dreamwasp Oct 20, 2026
7d0ce3d
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-eslint
dreamwasp Oct 20, 2026
b00216c
fix(gamut-codemods): rename match to appliesTo in this branch's file …
dreamwasp Oct 20, 2026
82bd085
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-next-config
dreamwasp Oct 20, 2026
84758da
fix(gamut-codemods): rename match to appliesTo in this branch's file …
dreamwasp Oct 20, 2026
6c622a1
Merge branch 'cass-gmt-1790-video-markdown' into cass-gmt-1790-scope-…
dreamwasp Oct 20, 2026
125cfa7
Merge branch 'cass-gmt-1790-deep-imports' into cass-gmt-1790-scope-sw…
dreamwasp Oct 20, 2026
4b86b7f
Merge branch 'cass-gmt-1790-eslint' into cass-gmt-1790-scope-swap-skill
dreamwasp Oct 20, 2026
e41c57d
Merge branch 'cass-gmt-1790-next-config' into cass-gmt-1790-scope-swa…
dreamwasp Oct 20, 2026
7cf5c68
refactor(gamut-codemods): drop the newer-than-source checklist item
dreamwasp Oct 20, 2026
1afc987
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-video-ma…
dreamwasp Oct 20, 2026
6670c23
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-deep-imp…
dreamwasp Oct 20, 2026
f14f0ae
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-eslint
dreamwasp Oct 20, 2026
413c601
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-next-config
dreamwasp Oct 20, 2026
fad1c46
Merge branch 'cass-gmt-1790-video-markdown' into cass-gmt-1790-scope-…
dreamwasp Oct 20, 2026
1d4aa4b
Merge branch 'cass-gmt-1790-deep-imports' into cass-gmt-1790-scope-sw…
dreamwasp Oct 20, 2026
8af554b
Merge branch 'cass-gmt-1790-eslint' into cass-gmt-1790-scope-swap-skill
dreamwasp Oct 20, 2026
8d639e5
Merge branch 'cass-gmt-1790-next-config' into cass-gmt-1790-scope-swa…
dreamwasp Oct 20, 2026
8c0b958
chore(changeset): one changeset per package for Video and Markdown
dreamwasp Oct 20, 2026
34cf28e
Merge branch 'cass-gmt-1790-video-markdown' into cass-gmt-1790-scope-…
dreamwasp Oct 20, 2026
79fe678
chore(changeset): one changeset for the new gamut root exports
dreamwasp Oct 20, 2026
4cd726f
Merge branch 'cass-gmt-1790-deep-imports' into cass-gmt-1790-scope-sw…
dreamwasp Oct 20, 2026
da715ae
Merge branch 'main' into cass-gmt-1790-scaffold
dreamwasp Oct 26, 2026
6d427e3
Merge branch 'cass-gmt-1790-scaffold' into cass-gmt-1790-scope-rename
dreamwasp Oct 26, 2026
f1d2a29
Merge branch 'cass-gmt-1790-scope-rename' into cass-gmt-1790-scope-sw…
dreamwasp Oct 26, 2026
3ebf1b7
feat(gamut-styles): color system with tokens.css as the color contrac…
dreamwasp Oct 26, 2026
ff90dca
chore: add changeset for the color system
dreamwasp Oct 27, 2026
a435cf0
feat(gamut-styles)!: brands, overrides and Original Codecademy on the…
dreamwasp Oct 27, 2026
5e3d707
feat(gamut-codemods): add a color-roles preset
dreamwasp Oct 27, 2026
75fc87a
Merge branch 'main' into cass-gmt-1825-color-codemod
dreamwasp Oct 28, 2026
fa0b3b9
feat(gamut-styles): GamutProvider injects tokens.css
dreamwasp Oct 28, 2026
010addb
Merge remote-tracking branch 'origin/main' into cass-gmt-1825-color-s…
dreamwasp Oct 28, 2026
59416ca
feat(gamut)!: move components onto color roles
dreamwasp Oct 28, 2026
e0699a0
Merge branch 'cass-gmt-1825-color-system' into cass-gmt-1825-color-br…
dreamwasp Oct 28, 2026
b1f574e
Merge branch 'cass-gmt-1825-color-brands' into cass-gmt-1825-color-co…
dreamwasp Oct 28, 2026
4585a13
feat(gamut-styles): per-brand gradient overrides; Original Codecademy…
dreamwasp Oct 29, 2026
b05e3e9
Merge branch 'cass-gmt-1825-color-brands' into cass-gmt-1825-color-co…
dreamwasp Oct 29, 2026
21540cb
feat(gamut-styles)!: rebuild admin, platform, percipio and lxStudio a…
dreamwasp Oct 29, 2026
399c188
docs(gamut-docs): add the color system concept page
dreamwasp Oct 29, 2026
ed1f8a6
docs(gamut-docs): list the rebuilt admin, platform, percipio and lxSt…
dreamwasp Oct 29, 2026
e4e6a7e
feat(gamut): give interactive Cards design's hover veil
dreamwasp Oct 29, 2026
eeb4dfb
feat(styleguide): move stories and docs onto color roles
dreamwasp Oct 29, 2026
1a728e6
Merge branch 'cass-gmt-1825-color-legacy-brands' into cass-gmt-1825-c…
dreamwasp Oct 29, 2026
2af0982
chore(storybook): default to the Skillsoft theme; drop the old Core o…
dreamwasp Oct 29, 2026
f22e7b5
chore(styleguide): leave the unused .storybook copy's theme map alone
dreamwasp Oct 29, 2026
424a2d4
fix(gamut): Alert takes design's status inks; Original Codecademy sto…
dreamwasp Oct 29, 2026
dd90133
Merge branch 'cass-gmt-1825-color-brands' into cass-gmt-1825-color-le…
dreamwasp Oct 29, 2026
4268c86
fix(gamut-styles): lxStudio stops pinning navy
dreamwasp Oct 29, 2026
5cb9f23
Merge branch 'cass-gmt-1825-color-legacy-brands' into cass-gmt-1825-c…
dreamwasp Oct 29, 2026
960edad
fix(gamut): navigation, suggestion and disabled tags have no fill
dreamwasp Oct 29, 2026
e5165c3
Merge branch 'cass-gmt-1825-color-legacy-brands' into cass-gmt-1825-c…
dreamwasp Oct 29, 2026
41c22f7
docs(gamut-docs): navy and beige unpinned; status alerts carry their ink
dreamwasp Oct 29, 2026
b7b704a
feat(gamut-styles): shadow roles and brand elevation from design's sa…
dreamwasp Nov 4, 2026
47ca708
feat(gamut-styles)!: remove percipioTheme; lxStudio stops pinning yellow
dreamwasp Nov 4, 2026
e0a64e8
Merge #52 (design's sandbox update, df33b47) into cass-gmt-1825-color…
dreamwasp Nov 4, 2026
9dfdd52
Merge #58 (design's sandbox update, df33b47) into cass-gmt-1825-color…
dreamwasp Nov 4, 2026
f5695fc
feat(gamut-styles): Original Codecademy's raised depth is old core's …
dreamwasp Nov 4, 2026
aea6fd2
Merge remote-tracking branch 'origin/cass-gmt-1825-color-brands' into…
dreamwasp Nov 4, 2026
9af4dca
Merge remote-tracking branch 'origin/cass-gmt-1825-color-legacy-brand…
dreamwasp Nov 4, 2026
edde433
feat(gamut): components follow design's sandbox update
dreamwasp Nov 4, 2026
2ba244b
feat(gamut-codemods): color-roles covers stylesheets, JS strings and …
dreamwasp Nov 4, 2026
fcd29d1
docs(gamut-docs): percipioTheme is removed; five brands ship
dreamwasp Nov 4, 2026
f11a9dd
Merge remote-tracking branch 'origin/cass-gmt-1825-color-legacy-brand…
dreamwasp Nov 4, 2026
fe7333e
docs(gamut-docs): color system page follows design's sandbox update
dreamwasp Nov 4, 2026
c0cec9f
chore(gamut-styles): changeset says skillsoftTheme replaces percipioT…
dreamwasp Nov 4, 2026
781feeb
chore(gamut-styles): report labels the migration map at df33b47
dreamwasp Nov 4, 2026
b9789a9
Merge cass-gmt-1825-color-brands into cass-gmt-1825-color-legacy-brands
dreamwasp Nov 4, 2026
0c54a72
Merge cass-gmt-1825-color-legacy-brands into cass-gmt-1825-color-docs
dreamwasp Nov 4, 2026
bdab784
docs(gamut-docs): skillsoftTheme replaces percipioTheme; 204 componen…
dreamwasp Nov 4, 2026
17fc3ee
feat(gamut-codemods): color-roles renames the old theme names
dreamwasp Nov 4, 2026
75f068b
Merge main into cass-gmt-1825-color-codemod
dreamwasp Nov 4, 2026
1e57c91
Merge remote-tracking branch 'origin/main' into cass-gmt-1825-color-s…
dreamwasp Nov 4, 2026
20a31de
Merge branch 'cass-gmt-1825-color-system' into cass-gmt-1825-color-br…
dreamwasp Nov 4, 2026
06ad077
Merge branch 'cass-gmt-1825-color-brands' into cass-gmt-1825-color-le…
dreamwasp Nov 4, 2026
b6d9ddf
Merge branch 'cass-gmt-1825-color-brands' into cass-gmt-1825-color-co…
dreamwasp Nov 4, 2026
1f4d7fa
Merge branch 'cass-gmt-1825-color-legacy-brands' into cass-gmt-1825-c…
dreamwasp Nov 4, 2026
f6ebb92
fix(gamut): type the CTAButton elevation for the button factory; text…
dreamwasp Nov 4, 2026
2407db6
fix(gamut-codemods): narrow isString so the color-roles build typechecks
dreamwasp Nov 4, 2026
809e04c
fix(gamut): field fills, form states and floating-surface patterns fr…
dreamwasp Nov 4, 2026
5b345cd
feat(gamut): selected-row tint, raised table rows and a two-tone Prog…
dreamwasp Nov 4, 2026
7aa5810
test(gamut-styles): sandbox parity runs in CI, against a fixture that…
dreamwasp Nov 4, 2026
fef0319
Merge remote-tracking branch 'origin/cass-gmt-1825-color-brands' into…
dreamwasp Nov 4, 2026
6faecba
Merge remote-tracking branch 'origin/cass-gmt-1825-color-brands' into…
dreamwasp Nov 4, 2026
b3f6b9b
Merge remote-tracking branch 'origin/cass-gmt-1825-color-components' …
dreamwasp Nov 4, 2026
2d9af71
Merge remote-tracking branch 'origin/cass-gmt-1825-color-legacy-brand…
dreamwasp Nov 4, 2026
13efd24
feat(gamut-brand)!: one tokens.css per brand, and white-label tooling
dreamwasp Nov 5, 2026
74995d7
Merge branch 'cass-gmt-1825-color-white-label' into cass-gmt-1825-col…
dreamwasp Nov 5, 2026
d4a0eda
Merge branch 'cass-gmt-1825-color-white-label' into cass-gmt-1825-col…
dreamwasp Nov 5, 2026
5a2390c
fix(gamut-brand): dump:sandbox writes the fixture where it moved
dreamwasp Nov 5, 2026
bded536
docs(gamut): component map comments point at gamut-brand's migration.ts
dreamwasp Nov 5, 2026
a10b5b2
Merge branch 'cass-gmt-1825-color-components' into cass-gmt-1825-colo…
dreamwasp Nov 5, 2026
75a06be
Merge branch 'cass-gmt-1825-color-white-label' into cass-gmt-1825-col…
dreamwasp Nov 5, 2026
ed87041
docs(gamut-docs): color system page covers per-brand CSS and building…
dreamwasp Nov 5, 2026
c641a95
docs(gamut-codemods): color-roles points at design's map in gamut-brand
dreamwasp Nov 5, 2026
f73f65c
test(gamut-brand): general generator tests in place of sandbox parity
dreamwasp Nov 5, 2026
9918022
Merge branch 'cass-gmt-1825-color-white-label' into cass-gmt-1825-col…
dreamwasp Nov 5, 2026
1501ed6
Merge branch 'cass-gmt-1825-color-components' into cass-gmt-1825-colo…
dreamwasp Nov 5, 2026
129a045
docs(gamut): component comments state design's map without sandbox co…
dreamwasp Nov 5, 2026
ab01baf
Merge branch 'cass-gmt-1825-color-white-label' into cass-gmt-1825-col…
dreamwasp Nov 5, 2026
6dad02d
docs(gamut-codemods): color-roles comments without sandbox commits
dreamwasp Nov 5, 2026
47d1213
Merge branch 'cass-gmt-1825-color-docs' into cass-gmt-1825-color-site
dreamwasp Nov 5, 2026
5086aa2
docs(gamut-docs): move the docs site onto the color system
dreamwasp Nov 5, 2026
b3e6deb
Merge branch 'main' into cass-gmt-1825-color-codemod
dreamwasp Nov 9, 2026
8c0fcd9
chore(gamut-styles): move the color generator to cass-gmt-1825-color-…
dreamwasp Nov 9, 2026
87d0ec1
Revert "chore(gamut-styles): move the color generator to cass-gmt-182…
dreamwasp Nov 9, 2026
f4f76ff
docs(gamut-styles): split color README between the package and the ge…
dreamwasp Nov 9, 2026
938000c
Merge remote-tracking branch 'origin/main' into cass-gmt-1825-color-s…
dreamwasp Nov 9, 2026
757274c
Merge origin/cass-gmt-1825-color-system into cass-gmt-1825-color-brands
dreamwasp Nov 9, 2026
add32c3
feat(gamut-styles)!: drop the old themes from this PR
dreamwasp Nov 10, 2026
593ed3e
Merge remote-tracking branch 'origin/main' into cass-gmt-1825-color-s…
dreamwasp Nov 10, 2026
d7945a1
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
d7483fc
Merge branch 'cass-gmt-1825-color-system' into cass-gmt-1825-color-br…
dreamwasp Nov 10, 2026
d131a2d
refactor(gamut-codemods): rewrite old colors to the singular --color-…
dreamwasp Nov 10, 2026
12094eb
docs(changeset): drop the variable rename, the prefix stays --color-
dreamwasp Nov 10, 2026
3e08400
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
80c206c
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
001a5ff
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
c30e2cb
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
20b5b44
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
09e0187
refactor: use the singular --color- prefix for color variables
dreamwasp Nov 10, 2026
f703ea4
Merge remote-tracking branch 'origin/cass-gmt-1825-color-codemod' int…
dreamwasp Nov 10, 2026
f00c09b
Merge remote-tracking branch 'origin/main' into cass-gmt-1825-color-p…
dreamwasp Nov 10, 2026
ccf7597
Merge remote-tracking branch 'origin/cass-gmt-1825-color-system' into…
dreamwasp Nov 10, 2026
2b0cf3c
Merge remote-tracking branch 'origin/cass-gmt-1825-color-brands' into…
dreamwasp Nov 10, 2026
0fb4e06
Merge remote-tracking branch 'origin/cass-gmt-1825-color-legacy-brand…
dreamwasp Nov 10, 2026
63a8c6b
Merge remote-tracking branch 'origin/cass-gmt-1825-color-components' …
dreamwasp Nov 10, 2026
58398da
Merge remote-tracking branch 'origin/cass-gmt-1825-color-docs' into c…
dreamwasp Nov 10, 2026
5fc62f0
Merge remote-tracking branch 'origin/cass-gmt-1825-color-behavior' in…
dreamwasp Nov 10, 2026
e344128
Merge remote-tracking branch 'origin/cass-gmt-1825-color-white-label'…
dreamwasp Nov 10, 2026
1549c30
Merge remote-tracking branch 'origin/cass-gmt-1825-color-codemod' int…
dreamwasp Nov 10, 2026
52184a4
fix(ci): unblock PR 73 checks (lint, tests, dedupe, CodeQL)
dreamwasp Nov 10, 2026
c017b8d
fix(color): disabled text uses text-subtle, not action-disabled
dreamwasp Nov 11, 2026
8a4f749
test(storybook): exempt raw palette swatches from contrast, not roles
dreamwasp Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions .changeset/color-roles-component-behavior.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@skillsoft/gamut': minor
---

Component behavior from design's component map that the role swap didn't cover.

- A selected DataList or DataTable row takes the `state-selected` veil over its fill, with the hover veil on top when hovered. `ListRow` takes an `isSelected` prop for the same tint.
- Table rows are `surface-raised`, with `surface-sunken` stripes, instead of transparent.
- ProgressBar's label at `large` and `xl` sizes is two-tone: `text-inverse` on the bar and `text-default` where it runs onto the track, so a short bar's label stays readable.
18 changes: 18 additions & 0 deletions .changeset/color-roles-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@skillsoft/gamut': minor
---

Components use the color system's roles, following design's component map.

- **Breaking:** every color name a component uses is a role (`surface-raised`, `text-subtle`, `action-primary`, `state-hover`, …). Code that passes old names (`background`, `primary`, `navy`, `text-disabled`) to gamut props has to move; the `color-roles` codemod in `@skillsoft/gamut-codemods` does most of it.
- **Breaking:** old `coreTheme` doesn't define the roles, so components lose their colors on it. Use `originalCodecademyTheme`, its rebuild, or `skillsoftTheme`. Admin, platform and lxStudio are rebuilt as brands and keep their names.
- Buttons map onto the action families: `secondary` is `action-neutral`, `interface` merges into primary, labels on fills are `text-inverse`, every variant takes the `action-primary` focus ring, and StrokeButton and TextButton hover and press with veils.
- Fields are `surface-raised` with a `border-default` edge; field hover is `border-strong`, so blue only means focus. Floating surfaces (menus, popovers, tooltips, toasts, the SelectDropdown menu) are `surface-raised` with a `border-subtle` hairline and the theme's raised shadow. A checked Radio is `action-primary`.
- **Breaking:** Card's `variant` is `default` or `brand`. `white`, `beige` and `navy` become `default` (`surface-raised`); `yellow` and `hyper` become `brand`, the featured card on the brand gradient. Every card has a `border-subtle` hairline. An interactive card has the raised shadow at rest, and the `state-hover` veil with the raised-hover shadow on hover; its border no longer changes. A card that isn't interactive has no shadow.
- CTAButton's shadow comes from the theme's elevation: the soft raised shadow on most brands, old core's hard offset on Original Codecademy.
- Modal and Flyout's scrim is `shadow-scrim`, and Flyout's panel has a `border-subtle` inner edge.
- ProgressBar's blue and yellow bars are `text-default` on a sunken track. Block Tabs follow the page's mode instead of forcing dark.
- `Tag`: navigation and suggestion tags have no fill of their own, so they sit on the surface they're on. Disabled tags drop the `action-disabled` fill and take the disabled ink, keeping their edge.
- Every input-like control fills with `surface-raised`, an unchecked Checkbox included. Placeholders are `text-subtle`, an error is a 2px `text-error` outline at rest, and an edited field keeps its `border-default` outline. A disabled DatePicker field now looks disabled, and its error ring draws. FormGroup descriptions are `text-subtle`.
- The checker pattern behind Modal, Toast, PreviewTip and the DatePicker calendar is drawn only on Original Codecademy, in `border-subtle`. Themes from before the color system keep it.
- Smaller fixes from design's map: link hover is `action-primary-hover`, link focus rings are `action-primary`, the Breadcrumbs separator is `text-subtle`, List row hover is a veil over the row's fill, focus is a ring without a fill, and Shimmer is a `surface-sunken` base with a `surface-raised` sweep.
16 changes: 16 additions & 0 deletions .changeset/color-system-brands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@skillsoft/gamut-styles': minor
'@skillsoft/variance': minor
'@skillsoft/gamut': minor
---

Brands on the generated color system.

- **Breaking:** `tokens.css` puts its rules in `@layer tokens`, with `reset, base, tokens, recipes, utilities` declared first.
- Adds `originalCodecademyTheme`, today's core colors, fonts and hard-offset elevation rebuilt on the generated system. `tokens.css` carries a palette block per brand under `[data-brand]`.
- A brand can override a palette step with an exact hex, or point a role at a different step (and, optionally, a different alpha) in one mode. Overrides go through the same contrast checks as generated values.
- `ColorMode` on generated themes sets `data-color-mode` and `data-brand` instead of injecting every role variable.
- Fixes `Background` painting the flipped mode's color for an alias `bg`, such as `bg="primary"`.
- `Alert`: General uses `surface-brand-subtle`. Gradient alerts size their gradient to the alert, not the viewport. Status alerts (error, success, notice) put their status ink on the message, and a floating Alert's border takes the same ink. The CTA follows the Alert's color mode instead of always rendering dark.
- Original Codecademy no longer pins navy and beige; their generated steps are used as is. Yellow stays exact.
- **Breaking:** the `backdrop` role is renamed `shadow-scrim`, and two shadow roles are added: `shadow-key` and `shadow-ambient`, the two layers every elevation shadow is drawn in. Brand themes' `elevation` now uses them, so shadows no longer render `undefined`: Skillsoft gets the soft raised shadow, and Original Codecademy keeps old core's hard offset with a transparent `shadow-ambient`.
11 changes: 11 additions & 0 deletions .changeset/color-system-legacy-brands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@skillsoft/gamut-styles': minor
---

Rebuild `adminTheme`, `platformTheme` and `lxStudioTheme` as brands of the generated color system, so they define every color role.

- Each brand takes its colors from what the old theme rendered in each job, including what it inherited from core, such as lxStudio's yellow accent. Admin and platform inherit Original Codecademy's pins (yellow exact; navy and beige not pinned). lxStudio pins only its near-white page; its yellow is generated, and its dark mode keeps the sapphire primary instead of core's yellow one.
- Fonts, weights and lxStudio's radii are unchanged. Elevation is the soft shadow drawn in the shadow roles; only Original Codecademy keeps the hard offset. `platformTheme` still starts in dark mode and keeps its `editor-*` code editor colors with their old values.
- The two-color brand gradient pairs primary with accent-alt for every brand with a yellow accent.
- **Visual change:** the rebuilt themes aren't pixel-identical to the old ones; role grades come from design's system. Old color names that only these themes had are gone.
- **Breaking:** `percipioTheme` and the `PercipioTheme` type are removed. `skillsoftTheme`, the new default, replaces it: it keeps Percipio's fonts, font weights and resting shadow, with colors generated from the Skillsoft brand's hues. Use `skillsoftTheme` wherever an app used `percipioTheme`.
12 changes: 12 additions & 0 deletions .changeset/color-system-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@skillsoft/gamut-styles': minor
'@skillsoft/gamut': minor
---

Add the generated OKLCH color system.

- `@skillsoft/gamut-styles/tokens`, `/tokens.css` and `/tokens/*.tokens.json` export an OKLCH palette and 43 semantic roles in light and dark, as static CSS, DTCG JSON and TS constants. The `tokens` entry has no React or Emotion dependency.
- `skillsoftTheme` is the new default theme. Its color values come from `tokens.css`, which `GamutProvider` injects; pass `useTokens={false}` if the page loads `@skillsoft/gamut-styles/tokens.css` itself. The static file also works without React or Emotion.
- `Background` picks the content mode from a build-time table on generated themes, instead of measuring contrast at runtime.
- The core, admin, platform, lxStudio and percipio themes are removed from this release. Brand themes built on the generator (originalCodecademy and the others) return in the PRs that follow.
- `Alert` follows design's mapping: status tints, an icon color per variant, and the brand gradient on Feature.
14 changes: 14 additions & 0 deletions .changeset/color-system-white-label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@skillsoft/gamut-brand': minor
'@skillsoft/gamut-styles': minor
---

Add `@skillsoft/gamut-brand`, for teams building their own brand on gamut, and give every brand its own `tokens.css`.

- `@skillsoft/gamut-brand` is new, and build-time only: install it as a dev dependency. `defineBrand({ name, hues })` types a brand, and `gamut-brand build <brand file>` writes its `values.ts`, `tokens.css` and DTCG JSON, refusing a brand that fails a contrast check. `--watch` regenerates when the brand file changes; `--check` fails CI when the files are out of date. The generator, the role table, the checks and gamut's own brands moved here from `@skillsoft/gamut-styles`.
- `createBrandTheme`, `BrandBase` and `BrandValues` are exported from `@skillsoft/gamut-styles`. `createBrandTheme(values, base)` turns a generated `values.ts` into a theme with the same type as gamut's own, so system props and styling functions stay typed against it.
- Each theme now carries only its own brand's colors. `GamutProvider` injects that brand's CSS, which puts its palette and its initial mode on `:root`, so a page starts in the right brand and mode without attributes on `<html>`. A brand's role overrides apply under a bare `data-color-mode` too.
- **Breaking:** the generated files moved to one folder per brand. Import `@skillsoft/gamut-styles/tokens/<brand>.css` for a brand's CSS (`tokens.css` is still the default brand) and `@skillsoft/gamut-styles/tokens/<brand>/{palette,light,dark}.tokens.json` for its DTCG files. `tokens/brands/*` is gone, and `brands` in `@skillsoft/gamut-styles/tokens` now includes the default brand.
- **Breaking:** `initialMode` moved from `createBrandTheme`'s second argument to the brand (`defineBrand({ initialMode: 'dark' })`), because the brand's CSS has to know it. `BrandBase` now requires gamut's font family and font weight keys.
- `platformTheme` now starts in dark mode in its CSS as well as in its theme, so a server-rendered page starts dark.
- The DTCG mode files include each brand's role overrides. They had the default roles for every brand.
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"fixed": [
[
"@skillsoft/gamut-agent-tools",
"@skillsoft/gamut-brand",
"@skillsoft/gamut-codemods",
"@skillsoft/gamut-icons",
"@skillsoft/gamut-illustrations",
Expand Down
13 changes: 13 additions & 0 deletions .changeset/gamut-codemods-color-roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@skillsoft/gamut-codemods': minor
---

Add a `color-roles` preset that moves Gamut color names onto the generated color system's roles, using design's migration map.

- Renames and merges are applied. Names that split, were retired or are still pending stay in place, with a `/* color-roles: … */` comment carrying design's rule, and keep failing the type check until someone picks.
- Old palette names (`navy`, `gray-200`) and color names built at runtime get a warning.
- Old `--color-*` CSS variables are renamed to `--color-<role>` in `.css`, `.scss` and `.less` files and inside JS strings and template literals; splits get the same comment. The type check can't see stylesheets, so the leftovers report lists every one left. Indented-syntax `.sass` isn't rewritten.
- Card's `variant` moves onto design's two: `white`, `beige` and `navy` become `default`, `yellow` and `hyper` become `brand`. A `navy` card gets a comment, since it now renders light.
- Old theme names move to the brand themes that replace them: `percipioTheme` → `skillsoftTheme`, `coreTheme` → `originalCodecademyTheme`, and the `PercipioTheme` type → `SkillsoftTheme`. An aliased import (`percipioTheme as theme`) only changes the imported name. A `CoreTheme` type gets a comment pointing at `SkillsoftTheme`, which types every brand.
- Follows design's map: `shadow-primary` and `shadow-secondary` split onto `shadow-key` and `shadow-ambient`.
- Presets can bring their own manifest type, pre-filter and leftovers report. `scope-swap` is unchanged.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ packages/gamut-codemods/**/__testfixtures__

/.nx/cache
/.nx/workspace-data
packages/gamut-styles/src/tokens/generated
17 changes: 9 additions & 8 deletions packages/.storybook/components/Elements/DocsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {
AssetProvider,
coreTheme,
skillsoftTheme,
createEmotionCache,
GamutProvider,
platformPalette,
adminTheme,
lxStudioTheme,
percipioTheme,
CoreTheme,
platformTheme,
skillsoftTheme,
originalCodecademyTheme,
ColorMode,
} from '@skillsoft/gamut-styles';
import {
Expand All @@ -21,24 +22,24 @@ import { useMemo } from 'react';
import { HelmetProvider } from 'react-helmet-async';
import { createGamutDocsTheme } from '../../theming/GamutTheme';
import { createTheme } from '@skillsoft/variance';
export const storybookTheme = createTheme(coreTheme)
export const storybookTheme = createTheme(skillsoftTheme)
.addColors(platformPalette)
.build();

const themeMap = {
core: coreTheme,
core: skillsoftTheme,
admin: adminTheme,
lxStudio: lxStudioTheme,
percipio: percipioTheme,
platform: platformTheme,
skillsoft: skillsoftTheme,
originalCodecademy: originalCodecademyTheme,
} as const;

const themeSpecificStories = {
'foundations-theme-lx-studio-theme--docs': 'lxStudio',
'foundations-theme-percipio-theme--docs': 'percipio',
'foundations-theme-platform-theme--docs': 'platform',
'foundations-theme-admin-theme--docs': 'admin',
'foundations-theme-core-theme--docs': 'core',
'foundations-theme-core-theme--docs': 'originalCodecademy',
};
export const DocsContainer: React.FC<{
context: DocsContextProps;
Expand All @@ -51,7 +52,7 @@ export const DocsContainer: React.FC<{
?.storyId;

const globalTheme =
(context as any).store.userGlobals?.globals?.theme || 'core';
(context as any).store.userGlobals?.globals?.theme || 'skillsoft';
const globalLogicalProps = (context as any).store.userGlobals?.globals
?.logicalProps;
const useLogicalProperties = globalLogicalProps !== 'false';
Expand Down
20 changes: 20 additions & 0 deletions packages/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,26 @@ const config: StorybookConfig = {
'../gamut-styles/src/variance/config'
),
},
// Public subpaths of gamut-styles (see its `exports`), pointed at
// source like the bare specifier above.
{
find: /^@skillsoft\/gamut-styles\/tokens$/,
replacement: resolve(__dirname, '../gamut-styles/src/tokens'),
},
{
find: /^@skillsoft\/gamut-styles\/tokens\.css(\?.*)?$/,
replacement: `${resolve(
__dirname,
'../gamut-styles/src/tokens/generated/skillsoft/tokens.css'
)}$1`,
},
{
find: /^@skillsoft\/gamut-styles\/tokens\/(\w+)\.css(\?.*)?$/,
replacement: `${resolve(
__dirname,
'../gamut-styles/src/tokens/generated'
)}/$1/tokens.css$2`,
},
...normalizeAlias(config.resolve?.alias),
],
};
Expand Down
6 changes: 3 additions & 3 deletions packages/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'core',
defaultValue: 'skillsoft',
toolbar: {
icon: 'paintbrush',
items: [
{ value: 'core', title: 'Core' },
{ value: 'skillsoft', title: 'Skillsoft' },
{ value: 'originalCodecademy', title: 'Original Codecademy' },
{ value: 'admin', title: 'Admin' },
{ value: 'lxStudio', title: 'LX Studio' },
{ value: 'percipio', title: 'Percipio' },
{ value: 'platform', title: 'Learning Platform' },
],
showName: true,
Expand Down
6 changes: 3 additions & 3 deletions packages/.storybook/systemProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { coreTheme, system } from '@skillsoft/gamut-styles';
import { skillsoftTheme, system } from '@skillsoft/gamut-styles';
import type {
ArgTypesEnhancer,
StrictInputType,
Expand Down Expand Up @@ -51,12 +51,12 @@ const categoryRank = (category: string | undefined) =>
export const isSystemPropCategory = (category: string | undefined) =>
categoryRank(category) >= 0;

const themeScales = coreTheme as unknown as Record<
const themeScales = skillsoftTheme as unknown as Record<
string,
Record<string, unknown> | undefined
>;

// Token names come from the Core theme; other themes may define more or fewer.
// Token names come from the skillsoft theme.
const getScaleTokens = ({ scale }: SystemPropConfig) =>
typeof scale === 'string' ? Object.keys(themeScales[scale] ?? {}) : [];

Expand Down
45 changes: 29 additions & 16 deletions packages/.storybook/theming/GamutThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
corePalette,
ColorModes,
GamutProvider,
coreTheme,
skillsoftTheme,
adminTheme,
lxStudioTheme,
percipioTheme,
platformTheme,
skillsoftTheme,
originalCodecademyTheme,
} from '@skillsoft/gamut-styles';
import { Theme } from '@emotion/react';

Expand All @@ -25,11 +26,12 @@ const themeBackground: Record<ColorModes, 'white' | 'navy'> = {
};

const themeMap = {
core: coreTheme,
core: skillsoftTheme,
admin: adminTheme,
lxStudio: lxStudioTheme,
percipio: percipioTheme,
platform: platformTheme,
skillsoft: skillsoftTheme,
originalCodecademy: originalCodecademyTheme,
} as const;

type GlobalsContext = {
Expand All @@ -46,9 +48,27 @@ export const withEmotion = (Story: any, context: GlobalsContext) => {
const selectedTheme = context.globals.theme;
const useLogicalProperties = context.globals.logicalProps === 'true';
const direction = context.globals.direction ?? 'ltr';
const background = corePalette[themeBackground[colorMode]];
const storyRef = useRef<HTMLDivElement>(null);
const currentTheme = themeMap[selectedTheme];
/*
* Generated themes (they carry contentModes) take their values from their
* brand's tokens.css, not Emotion. GamutProvider injects it; the test
* provider below runs without globals, so it injects the theme's own copy.
* Only for those: tokens.css also sets white, black and background-current
* on :root, which would leak into the other themes. They have none of
* core's primitives, so `navy` doesn't exist there; the story sits on their
* own surface-default.
*/
const generated = 'contentModes' in currentTheme ? currentTheme : undefined;
const tokens = generated && <style>{generated.tokensCss}</style>;
const bg = (
generated
? generated.modes[colorMode]['surface-default']
: themeBackground[colorMode]
) as 'white';
const background = generated
? (generated._tokens.colors as Record<string, string>)[bg]
: corePalette[themeBackground[colorMode]];
const storyRef = useRef<HTMLDivElement>(null);

useLayoutEffect(() => {
const storyEl = storyRef.current?.closest(
Expand All @@ -72,11 +92,8 @@ export const withEmotion = (Story: any, context: GlobalsContext) => {
useLogicalProperties={useLogicalProperties}
theme={currentTheme as unknown as Theme}
>
<Background
alwaysSetVariables
bg={themeBackground[colorMode]}
ref={storyRef}
>
{tokens}
<Background alwaysSetVariables bg={bg} ref={storyRef}>
{Story()}
</Background>
</GamutProvider>
Expand All @@ -89,11 +106,7 @@ export const withEmotion = (Story: any, context: GlobalsContext) => {
useLogicalProperties={useLogicalProperties}
theme={currentTheme as unknown as Theme}
>
<Background
alwaysSetVariables
bg={themeBackground[colorMode]}
ref={storyRef}
>
<Background alwaysSetVariables bg={bg} ref={storyRef}>
{Story()}
</Background>
</GamutProvider>
Expand Down
Loading
Loading