@codecademy/gamut 68.6.1-alpha.edab62.0 → 68.6.1-alpha.f6b2ce.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.
- package/agent-tools/.cursor-plugin/plugin.json +1 -1
- package/agent-tools/DESIGN.Codecademy.md +466 -413
- package/agent-tools/DESIGN.LXStudio.md +350 -282
- package/agent-tools/DESIGN.Percipio.md +357 -279
- package/agent-tools/commands/gamut-review.md +176 -87
- package/agent-tools/guidelines/components/animations.md +74 -0
- package/agent-tools/guidelines/components/buttons.md +74 -23
- package/agent-tools/guidelines/components/card.md +19 -0
- package/agent-tools/guidelines/components/coachmark.md +21 -0
- package/agent-tools/guidelines/components/data-table.md +79 -0
- package/agent-tools/guidelines/components/forms.md +106 -0
- package/agent-tools/guidelines/components/loading-states.md +17 -0
- package/agent-tools/guidelines/components/menu.md +58 -0
- package/agent-tools/guidelines/components/overview.md +97 -17
- package/agent-tools/guidelines/components/radial-progress.md +13 -0
- package/agent-tools/guidelines/components/select.md +23 -0
- package/agent-tools/guidelines/components/tooltips.md +22 -0
- package/agent-tools/guidelines/components/video.md +29 -0
- package/agent-tools/guidelines/foundations/color.md +140 -58
- package/agent-tools/guidelines/foundations/modes.md +41 -17
- package/agent-tools/guidelines/foundations/spacing.md +78 -37
- package/agent-tools/guidelines/foundations/typography.md +69 -37
- package/agent-tools/guidelines/overview-icons.md +19 -0
- package/agent-tools/guidelines/overview-illustrations.md +7 -0
- package/agent-tools/guidelines/overview-patterns.md +7 -0
- package/agent-tools/guidelines/overview.md +71 -22
- package/agent-tools/guidelines/setup.md +59 -18
- package/agent-tools/rules/accessibility.mdc +22 -13
- package/agent-tools/skills/gamut-accessibility/SKILL.md +97 -112
- package/agent-tools/skills/gamut-color-mode/SKILL.md +91 -41
- package/agent-tools/skills/gamut-components/SKILL.md +46 -0
- package/agent-tools/skills/gamut-forms/SKILL.md +101 -0
- package/agent-tools/skills/gamut-style-utilities/SKILL.md +111 -0
- package/agent-tools/skills/gamut-system-props/SKILL.md +81 -29
- package/agent-tools/skills/gamut-testing/SKILL.md +106 -62
- package/agent-tools/skills/gamut-theming/SKILL.md +36 -86
- package/agent-tools/skills/gamut-typography/SKILL.md +36 -80
- package/bin/commands/plugin/install.mjs +96 -56
- package/bin/commands/plugin/list.mjs +11 -43
- package/bin/commands/plugin/remove.mjs +30 -38
- package/bin/commands/plugin/update.mjs +15 -5
- package/bin/gamut.mjs +17 -13
- package/bin/lib/design.mjs +71 -0
- package/bin/lib/io.mjs +14 -0
- package/package.json +6 -6
- package/bin/lib/figma.mjs +0 -49
|
@@ -1,86 +1,168 @@
|
|
|
1
1
|
# Color
|
|
2
2
|
|
|
3
|
-
Use
|
|
3
|
+
Use semantic aliases for UI that should respond to color mode (light/dark) and theme (Core, Admin, Platform, Percipio, LX Studio). The same semantic token names (`text`, `primary`, `background`, …) exist across themes; resolved palette values and hex differ by `GamutProvider` theme and active ColorMode. Never assume Codecademy Core hex when advising another product.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Prefer `css` / `variant` / `states` from `@codecademy/gamut-styles` with semantic names (see Storybook [Best practices](https://gamut.codecademy.com/?path=/docs-meta-best-practices--page)).
|
|
6
|
+
|
|
7
|
+
Related: [`setup.md`](../setup.md) (which theme to import) · [`gamut-theming` skill](../../skills/gamut-theming/SKILL.md) · [`gamut-style-utilities` skill](../../skills/gamut-style-utilities/SKILL.md) · [`gamut-color-mode` skill](../../skills/gamut-color-mode/SKILL.md) · [`modes.md`](modes.md) (`<ColorMode>`, `<Background>`)
|
|
8
|
+
|
|
9
|
+
Percipio, LX Studio, Admin, and Platform override subsets of semantic mappings while keeping the shared alias API — see theme sources below before hardcoding palette names or hex.
|
|
10
|
+
|
|
11
|
+
## Semantic aliases (theme-stable names)
|
|
12
|
+
|
|
13
|
+
These tokens describe roles. Actual colors come from the active theme + ColorMode.
|
|
14
|
+
|
|
15
|
+
### Text
|
|
16
|
+
|
|
17
|
+
| Token | Use for | Notes |
|
|
18
|
+
| ---------------- | --------------------------- | -------------------------- |
|
|
19
|
+
| `text` | Default body and UI text | |
|
|
20
|
+
| `text-accent` | Stronger emphasis text | |
|
|
21
|
+
| `text-secondary` | Supporting / secondary copy | Often opacity on base text |
|
|
22
|
+
| `text-disabled` | Disabled state labels | |
|
|
23
|
+
|
|
24
|
+
### Background
|
|
25
|
+
|
|
26
|
+
| Token | Use for | Notes |
|
|
27
|
+
| --------------------- | --------------------------------- | ------------------------- |
|
|
28
|
+
| `background` | Default page/component background | |
|
|
29
|
+
| `background-primary` | Slightly elevated surfaces | |
|
|
30
|
+
| `background-contrast` | Maximum contrast surface | |
|
|
31
|
+
| `background-selected` | Selected row / item | Often low-opacity overlay |
|
|
32
|
+
| `background-hover` | Hover state overlay | |
|
|
33
|
+
| `background-disabled` | Disabled surface | |
|
|
34
|
+
| `background-success` | Success state container | |
|
|
35
|
+
| `background-warning` | Warning state container | |
|
|
36
|
+
| `background-error` | Error state container | |
|
|
37
|
+
|
|
38
|
+
### Interactive
|
|
39
|
+
|
|
40
|
+
| Token | Use for | Notes |
|
|
41
|
+
| ----------------- | ----------------------------------------- | ---------------------------- |
|
|
42
|
+
| `primary` | Primary CTA, links, focus accents | Pairs with `primary-hover` |
|
|
43
|
+
| `primary-hover` | Hover on primary interactive | |
|
|
44
|
+
| `primary-inverse` | Accent on top of primary-colored surfaces | |
|
|
45
|
+
| `secondary` | Secondary CTA, ghost buttons | Pairs with `secondary-hover` |
|
|
46
|
+
| `secondary-hover` | Hover on secondary interactive | |
|
|
47
|
+
| `danger` | Destructive actions, error emphasis | Pairs with `danger-hover` |
|
|
48
|
+
| `danger-hover` | Hover on danger interactive | |
|
|
49
|
+
|
|
50
|
+
### Border
|
|
51
|
+
|
|
52
|
+
| Token | Use for | Notes |
|
|
53
|
+
| ------------------ | -------------------------- | ----- |
|
|
54
|
+
| `border-primary` | Strong borders, dividers | |
|
|
55
|
+
| `border-secondary` | Medium-weight borders | |
|
|
56
|
+
| `border-tertiary` | Subtle borders, separators | |
|
|
57
|
+
| `border-disabled` | Disabled input borders | |
|
|
58
|
+
|
|
59
|
+
### Feedback
|
|
60
|
+
|
|
61
|
+
| Token | Use for | Notes |
|
|
62
|
+
| ------------------ | -------------------------- | ----- |
|
|
63
|
+
| `feedback-error` | Error messages, validation | |
|
|
64
|
+
| `feedback-success` | Success messages | |
|
|
65
|
+
| `feedback-warning` | Warning messages | |
|
|
66
|
+
|
|
67
|
+
## Where resolved colors are documented
|
|
68
|
+
|
|
69
|
+
Use these instead of memorizing hex:
|
|
70
|
+
|
|
71
|
+
- Storybook [ColorMode](https://gamut.codecademy.com/?path=/docs-foundations-colormode--page) — how aliases map per light/dark for reference layouts.
|
|
72
|
+
- Storybook Foundations → Theme — per-product tables and guidance:
|
|
73
|
+
- [Core Theme](https://gamut.codecademy.com/?path=/docs-foundations-theme-core-theme--docs)
|
|
74
|
+
- [Admin Theme](https://gamut.codecademy.com/?path=/docs-foundations-theme-admin-theme--docs)
|
|
75
|
+
- [Platform Theme](https://gamut.codecademy.com/?path=/docs-foundations-theme-platform-theme--docs)
|
|
76
|
+
- [Percipio Theme](https://gamut.codecademy.com/?path=/docs-foundations-theme-percipio-theme--docs)
|
|
77
|
+
- [LX Studio Theme](https://gamut.codecademy.com/?path=/docs-foundations-theme-lx-studio-theme--docs)
|
|
78
|
+
- [Creating Themes](https://gamut.codecademy.com/?path=/docs-foundations-theme-creating-themes--docs) — authoring new themes in `gamut-styles`
|
|
79
|
+
- Product design YAML (root `DESIGN.md` from agent-tools): [`DESIGN.Codecademy.md`](../../DESIGN.Codecademy.md), [`DESIGN.Percipio.md`](../../DESIGN.Percipio.md), [`DESIGN.LXStudio.md`](../../DESIGN.LXStudio.md) — semantic ↔ palette for that product.
|
|
80
|
+
- Source: theme definitions in [`packages/gamut-styles/src/themes`](https://github.com/Codecademy/gamut/tree/main/packages/gamut-styles/src/themes), palette scales in [`packages/gamut-styles/src/variables`](https://github.com/Codecademy/gamut/tree/main/packages/gamut-styles/src/variables).
|
|
81
|
+
|
|
82
|
+
## Codecademy Core — illustrative light/dark hex only
|
|
83
|
+
|
|
84
|
+
The tables below are not valid for Percipio, LX Studio, or other themes. They are a quick mental model for Codecademy Core defaults only.
|
|
6
85
|
|
|
7
86
|
### Text
|
|
8
87
|
|
|
9
|
-
| Token
|
|
10
|
-
|
|
11
|
-
| `text`
|
|
12
|
-
| `text-accent`
|
|
13
|
-
| `text-secondary` | navy-800 75% | white 65% |
|
|
14
|
-
| `text-disabled`
|
|
88
|
+
| Token | Light | Dark |
|
|
89
|
+
| ---------------- | ------------ | --------- |
|
|
90
|
+
| `text` | `#10162F` | `#ffffff` |
|
|
91
|
+
| `text-accent` | `#0A0D1C` | `#FFF0E5` |
|
|
92
|
+
| `text-secondary` | navy-800 75% | white 65% |
|
|
93
|
+
| `text-disabled` | navy-800 63% | white 50% |
|
|
15
94
|
|
|
16
95
|
### Background
|
|
17
96
|
|
|
18
|
-
| Token
|
|
19
|
-
|
|
20
|
-
| `background`
|
|
21
|
-
| `background-primary`
|
|
22
|
-
| `background-contrast` | white
|
|
23
|
-
| `background-selected` | navy-800 4%
|
|
24
|
-
| `background-hover`
|
|
25
|
-
| `background-disabled` | navy-800 12% | white 9%
|
|
26
|
-
| `background-success`
|
|
27
|
-
| `background-warning`
|
|
28
|
-
| `background-error`
|
|
97
|
+
| Token | Light | Dark |
|
|
98
|
+
| --------------------- | ------------ | --------- |
|
|
99
|
+
| `background` | `#ffffff` | `#10162F` |
|
|
100
|
+
| `background-primary` | `#FFF0E5` | `#0A0D1C` |
|
|
101
|
+
| `background-contrast` | white | black |
|
|
102
|
+
| `background-selected` | navy-800 4% | white 4% |
|
|
103
|
+
| `background-hover` | navy-800 12% | white 9% |
|
|
104
|
+
| `background-disabled` | navy-800 12% | white 9% |
|
|
105
|
+
| `background-success` | `#F5FFE3` | `#151C07` |
|
|
106
|
+
| `background-warning` | `#FFFAE5` | `#211B00` |
|
|
107
|
+
| `background-error` | `#FBF1F0` | `#280503` |
|
|
29
108
|
|
|
30
109
|
### Interactive
|
|
31
110
|
|
|
32
|
-
| Token
|
|
33
|
-
|
|
34
|
-
| `primary`
|
|
35
|
-
| `primary-hover`
|
|
36
|
-
| `primary-inverse` | `#FFD300`
|
|
37
|
-
| `secondary`
|
|
38
|
-
| `secondary-hover` | navy-800 86% | white 80% |
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `danger` | `#E91C11` | `#E85D7F` | Destructive actions, error states |
|
|
42
|
-
| `danger-hover` | `#BE1809` | `#DC5879` | Hover on danger interactive |
|
|
111
|
+
| Token | Light | Dark |
|
|
112
|
+
| ----------------- | ------------ | --------- |
|
|
113
|
+
| `primary` | `#3A10E5` | `#FFD300` |
|
|
114
|
+
| `primary-hover` | `#5533FF` | `#CCA900` |
|
|
115
|
+
| `primary-inverse` | `#FFD300` | `#3A10E5` |
|
|
116
|
+
| `secondary` | `#10162F` | `#ffffff` |
|
|
117
|
+
| `secondary-hover` | navy-800 86% | white 80% |
|
|
118
|
+
| `danger` | `#E91C11` | `#E85D7F` |
|
|
119
|
+
| `danger-hover` | `#BE1809` | `#DC5879` |
|
|
43
120
|
|
|
44
121
|
### Border
|
|
45
122
|
|
|
46
|
-
| Token
|
|
47
|
-
|
|
48
|
-
| `border-primary`
|
|
49
|
-
| `border-secondary` | navy-800 75% | white 65% |
|
|
50
|
-
| `border-tertiary`
|
|
51
|
-
| `border-disabled`
|
|
123
|
+
| Token | Light | Dark |
|
|
124
|
+
| ------------------ | ------------ | --------- |
|
|
125
|
+
| `border-primary` | `#10162F` | `#ffffff` |
|
|
126
|
+
| `border-secondary` | navy-800 75% | white 65% |
|
|
127
|
+
| `border-tertiary` | navy-800 28% | white 20% |
|
|
128
|
+
| `border-disabled` | navy-800 63% | white 50% |
|
|
52
129
|
|
|
53
130
|
### Feedback
|
|
54
131
|
|
|
55
|
-
| Token
|
|
56
|
-
|
|
57
|
-
| `feedback-error`
|
|
58
|
-
| `feedback-success` | `#008A27` | `#AEE938` |
|
|
59
|
-
| `feedback-warning` | `#FFD300` | `#FFFAE5` |
|
|
132
|
+
| Token | Light | Dark |
|
|
133
|
+
| ------------------ | --------- | --------- |
|
|
134
|
+
| `feedback-error` | `#BE1809` | `#E85D7F` |
|
|
135
|
+
| `feedback-success` | `#008A27` | `#AEE938` |
|
|
136
|
+
| `feedback-warning` | `#FFD300` | `#FFFAE5` |
|
|
137
|
+
|
|
138
|
+
## Raw palette (Core-centric reference)
|
|
60
139
|
|
|
61
|
-
|
|
140
|
+
Raw tokens name fixed swatches (surfaces, illustration, `<Background bg="…">` on Codecademy). Palette keys and hex vary by theme — Percipio and others add or remap scales (`percipioPalette`, etc.). Confirm allowed keys in the active theme or `DESIGN.md` before using a raw token in a non-Core app.
|
|
62
141
|
|
|
63
|
-
|
|
142
|
+
For Codecademy Core defaults:
|
|
64
143
|
|
|
65
|
-
| Name
|
|
66
|
-
|
|
67
|
-
| `navy`
|
|
68
|
-
| `hyper`
|
|
69
|
-
| `yellow` | 0, 400, 500, 900
|
|
70
|
-
| `red`
|
|
71
|
-
| `green`
|
|
72
|
-
| `blue`
|
|
73
|
-
| `beige`
|
|
74
|
-
| `pink`
|
|
75
|
-
| `orange` | 100, 500
|
|
144
|
+
| Name | Weights | Key values (illustrative) |
|
|
145
|
+
| -------- | -------------------------- | -------------------------------- |
|
|
146
|
+
| `navy` | 100–900 | 800 = `#10162F`, 900 = `#0A0D1C` |
|
|
147
|
+
| `hyper` | 400, 500 | 500 = `#3A10E5`, 400 = `#5533FF` |
|
|
148
|
+
| `yellow` | 0, 400, 500, 900 | 500 = `#FFD300` |
|
|
149
|
+
| `red` | 0, 300, 400, 500, 600, 900 | 500 = `#E91C11` |
|
|
150
|
+
| `green` | 0, 100, 400, 700, 900 | 700 = `#008A27` |
|
|
151
|
+
| `blue` | 0, 100, 300, 400, 500, 800 | 500 = `#1557FF` |
|
|
152
|
+
| `beige` | — | `#FFF0E5` |
|
|
153
|
+
| `pink` | 0, 400 | 400 = `#F966FF` |
|
|
154
|
+
| `orange` | 100, 500 | 500 = `#FF8C00` |
|
|
76
155
|
|
|
77
|
-
Named shorthand aliases: `beige`, `blue`, `green`, `hyper`, `navy`, `orange`, `pink`, `red`, `yellow`, `black`, `white`
|
|
156
|
+
Named shorthand aliases commonly used on Core surfaces: `beige`, `blue`, `green`, `hyper`, `navy`, `orange`, `pink`, `red`, `yellow`, `black`, `white`
|
|
78
157
|
|
|
79
158
|
## Decision guide
|
|
80
159
|
|
|
81
160
|
```
|
|
161
|
+
Which product theme is GamutProvider using?
|
|
162
|
+
└─ Unknown → check setup.md / DESIGN.md / Storybook theme page before assuming hex or palette name
|
|
163
|
+
|
|
82
164
|
Coloring UI text or backgrounds?
|
|
83
|
-
└─
|
|
84
|
-
└─ Must
|
|
85
|
-
└─
|
|
165
|
+
└─ Must adapt to light/dark OR theme? → semantic alias (text, background, primary, …)
|
|
166
|
+
└─ Must stay fixed regardless of mode? → raw palette token (confirm key exists in that theme)
|
|
167
|
+
└─ Section background with content inside? → <Background bg="…"> (see modes.md)
|
|
86
168
|
```
|
|
@@ -1,45 +1,69 @@
|
|
|
1
1
|
# Color Modes
|
|
2
2
|
|
|
3
|
-
Gamut uses
|
|
3
|
+
Gamut uses semantic color aliases so components adapt to light/dark mode without configuration. See [color.md](color.md) for the full alias reference and decision guide.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Product tokens: Semantic mappings vary by theme. Confirm aliases and palette keys against root `DESIGN.md` and the active theme Storybook page — do not assume Codecademy Core values in Percipio, LX Studio, or other products.
|
|
6
|
+
|
|
7
|
+
Deep reference: [`skills/gamut-color-mode/SKILL.md`](../../skills/gamut-color-mode/SKILL.md) · Storybook [ColorMode](https://gamut.codecademy.com/?path=/docs-foundations-colormode--page)
|
|
8
|
+
|
|
9
|
+
## When to use the color mode system
|
|
10
|
+
|
|
11
|
+
For any dark or light region — sidebars, footers, hero bands, callouts, panels, whole-app dark mode — use `ColorMode` or `Background` from `@codecademy/gamut-styles`. Do not handle these with custom CSS, hardcoded `rgba`, or manual color swaps.
|
|
12
|
+
|
|
13
|
+
| Component | Use when |
|
|
14
|
+
| ------------ | ----------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `ColorMode` | You know the mode (`light`, `dark`, or `system` for OS preference). |
|
|
16
|
+
| `Background` | Background color is a palette token and Gamut should pick the best contrast mode automatically. |
|
|
6
17
|
|
|
7
|
-
|
|
18
|
+
## Rules
|
|
19
|
+
|
|
20
|
+
1. Never override Gamut colors with custom CSS when a `ColorMode` or `Background` wrapper achieves the same result via tokens.
|
|
21
|
+
2. Prefer `ColorMode` over `Background` when the intended mode is known (e.g. sidebar always dark). Use `Background` when the surface color is fixed and mode should adapt.
|
|
22
|
+
3. `ColorMode` has no `as` prop — nest semantic elements inside (`<nav>`, `<aside>`, `<footer>`).
|
|
23
|
+
4. System props work on `ColorMode` — `p`, `m`, `width`, `position`, etc. without extra wrappers.
|
|
24
|
+
5. `mode="system"` follows OS `prefers-color-scheme`. For in-app theme toggles, pass `mode="light"` or `mode="dark"` from your own state.
|
|
25
|
+
|
|
26
|
+
## `<ColorMode>`
|
|
8
27
|
|
|
9
28
|
```tsx
|
|
10
29
|
import { ColorMode } from '@codecademy/gamut-styles';
|
|
11
30
|
|
|
12
|
-
<ColorMode mode="light">{children}</ColorMode>
|
|
13
|
-
<ColorMode mode="dark">{children}</ColorMode>
|
|
14
|
-
<ColorMode mode="system">{children}</ColorMode>
|
|
31
|
+
<ColorMode mode="light">{children}</ColorMode>
|
|
32
|
+
<ColorMode mode="dark">{children}</ColorMode>
|
|
33
|
+
<ColorMode mode="system">{children}</ColorMode>
|
|
15
34
|
```
|
|
16
35
|
|
|
17
|
-
|
|
36
|
+
Props: `mode="light" | "dark" | "system"`
|
|
18
37
|
|
|
19
38
|
## `<Background>`
|
|
20
39
|
|
|
21
|
-
Use `<Background>` — not a raw `bg`
|
|
40
|
+
Use `<Background>` — not a raw `bg` on layout — for colored sections with text or interactive children. Pass a palette token to `bg` (e.g. `hyper`, `navy`), not a semantic alias.
|
|
22
41
|
|
|
23
42
|
```tsx
|
|
24
43
|
import { Background } from '@codecademy/gamut-styles';
|
|
25
44
|
|
|
26
|
-
<Background bg="hyper">{children}</Background
|
|
45
|
+
<Background bg="hyper">{children}</Background>;
|
|
27
46
|
```
|
|
28
47
|
|
|
29
48
|
Nesting is supported — each `<Background>` creates its own accessible color context.
|
|
30
49
|
|
|
31
50
|
## Hooks
|
|
32
51
|
|
|
33
|
-
| Hook
|
|
34
|
-
|
|
35
|
-
| `useCurrentMode()`
|
|
36
|
-
| `
|
|
37
|
-
| `usePrefersDarkMode()` | `boolean`
|
|
52
|
+
| Hook | Returns | Use |
|
|
53
|
+
| ---------------------- | ------------------------------------- | ---------------------------------------------------------- |
|
|
54
|
+
| `useCurrentMode()` | `"light" \| "dark"` | Active mode key only |
|
|
55
|
+
| `useColorModes()` | mode key, colors, all modes, resolver | Full mode data + `getColorValue` |
|
|
56
|
+
| `usePrefersDarkMode()` | `boolean` | OS dark preference (prefer `mode="system"` on `ColorMode`) |
|
|
38
57
|
|
|
39
58
|
Import from `@codecademy/gamut-styles`.
|
|
40
59
|
|
|
60
|
+
## Example (Core theme)
|
|
61
|
+
|
|
62
|
+
Core light/dark semantic mappings are documented in Storybook [ColorMode](https://gamut.codecademy.com/?path=/docs-foundations-colormode--page). Other themes remap the same alias names to different palette values — verify in `DESIGN.md` and the product theme story before hardcoding palette fallbacks.
|
|
63
|
+
Storybook: [Foundations / ColorMode](https://gamut.codecademy.com/?path=/docs-foundations-colormode--page) · [Meta / Best practices](https://gamut.codecademy.com/?path=/docs-meta-best-practices--page)
|
|
64
|
+
|
|
41
65
|
## Common mistakes
|
|
42
66
|
|
|
43
|
-
- Do not use raw
|
|
44
|
-
- Do not use a raw `bg` prop on colored sections
|
|
45
|
-
- Do not
|
|
67
|
+
- Do not use raw palette tokens (`navy-400`, `white`) for text/backgrounds that must adapt across modes — use semantic aliases.
|
|
68
|
+
- Do not use a raw `bg` prop on colored sections with content — use `<Background>`.
|
|
69
|
+
- Do not wire `usePrefersDarkMode()` into `ColorMode` when `mode="system"` suffices.
|
|
@@ -1,62 +1,103 @@
|
|
|
1
1
|
# Spacing, Border Radius & Layout
|
|
2
2
|
|
|
3
|
+
Token values match [`packages/gamut-styles/src/variables`](https://github.com/Codecademy/gamut/tree/main/packages/gamut-styles/src/variables) (`spacing.ts`, `borderRadii.ts`, `responsive.ts`). Breakpoints and max-content widths align with Storybook [Foundations / Layout](https://gamut.codecademy.com/?path=/docs-foundations-layout--docs).
|
|
4
|
+
|
|
5
|
+
In code — use system props for spacing: Gamut layout primitives (`Box`, `FlexBox`, `GridBox`, …) expose margin, padding, and gap props backed by `system.space` from `@codecademy/gamut-styles`. Pass spacing scale numbers (`4`, `8`, `16`, …), not raw pixel strings. For custom `styled` components, compose `system.space` (see [`gamut-system-props` skill](../../skills/gamut-system-props/SKILL.md)). [Meta / Best practices](https://gamut.codecademy.com/?path=/docs-meta-best-practices--page) shows responsive `Box` examples.
|
|
6
|
+
|
|
7
|
+
Responsive behavior: All those props accept mobile-first object (`{ _: 8, md: 24 }`) or array syntax per [Responsive properties](https://gamut.codecademy.com/?path=/docs-foundations-system-responsive-properties--page). Container queries use keys `c_base`, `c_xs`, … `c_xl`; the parent must set a container (e.g. `containerType="inline-size"` on `FlexBox`). Prefer a media-query fallback when mixing `c_*` with viewport breakpoints.
|
|
8
|
+
|
|
9
|
+
Two different “grids”:
|
|
10
|
+
|
|
11
|
+
- Design / page grid (this doc’s “Grid” section, 12 columns, margins/gutters) — product layout guidelines; implement with [`LayoutGrid`](https://gamut.codecademy.com/?path=/docs-layouts-layoutgrid-layoutgrid--docs) and responsive `columnGap` / `rowGap` where appropriate.
|
|
12
|
+
- CSS Grid system props — `system.grid` on styled components or `GridBox` for local regions; not the same as full-page `LayoutGrid`. See [System props / Grid](https://gamut.codecademy.com/?path=/docs-foundations-system-props-grid--page). `LayoutGrid` is for flexible full-page sections; use `FlexBox` / `GridBox` / `Box` for smaller areas ([LayoutGrid usage](https://gamut.codecademy.com/?path=/docs-layouts-layoutgrid-layoutgrid--docs)).
|
|
13
|
+
|
|
14
|
+
Designer vs code names: Figma / Layout docs often label artboards XL, LG, MD, SM, XS, Base. In code, viewport breakpoints are `xl`, `lg`, `md`, `sm`, `xs` (min-widths below); `_` is the base (no min-width query). The “Max content width” column maps to those design sizes, not the `xs` token name alone.
|
|
15
|
+
|
|
3
16
|
## Spacing scale
|
|
4
17
|
|
|
5
18
|
All spacing is multiples of 4px on an 8px grid.
|
|
6
19
|
|
|
7
20
|
| Token | Value |
|
|
8
|
-
|
|
9
|
-
| `0`
|
|
10
|
-
| `4`
|
|
11
|
-
| `8`
|
|
12
|
-
| `12`
|
|
13
|
-
| `16`
|
|
14
|
-
| `24`
|
|
15
|
-
| `32`
|
|
16
|
-
| `40`
|
|
17
|
-
| `48`
|
|
18
|
-
| `64`
|
|
19
|
-
| `96`
|
|
21
|
+
| ----- | ----- |
|
|
22
|
+
| `0` | 0 |
|
|
23
|
+
| `4` | 4px |
|
|
24
|
+
| `8` | 8px |
|
|
25
|
+
| `12` | 12px |
|
|
26
|
+
| `16` | 16px |
|
|
27
|
+
| `24` | 24px |
|
|
28
|
+
| `32` | 32px |
|
|
29
|
+
| `40` | 40px |
|
|
30
|
+
| `48` | 48px |
|
|
31
|
+
| `64` | 64px |
|
|
32
|
+
| `96` | 96px |
|
|
20
33
|
|
|
21
34
|
Use multiples of 8px for block-element spacing. Use 4px only for inline or typographic relationships.
|
|
22
35
|
|
|
23
36
|
## Border radius
|
|
24
37
|
|
|
25
|
-
| Token
|
|
26
|
-
|
|
27
|
-
| `none` | 0px
|
|
28
|
-
| `sm`
|
|
29
|
-
| `md`
|
|
30
|
-
| `lg`
|
|
31
|
-
| `xl`
|
|
32
|
-
| `full` | 999px | Pills, avatars, circular elements
|
|
38
|
+
| Token | Value | Use |
|
|
39
|
+
| ------ | ----- | ---------------------------------- |
|
|
40
|
+
| `none` | 0px | Square / non-interactive elements |
|
|
41
|
+
| `sm` | 2px | Subtle rounding, tags |
|
|
42
|
+
| `md` | 4px | Buttons, inputs, interactive cards |
|
|
43
|
+
| `lg` | 8px | Cards, panels |
|
|
44
|
+
| `xl` | 16px | Large cards, modals |
|
|
45
|
+
| `full` | 999px | Pills, avatars, circular elements |
|
|
33
46
|
|
|
34
47
|
## Breakpoints
|
|
35
48
|
|
|
36
49
|
Mobile-first. Styles apply from the named breakpoint and up.
|
|
37
50
|
|
|
38
|
-
| Token
|
|
39
|
-
|
|
40
|
-
| _(base)_ | 0
|
|
41
|
-
| `xs`
|
|
42
|
-
| `sm`
|
|
43
|
-
| `md`
|
|
44
|
-
| `lg`
|
|
45
|
-
| `xl`
|
|
51
|
+
| Token | Min-width | Max content width |
|
|
52
|
+
| -------- | --------- | ----------------- |
|
|
53
|
+
| _(base)_ | 0 | 288px |
|
|
54
|
+
| `xs` | 480px | 448px |
|
|
55
|
+
| `sm` | 768px | 704px |
|
|
56
|
+
| `md` | 1024px | 896px |
|
|
57
|
+
| `lg` | 1200px | 1072px |
|
|
58
|
+
| `xl` | 1440px | 1248px |
|
|
59
|
+
|
|
60
|
+
The grid table below collapses xl+lg, md, sm+xs, and base to four implementation tiers; max-content widths still follow the six design sizes in Layout.
|
|
61
|
+
|
|
62
|
+
## Container query breakpoints
|
|
63
|
+
|
|
64
|
+
Container keys (`c_*`) use the same min-width numbers as viewport breakpoints, but they apply to the width of a CSS containment context (usually a parent), not the browser viewport. Use them when a component must adapt inside sidebars, split layouts, or embeds. Full detail: [Responsive properties — Container Queries](https://gamut.codecademy.com/?path=/docs-foundations-system-responsive-properties--page).
|
|
65
|
+
|
|
66
|
+
| Key | Min container width | Typical use |
|
|
67
|
+
| -------- | ------------------- | ----------------------------------------------------------------------- |
|
|
68
|
+
| `c_base` | 1px | Always matches once a container exists; base style inside the container |
|
|
69
|
+
| `c_xs` | 480px | Matches viewport `xs` threshold, but on container width |
|
|
70
|
+
| `c_sm` | 768px | |
|
|
71
|
+
| `c_md` | 1024px | |
|
|
72
|
+
| `c_lg` | 1200px | |
|
|
73
|
+
| `c_xl` | 1440px | |
|
|
74
|
+
|
|
75
|
+
Requirements
|
|
76
|
+
|
|
77
|
+
- A descendant of an element that establishes a container — e.g. parent `<FlexBox containerType="inline-size">` (or other `container-type`). Without that, `c_*` rules never match.
|
|
78
|
+
- Prefer a viewport fallback alongside `c_*` (e.g. `display={{ _: 'block', sm: 'flex', c_md: 'grid' }}`) for browsers or trees without container support.
|
|
79
|
+
|
|
80
|
+
Object vs array
|
|
81
|
+
|
|
82
|
+
- Object: `p={{ _: 8, c_md: 24 }}` — readable for a few container-only overrides.
|
|
83
|
+
- Array: after the six viewport slots (`_` through `xl`), indices 6–11 are `c_base`, `c_xs`, `c_sm`, `c_md`, `c_lg`, `c_xl` respectively. Use when you need the full ordered chain.
|
|
84
|
+
|
|
85
|
+
When to use which
|
|
46
86
|
|
|
47
|
-
|
|
87
|
+
- Viewport keys (`_`, `xs`, … `xl`) — page-level layout, full-bleed sections, global nav.
|
|
88
|
+
- Container keys (`c_base`, … `c_xl`) — reusable widgets whose width is driven by layout, not the device alone.
|
|
48
89
|
|
|
49
|
-
##
|
|
90
|
+
## Page layout grid (12 columns)
|
|
50
91
|
|
|
51
|
-
12-column grid at all breakpoints.
|
|
92
|
+
12-column grid at all breakpoints. Tier columns group breakpoints with identical margin/gutter/row-gap numbers from [Layout](https://gamut.codecademy.com/?path=/docs-foundations-layout--docs).
|
|
52
93
|
|
|
53
|
-
| Property
|
|
54
|
-
|
|
55
|
-
| Horizontal margins | 64px
|
|
56
|
-
| Column gutters
|
|
57
|
-
| Row gaps
|
|
94
|
+
| Property | xl/lg | md | sm/xs | base |
|
|
95
|
+
| ------------------ | ----- | ---- | ----- | ---- |
|
|
96
|
+
| Horizontal margins | 64px | 48px | 32px | 16px |
|
|
97
|
+
| Column gutters | 32px | 24px | 16px | 8px |
|
|
98
|
+
| Row gaps | 32px | 24px | 16px | 8px |
|
|
58
99
|
|
|
59
|
-
Minimum touch target on mobile:
|
|
100
|
+
Minimum touch target on mobile: 44×44px — see `gamut-accessibility` skill for hit-target guidance.
|
|
60
101
|
|
|
61
102
|
## Responsive rules
|
|
62
103
|
|
|
@@ -1,50 +1,82 @@
|
|
|
1
1
|
# Typography
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use theme typography tokens (`fontFamily`, `fontSize`, `fontWeight`, `lineHeight`) — never hardcoded font-family strings or magic px for product UI. Prefer `<Text>` from `@codecademy/gamut`, or `system.typography` / `css()` from `@codecademy/gamut-styles` ([`gamut-system-props` skill](../../skills/gamut-system-props/SKILL.md)).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|---|---|---|---|
|
|
7
|
-
| `base` | Apercu Pro | Hanken Grotesk | All UI text, headlines, body copy |
|
|
8
|
-
| `accent` | Suisse Intl Mono | Hanken Grotesk | Code, captions, labels, technical context |
|
|
9
|
-
| `monospace` | Monaco / Menlo / Consolas | Monaco / Menlo / Consolas | Code editor contexts |
|
|
5
|
+
Source of truth for scales and stacks: [`packages/gamut-styles/src/variables/typography.ts`](https://github.com/Codecademy/gamut/blob/main/packages/gamut-styles/src/variables/typography.ts) and theme builders under [`packages/gamut-styles/src/themes`](https://github.com/Codecademy/gamut/tree/main/packages/gamut-styles/src/themes).
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
Storybook: [Typography / Text](https://gamut.codecademy.com/?path=/docs-typography-text--docs) · [Meta / Best practices](https://gamut.codecademy.com/?path=/docs-meta-best-practices--page) (system props) · Foundations / Theme: [Core](https://gamut.codecademy.com/?path=/docs-foundations-theme-core-theme--docs), [Percipio](https://gamut.codecademy.com/?path=/docs-foundations-theme-percipio-theme--docs), [LX Studio](https://gamut.codecademy.com/?path=/docs-foundations-theme-lx-studio-theme--docs)
|
|
8
|
+
|
|
9
|
+
## Themes × font families
|
|
10
|
+
|
|
11
|
+
Semantic keys (`base`, `accent`, `monospace`, `system`) are stable; resolved stacks depend on `GamutProvider` theme ([`setup.md`](../setup.md)).
|
|
12
|
+
|
|
13
|
+
| Theme | `fontFamily.base` | `fontFamily.accent` | `fontFamily.monospace` | `fontFamily.system` |
|
|
14
|
+
| --------------------- | ------------------------------------ | ------------------------------------- | -------------------------------------- | ------------------------------ |
|
|
15
|
+
| Core, Admin, Platform | Apercu stack (`fontBase`) | Suisse + Apercu stack (`fontAccent`) | Monaco / Menlo stack (`fontMonospace`) | System UI stack (`fontSystem`) |
|
|
16
|
+
| Percipio | Skillsoft Text (`fontPercipioBase`) | Skillsoft Sans (`fontPercipioAccent`) | Roboto Mono | Roboto (`system`) |
|
|
17
|
+
| LX Studio | Same as Percipio (`base` / `accent`) | Same | Same stack as Core (`fontMonospace`) | Same as Core (`fontSystem`) |
|
|
18
|
+
|
|
19
|
+
Admin and Platform extend Core for colors / modes only — typography matches Core.
|
|
20
|
+
|
|
21
|
+
Licensing: Apercu is licensed for Codecademy surfaces only; Skillsoft products use Percipio/LX stacks above.
|
|
12
22
|
|
|
13
23
|
## Font size scale
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| Token | Value | Use |
|
|
30
|
-
|---|---|---|
|
|
31
|
-
| `base` | 400 | Body text, UI labels |
|
|
32
|
-
| `title` | 700 | Headlines, CTAs, buttons |
|
|
25
|
+
Values are `rem`-backed keys on `theme.fontSize` (aliases shown as px for readability).
|
|
26
|
+
|
|
27
|
+
| Token | Size | Common use |
|
|
28
|
+
| ----- | ---- | ---------------------------- |
|
|
29
|
+
| `64` | 64px | Hero / display |
|
|
30
|
+
| `44` | 44px | Page titles |
|
|
31
|
+
| `34` | 34px | Section titles |
|
|
32
|
+
| `26` | 26px | Sub-section titles |
|
|
33
|
+
| `22` | 22px | Card titles, large UI labels |
|
|
34
|
+
| `20` | 20px | Secondary titles |
|
|
35
|
+
| `18` | 18px | Large body, intro text |
|
|
36
|
+
| `16` | 16px | Default body text |
|
|
37
|
+
| `14` | 14px | Small body, captions, labels |
|
|
33
38
|
|
|
34
39
|
## Line height
|
|
35
40
|
|
|
36
|
-
| Token
|
|
37
|
-
|
|
38
|
-
| `base`
|
|
39
|
-
| `spacedTitle` | 1.3
|
|
40
|
-
| `title`
|
|
41
|
+
| Token | Value | Use |
|
|
42
|
+
| ------------- | ----- | ---------------------------- |
|
|
43
|
+
| `base` | 1.5 | Body text |
|
|
44
|
+
| `spacedTitle` | 1.3 | Sub-headlines, medium titles |
|
|
45
|
+
| `title` | 1.2 | Large headlines |
|
|
46
|
+
|
|
47
|
+
## Font weight (semantic)
|
|
48
|
+
|
|
49
|
+
Use semantic keys on components — do not assume a numeric bold everywhere.
|
|
50
|
+
|
|
51
|
+
| Token | Core / Admin / Platform | Percipio / LX Studio |
|
|
52
|
+
| ------- | ----------------------- | ----------------------------- |
|
|
53
|
+
| `base` | 400 | 400 |
|
|
54
|
+
| `title` | 700 | 500 (`fontWeightMediumTitle`) |
|
|
55
|
+
|
|
56
|
+
Headlines, CTAs, and buttons should use `fontWeight="title"` so Percipio/LX get 500, Core gets 700. Literal `700` breaks Skillsoft branding on those themes.
|
|
57
|
+
|
|
58
|
+
Numeric `400` and `700` keys also exist on the theme for rare explicit needs.
|
|
59
|
+
|
|
60
|
+
## Codecademy (Core / Admin / Platform) — voice & layout
|
|
61
|
+
|
|
62
|
+
These UX rules target Apercu + Suisse products; do not blindly apply to Percipio/LX without brand guidance.
|
|
63
|
+
|
|
64
|
+
- `fontFamily="base"` (Apercu): default UI and marketing type. Emphasis inside body copy: Italic, not Bold for intra-paragraph stress.
|
|
65
|
+
- `fontFamily="accent"` (Suisse stack): technical accent — code snippets, captions, labels with engineering flavor, figures. Use sparingly; glyph box reads larger — step down ~10–15% vs equivalent `base` size; give comfortable line-height.
|
|
66
|
+
- Alignment: left-align by default; center only short marketing headlines; avoid right-align except tabs / numerics.
|
|
67
|
+
- Letter-spacing: do not tweak tracking unless design specifies.
|
|
68
|
+
- Line length: ~45–85 characters per line (~66 ideal for single-column body); constrain container width, not arbitrary CSS letter-spacing.
|
|
69
|
+
|
|
70
|
+
## Line length (all products)
|
|
41
71
|
|
|
42
|
-
|
|
72
|
+
| Context | Target |
|
|
73
|
+
| ------------------ | ------------------- |
|
|
74
|
+
| Single-column body | ~66 chars (max ~85) |
|
|
75
|
+
| Multi-column | ≤50 chars per line |
|
|
76
|
+
| Minimum | ~45 chars |
|
|
43
77
|
|
|
44
|
-
##
|
|
78
|
+
## Related skills
|
|
45
79
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
- Left-align text by default. Center-align only for short marketing headlines. Never right-align.
|
|
50
|
-
- Do not adjust letter-spacing.
|
|
80
|
+
- [`gamut-typography`](../../skills/gamut-typography/SKILL.md) — deeper editorial patterns for agents.
|
|
81
|
+
- [`gamut-style-utilities`](../../skills/gamut-style-utilities/SKILL.md) — `css()` / `variant` / `states` and tokenized typography in styled components.
|
|
82
|
+
- [`gamut-theming`](../../skills/gamut-theming/SKILL.md) — which theme / `GamutProvider` / `theme.d.ts`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Icons
|
|
2
|
+
|
|
3
|
+
Icons must come from `@codecademy/gamut-icons`. Do not import or generate icons from other sources. If a needed icon is unavailable, pick a verified alternative from the library or flag for confirmation — do not substitute non-system assets.
|
|
4
|
+
|
|
5
|
+
## Identifying the correct icon
|
|
6
|
+
|
|
7
|
+
Do not rely on Figma layer names (`data-name`). Layer names are often stale after icon swaps.
|
|
8
|
+
|
|
9
|
+
Determine the correct icon by:
|
|
10
|
+
|
|
11
|
+
1. Reading the design image — visually identify the shape (three vertical dots → kebab menu, 3×3 grid → app switcher, etc.).
|
|
12
|
+
2. Using contextual clues — tooltip text, element purpose, surrounding UI patterns.
|
|
13
|
+
3. Cross-referencing exports — search `@codecademy/gamut-icons` for icons matching visual and semantic intent.
|
|
14
|
+
4. Treating layer names as hints only — if a layer name conflicts with visual/contextual evidence, trust the evidence.
|
|
15
|
+
5. When uncertain, flag for confirmation rather than guessing.
|
|
16
|
+
|
|
17
|
+
Before using any icon, confirm it exists in `@codecademy/gamut-icons` (`packages/gamut-icons/src` or package exports).
|
|
18
|
+
|
|
19
|
+
Storybook: [Foundations / Icons](https://gamut.codecademy.com/?path=/docs-foundations-icons--page)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Illustrations
|
|
2
|
+
|
|
3
|
+
Illustrations must come from `@codecademy/gamut-illustrations`. Do not generate or import illustrations from other sources.
|
|
4
|
+
|
|
5
|
+
If the correct illustration is unavailable, flag for confirmation rather than substituting a non-system asset.
|
|
6
|
+
|
|
7
|
+
Storybook: [Illustrations](https://gamut.codecademy.com/?path=/docs-illustrations--page) · `packages/gamut-illustrations/src` exports.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Patterns
|
|
2
|
+
|
|
3
|
+
Patterns must come from `@codecademy/gamut-patterns`. Match Figma component names to pattern exports when possible.
|
|
4
|
+
|
|
5
|
+
If the correct pattern is unavailable, flag for confirmation rather than substituting a non-system asset.
|
|
6
|
+
|
|
7
|
+
Storybook: browse pattern stories under the Gamut styleguide, or inspect `packages/gamut-patterns/src` exports.
|