@codecademy/gamut 68.6.1-alpha.f6b2ce.0 → 68.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/Modals/elements.d.ts +186 -1
  2. package/dist/Modals/elements.js +3 -3
  3. package/dist/{InternalFloatingCard/InternalFloatingCard.d.ts → PatternBackdrop/PatternBackdrop.d.ts} +8 -24
  4. package/dist/PatternBackdrop/PatternBackdrop.js +42 -0
  5. package/dist/Toast/Toast.js +4 -4
  6. package/package.json +8 -11
  7. package/agent-tools/.claude-plugin/marketplace.json +0 -16
  8. package/agent-tools/.claude-plugin/plugin.json +0 -7
  9. package/agent-tools/.cursor-plugin/plugin.json +0 -7
  10. package/agent-tools/DESIGN.Codecademy.md +0 -696
  11. package/agent-tools/DESIGN.LXStudio.md +0 -512
  12. package/agent-tools/DESIGN.Percipio.md +0 -513
  13. package/agent-tools/DESIGN.md +0 -1
  14. package/agent-tools/agents/.gitkeep +0 -0
  15. package/agent-tools/commands/gamut-review.md +0 -259
  16. package/agent-tools/guidelines/components/animations.md +0 -74
  17. package/agent-tools/guidelines/components/buttons.md +0 -95
  18. package/agent-tools/guidelines/components/card.md +0 -19
  19. package/agent-tools/guidelines/components/coachmark.md +0 -21
  20. package/agent-tools/guidelines/components/data-table.md +0 -79
  21. package/agent-tools/guidelines/components/forms.md +0 -106
  22. package/agent-tools/guidelines/components/loading-states.md +0 -17
  23. package/agent-tools/guidelines/components/menu.md +0 -58
  24. package/agent-tools/guidelines/components/overview.md +0 -124
  25. package/agent-tools/guidelines/components/radial-progress.md +0 -13
  26. package/agent-tools/guidelines/components/select.md +0 -23
  27. package/agent-tools/guidelines/components/tooltips.md +0 -22
  28. package/agent-tools/guidelines/components/video.md +0 -29
  29. package/agent-tools/guidelines/foundations/color.md +0 -168
  30. package/agent-tools/guidelines/foundations/modes.md +0 -69
  31. package/agent-tools/guidelines/foundations/spacing.md +0 -107
  32. package/agent-tools/guidelines/foundations/typography.md +0 -82
  33. package/agent-tools/guidelines/overview-icons.md +0 -19
  34. package/agent-tools/guidelines/overview-illustrations.md +0 -7
  35. package/agent-tools/guidelines/overview-patterns.md +0 -7
  36. package/agent-tools/guidelines/overview.md +0 -84
  37. package/agent-tools/guidelines/setup.md +0 -83
  38. package/agent-tools/rules/accessibility.mdc +0 -78
  39. package/agent-tools/skills/gamut-accessibility/SKILL.md +0 -224
  40. package/agent-tools/skills/gamut-color-mode/SKILL.md +0 -149
  41. package/agent-tools/skills/gamut-components/SKILL.md +0 -46
  42. package/agent-tools/skills/gamut-forms/SKILL.md +0 -101
  43. package/agent-tools/skills/gamut-style-utilities/SKILL.md +0 -111
  44. package/agent-tools/skills/gamut-system-props/SKILL.md +0 -225
  45. package/agent-tools/skills/gamut-testing/SKILL.md +0 -225
  46. package/agent-tools/skills/gamut-theming/SKILL.md +0 -63
  47. package/agent-tools/skills/gamut-typography/SKILL.md +0 -79
  48. package/bin/commands/plugin/install.mjs +0 -213
  49. package/bin/commands/plugin/list.mjs +0 -73
  50. package/bin/commands/plugin/remove.mjs +0 -108
  51. package/bin/commands/plugin/update.mjs +0 -59
  52. package/bin/gamut.mjs +0 -96
  53. package/bin/lib/claude.mjs +0 -52
  54. package/bin/lib/cursor.mjs +0 -40
  55. package/bin/lib/design.mjs +0 -71
  56. package/bin/lib/io.mjs +0 -14
  57. package/bin/lib/resolve-plugin-dir.mjs +0 -38
  58. package/bin/lib/run-command.mjs +0 -22
  59. package/dist/InternalFloatingCard/InternalFloatingCard.js +0 -98
@@ -1,225 +0,0 @@
1
- ---
2
- name: gamut-system-props
3
- description: Layout, spacing, color, flex, grid system props from @codecademy/gamut-styles. When invoked, read guidelines/foundations/spacing.md first.
4
- ---
5
-
6
- # Gamut System Props
7
-
8
- ## Read first
9
-
10
- When this skill applies, read [`guidelines/foundations/spacing.md`](../../guidelines/foundations/spacing.md) before writing code.
11
-
12
- Source: `@codecademy/gamut-styles` — [`variance/config.ts`](https://github.com/Codecademy/gamut/blob/main/packages/gamut-styles/src/variance/config.ts) (definitions) and [`variance/props.ts`](https://github.com/Codecademy/gamut/blob/main/packages/gamut-styles/src/variance/props.ts) (`variance.create` groups). `Box`, `FlexBox`, and `GridBox` compose the same groups in [`packages/gamut/src/Box/props.ts`](https://github.com/Codecademy/gamut/blob/main/packages/gamut/src/Box/props.ts).
13
-
14
- See also: [`gamut-style-utilities`](../gamut-style-utilities/SKILL.md) (`css`, `variant`, `states`, `StyleProps`). [foundations/spacing.md](../../guidelines/foundations/spacing.md) (token scale). [Styleguide — Best practices](../../../../styleguide/src/lib/Meta/Best%20practices.mdx) and Storybook [Responsive properties](https://gamut.codecademy.com/storybook/?path=/docs-foundations-system-responsive-properties--page).
15
-
16
- ## Styling rules
17
-
18
- - Never use inline `style` attributes. Use system props on `Box` / `FlexBox` / `Text`, or `css` / `variant` / `states` on styled components.
19
- - Use shorthand — `mb={16}`, not `marginBottom={16}`.
20
-
21
- | Long form | Shorthand |
22
- | -------------- | --------- |
23
- | `margin` | `m` |
24
- | `marginTop` | `mt` |
25
- | `marginBottom` | `mb` |
26
- | `marginX` | `mx` |
27
- | `marginY` | `my` |
28
- | `padding` | `p` |
29
- | `paddingX` | `px` |
30
- | `paddingY` | `py` |
31
-
32
- Colors and borders: `bg`, `color` / `textColor`, `borderColor`, `borderRadius` — values must be Gamut tokens, never raw hex.
33
-
34
- ## Overview
35
-
36
- System props are strongly-typed, theme-connected CSS prop groups from `@codecademy/gamut-styles`. They give styled components a consistent, responsive API. All props are built on top of `@codecademy/variance`.
37
-
38
- Each prop group has:
39
-
40
- - `properties`: The CSS properties it controls
41
- - `scale`: Token scale it's restricted to (theme colors, spacing values, etc.)
42
- - `transform`: Optional transform applied before output (e.g. `width={0.5}` → `width: 50%`)
43
-
44
- ## Basic usage
45
-
46
- ```tsx
47
- import styled from '@emotion/styled';
48
- import { system } from '@codecademy/gamut-styles';
49
-
50
- // Apply a single group
51
- const Box = styled.div(system.layout);
52
-
53
- // Compose multiple groups
54
- import { variance } from '@codecademy/variance';
55
-
56
- const FlexBox = styled.div(
57
- variance.compose(system.layout, system.flex, system.space)
58
- );
59
-
60
- <FlexBox display="flex" p={16} gap={8} width="100%" />;
61
- ```
62
-
63
- ## Prop groups
64
-
65
- ### `system.layout`
66
-
67
- Controls dimensions, display, overflow, and container behavior. This group also carries flex/grid item props used when laying out children: `flexGrow`, `flexShrink`, `flexBasis`, `order`, `gridColumn`, `gridRow`, `gridColumnStart`, `gridRowStart`, `gridColumnEnd`, `gridRowEnd`, `alignSelf`, `justifySelf`, `gridArea`.
68
-
69
- ```tsx
70
- const Box = styled.div(system.layout);
71
-
72
- <Box display="flex" width="50%" height="300px" verticalAlign="middle" />;
73
- ```
74
-
75
- Key props: `containerType`, `display`, `direction`, `dimensions`, `width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`, `overflow`, `overflowX`, `overflowY`, `verticalAlign`, plus the item props above (see `config.ts` for the full map).
76
-
77
- ### `system.space`
78
-
79
- Margin and padding using the theme's spacing scale. Supports logical properties (switches based on `useLogicalProperties` in `<GamutProvider>`).
80
-
81
- ```tsx
82
- const Box = styled.div(system.space);
83
-
84
- // Single value
85
- <Box p={8} m={16} />;
86
-
87
- // Responsive (array / object — see Responsive values)
88
- <Box my={[16, 24, 32]} px={[8, 16]} />;
89
- ```
90
-
91
- Key props: `p`, `pt`, `pr`, `pb`, `pl`, `px`, `py`, `m`, `mt`, `mr`, `mb`, `ml`, `mx`, `my`
92
-
93
- ### `system.color`
94
-
95
- Foreground, background, and border colors restricted to the theme's color palette.
96
-
97
- ```tsx
98
- const Box = styled.div(system.color);
99
-
100
- <Box bg="navy" color="gray-900" textColor="gray-100" borderColor="blue" />;
101
- ```
102
-
103
- Key props: `color`, `textColor` (both set CSS `color`), `bg`, `borderColor`, plus directional `borderColor*` variants — see `config.ts` for the full set.
104
-
105
- ### `system.typography`
106
-
107
- Text styling connected to theme typography scales.
108
-
109
- ```tsx
110
- const Text = styled.p(system.typography);
111
-
112
- <Text
113
- fontSize={16}
114
- fontFamily="accent"
115
- fontStyle="italic"
116
- textTransform="uppercase"
117
- lineHeight="base"
118
- />;
119
- ```
120
-
121
- Key props: `fontFamily`, `fontSize`, `fontWeight`, `fontStyle`, `lineHeight`, `textAlign`, `textTransform`, `textDecoration`, `letterSpacing`, `whiteSpace` — prefer `lineHeight` scale keys (`base`, `title`, `spacedTitle`) from the theme over raw numbers when possible.
122
-
123
- ### `system.border`
124
-
125
- Border width, style, radius, and color. Many logical shorthands exist (`borderX`, `borderColorY`, `borderRadiusTop`, …); see `config.ts` for the full map.
126
-
127
- Key props (non-exhaustive): `border`, `borderTop`, `borderRight`, `borderBottom`, `borderLeft`, `borderRadius`, `borderWidth`, `borderStyle`
128
-
129
- ### `system.background`
130
-
131
- Background image, size, position, and repeat (for images/patterns — use `system.color` for solid background colors).
132
-
133
- ```tsx
134
- import myBg from './myBg.png';
135
-
136
- const Box = styled.div(system.background);
137
-
138
- <Box
139
- background={`url(${myBg})`}
140
- backgroundSize="cover"
141
- backgroundPosition="center"
142
- />;
143
- ```
144
-
145
- Key props: `background`, `backgroundImage`, `backgroundSize`, `backgroundPosition`, `backgroundRepeat`
146
-
147
- ### `system.flex`
148
-
149
- Flexbox child and container properties.
150
-
151
- Key props (non-exhaustive): `flex`, `flexDirection`, `flexWrap`, `flexGrow`, `flexShrink`, `flexBasis`, `alignItems`, `alignContent`, `alignSelf`, `justifyContent`, `justifyItems`, `justifySelf`, `gap`, `rowGap`, `columnGap`
152
-
153
- ### `system.grid`
154
-
155
- CSS Grid container and child properties.
156
-
157
- Key props (non-exhaustive): `gridTemplateColumns`, `gridTemplateRows`, `gridTemplateAreas`, `gridColumn`, `gridRow`, `gridArea`, `gridAutoFlow`, `gridAutoColumns`, `gridAutoRows`, `gap`, `rowGap`, `columnGap`
158
-
159
- ### `system.positioning`
160
-
161
- Position and offset properties. Inset shorthands use `transformSize`; physical vs logical edges follow `useLogicalProperties`.
162
-
163
- ```tsx
164
- const Overlay = styled.div(variance.compose(system.layout, system.positioning));
165
-
166
- <Overlay position="absolute" top={0} left={0} width="100%" height="100%" />;
167
- ```
168
-
169
- Key props: `position`, `inset`, `top`, `right`, `bottom`, `left`, `zIndex`, `opacity`
170
-
171
- ### `system.shadow`
172
-
173
- Box and text shadow.
174
-
175
- Key props: `boxShadow`, `textShadow`
176
-
177
- ### `system.list`
178
-
179
- List marker styling (`listStyle`, `listStyleType`, `listStylePosition`, `listStyleImage`). Included on `Box` alongside the other composed groups.
180
-
181
- ## Responsive values
182
-
183
- All system props accept responsive values mobile-first (min-width queries). Two shapes are supported:
184
-
185
- ### Object syntax
186
-
187
- Keys are breakpoints; `_` is the base (no breakpoint). Includes `xs`, `sm`, `md`, `lg`, `xl`, and container keys `c_xs` … `c_xl`.
188
-
189
- ```tsx
190
- <Box width={{ _: '100%', sm: '50%', md: '33%' }} px={{ _: 8, md: 16 }} />
191
- ```
192
-
193
- ### Array syntax
194
-
195
- Slots map in order to: base, `xs`, `sm`, `md`, `lg`, `xl`, then `c_xs` … `c_xl`. Leave a slot empty (or use `undefined`) to skip a breakpoint.
196
-
197
- ```tsx
198
- <Box width={['100%', , '50%']} p={[8, 16, , 24]} />
199
- ```
200
-
201
- Full typings and behavior: [Responsive properties (Storybook)](https://gamut.codecademy.com/storybook/?path=/docs-foundations-system-responsive-properties--page).
202
-
203
- ## Using `css()` for styled definitions
204
-
205
- For static styles in styled components, use `css()` from `@codecademy/gamut-styles` (same implementation as `system.css` on the `system` namespace).
206
-
207
- ```tsx
208
- import { css } from '@codecademy/gamut-styles';
209
- import styled from '@emotion/styled';
210
-
211
- // Static color using raw token
212
- const Box = styled.div(css({ bg: 'navy-400', p: 4 }));
213
-
214
- // Semantic color (adapts to color mode)
215
- const Text = styled.div(css({ color: 'primary', p: 4 }));
216
- ```
217
-
218
- ## Key principles
219
-
220
- - Compose `system.*` groups via `variance.compose()` — don't apply multiple groups by chaining `styled.div(system.a)(system.b)`.
221
- - Prefer semantic color names on `system.color` (e.g. `bg="background"`, `textColor="text"`) so values track ColorMode; use raw palette keys only when the design should stay fixed across modes.
222
- - Use `bg` with semantic tokens for most mode-aware surfaces; use `<Background>` from `@codecademy/gamut-styles` when you need its contrast- and mode-aware behavior, not for every tinted panel.
223
- - Use `system.space` values on the spacing scale rather than arbitrary pixel strings to keep rhythm consistent.
224
- - For background images/patterns use `system.background`; for solid fills use `system.color` / semantic `bg` (or `Background` when that component’s behavior is required).
225
- - For reusable variants or boolean states on styled primitives, use `variant` / `states` from `@codecademy/gamut-styles` and expose props with `StyleProps<typeof …>` from `@codecademy/variance` — see [Best practices](../../../../styleguide/src/lib/Meta/Best%20practices.mdx).
@@ -1,225 +0,0 @@
1
- ---
2
- name: gamut-testing
3
- description: Unit tests for Gamut UI — setupRtl, MockGamutProvider, no jest.mock of @codecademy/gamut. When invoked, see commands/gamut-review.md Check 5 for test guardrails.
4
- ---
5
-
6
- # Gamut Testing
7
-
8
- ## Read first
9
-
10
- When this skill applies, skim [`commands/gamut-review.md`](../../commands/gamut-review.md) Check 5 (test setup) for blocking patterns before changing tests.
11
-
12
- Source: `@codecademy/gamut-tests` — [`index.tsx`](https://github.com/Codecademy/gamut/blob/main/packages/gamut-tests/src/index.tsx)
13
-
14
- ---
15
-
16
- ---
17
-
18
- ## What `MockGamutProvider` does (under `setupRtl`)
19
-
20
- `MockGamutProvider` forwards to `GamutProvider` with:
21
-
22
- - `useCache={false}` — stable Emotion output across tests
23
- - `useGlobals={false}` — no global Reboot/Typography bleed between files
24
- - `theme={theme}` — full token theme for styled components
25
- - Optional `useLogicalProperties` — forwarded for logical vs physical CSS in variance
26
-
27
- You normally do not import `MockGamutProvider` for plain component tests; `setupRtl` already wraps the component under test once. Import it inside a harness when the SUT needs a non-default provider flag or extra wrappers (see below).
28
-
29
- ---
30
-
31
- ## Decision guide
32
-
33
- | Scenario | Prefer |
34
- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
35
- | Default unit test for a Gamut (or app) component | `setupRtl(Component, defaultProps)` once per file / describe |
36
- | Vary `useLogicalProperties` across cases | Harness that accepts `useLogicalProperties` and wraps `MockGamutProvider`, then `setupRtl(Harness, defaults)`; pass overrides per `it` / `describe.each` |
37
- | Need `ColorMode` (or other context) around the SUT | Harness with `<ColorMode>` inside the tree, then `setupRtl(Harness)` — no need for raw `render` unless you are testing the provider itself |
38
- | `dir` / RTL behavior (e.g. mirrored layout, `useElementDir`) | Keep using `setupRtl` for the component; set `document.documentElement.setAttribute('dir', 'rtl' \| 'ltr')` (and scroll/viewport stubs if needed) in `beforeEach` / `afterEach`; reset `dir` after tests so suites do not leak |
39
- | Storybook-only mock, chromatic-style wrapper, or non-RTL harness | `MockGamutProvider` (± `ColorMode`) in the exported wrapper component |
40
-
41
- ---
42
-
43
- ## `setupRtl` — primary pattern
44
-
45
- ```tsx
46
- import { setupRtl } from '@codecademy/gamut-tests';
47
-
48
- import { MyComponent } from '../MyComponent';
49
-
50
- const renderView = setupRtl(MyComponent, {
51
- label: 'Default label',
52
- onClick: jest.fn(),
53
- });
54
-
55
- it('renders the label', () => {
56
- const { view } = renderView();
57
- expect(view.getByText('Default label')).toBeInTheDocument();
58
- });
59
-
60
- it('accepts prop overrides', () => {
61
- const { view } = renderView({ label: 'Override' });
62
- expect(view.getByText('Override')).toBeInTheDocument();
63
- });
64
- ```
65
-
66
- `renderView` returns `{ view, props, update }`:
67
-
68
- - `view` — RTL `RenderResult` (`getByRole`, `getByLabelText`, `getByText`, …)
69
- - `props` — resolved props (handy for `jest.fn()` assertions)
70
- - `update` — re-render with new props without remounting
71
-
72
- ### Query and interaction habits (RTL)
73
-
74
- - Prefer `getByRole`, `getByLabelText`, and accessible names over CSS selectors or snapshotting class strings unless you are explicitly testing styling.
75
- - Prefer `@testing-library/user-event` over `fireEvent` when simulating real input (import `userEvent` from `@testing-library/user-event` in current major versions).
76
-
77
- ### Accessing mock functions via `props`
78
-
79
- ```tsx
80
- import userEvent from '@testing-library/user-event';
81
-
82
- it('calls onClick when clicked', async () => {
83
- const { view, props } = renderView();
84
- await userEvent.click(view.getByRole('button'));
85
- expect(props.onClick).toHaveBeenCalled();
86
- });
87
- ```
88
-
89
- ---
90
-
91
- ## Harness + `setupRtl` when the wrapper is not default
92
-
93
- `setupRtl` always wraps with `MockGamutProvider` with default props. To vary `useLogicalProperties`, add `ColorMode`, or compose other providers, define a small harness and pass `setupRtl` that harness — still one `renderView` factory, still `props` / `update` ergonomics.
94
-
95
- ### Varying `useLogicalProperties` (logical vs physical CSS)
96
-
97
- ```tsx
98
- import { MockGamutProvider, setupRtl } from '@codecademy/gamut-tests';
99
-
100
- import { MyComponent } from '../MyComponent';
101
-
102
- type HarnessProps = React.ComponentProps<typeof MyComponent> & {
103
- useLogicalProperties?: boolean;
104
- };
105
-
106
- const MyHarness = ({ useLogicalProperties, ...rest }: HarnessProps) => (
107
- <MockGamutProvider useLogicalProperties={useLogicalProperties}>
108
- <MyComponent {...rest} />
109
- </MockGamutProvider>
110
- );
111
-
112
- const renderView = setupRtl(MyHarness, { width: '200px' });
113
-
114
- describe.each([
115
- { useLogicalProperties: true as const, widthProp: 'inlineSize' as const },
116
- { useLogicalProperties: false as const, widthProp: 'width' as const },
117
- ])(
118
- 'useLogicalProperties=$useLogicalProperties',
119
- ({ useLogicalProperties, widthProp }) => {
120
- it(`uses ${widthProp}`, () => {
121
- const { view } = renderView({ useLogicalProperties });
122
- expect(view.getByTestId('my-component-root')).toHaveStyle({
123
- [widthProp]: '200px',
124
- });
125
- });
126
- }
127
- );
128
- ```
129
-
130
- The outer `setupRtl` wrapper adds a default `MockGamutProvider`; the harness’s inner `MockGamutProvider` sets `useLogicalProperties` for the subtree under test (nested `GamutProvider` / theme is the nearest one Emotion and variance see).
131
-
132
- ### `ColorMode` without abandoning `setupRtl`
133
-
134
- ```tsx
135
- import { ColorMode } from '@codecademy/gamut-styles';
136
- import { setupRtl } from '@codecademy/gamut-tests';
137
-
138
- const DarkHarness = (props: React.ComponentProps<typeof MyComponent>) => (
139
- <ColorMode mode="dark">
140
- <MyComponent {...props} />
141
- </ColorMode>
142
- );
143
-
144
- const renderDark = setupRtl(DarkHarness, { title: 'Hi' });
145
- ```
146
-
147
- Use `MockGamutProvider` only inside the harness if you also need a non-default Gamut flag and `ColorMode` in the same tree; otherwise `setupRtl(DarkHarness)` is enough.
148
-
149
- ---
150
-
151
- ## Raw `render` + `MockGamutProvider` — rare
152
-
153
- Reserve `render` from `@testing-library/react` + manual `MockGamutProvider` for cases where a harness would be more obscure than a single inline tree (e.g. highly dynamic one-off trees). If the same wrapper appears more than once, switch to a harness + `setupRtl`.
154
-
155
- ---
156
-
157
- ## RTL / `dir` and document-level behavior
158
-
159
- Some components (e.g. overlays that call `useElementDir`) resolve direction from `document.documentElement` when there is no real target node. For those tests:
160
-
161
- - Set `document.documentElement.setAttribute('dir', 'rtl')` (or `'ltr'`) around the scenario, `unmount` between LTR and RTL assertions when re-rendering, and restore `dir` in `afterEach` so other tests start clean.
162
- - Combine with the harness pattern above when `useLogicalProperties` affects which longhand wins (`left` vs `insetInlineStart`, etc.).
163
-
164
- ---
165
-
166
- ## Emotion style assertions
167
-
168
- Install `@emotion/jest` matchers if you absolutely need to enable CSS-in-JS assertions:
169
-
170
- ```tsx
171
- import { matchers } from '@emotion/jest';
172
-
173
- expect.extend(matchers);
174
- ```
175
-
176
- Then assert on styles:
177
-
178
- ```tsx
179
- expect(element).toHaveStyle({ borderRadius: '2px' });
180
- expect(element).toHaveStyleRule('padding', '1rem');
181
- ```
182
-
183
- Use `theme` from `@codecademy/gamut-styles` instead of hardcoding token strings:
184
-
185
- ```tsx
186
- import { theme } from '@codecademy/gamut-styles';
187
-
188
- expect(element).toHaveStyle({ columnGap: theme.spacing[40] });
189
- ```
190
-
191
- ---
192
-
193
- ## Visual test wrappers and Storybook
194
-
195
- Exported mocks and stories may wrap with `MockGamutProvider` and `ColorMode` explicitly (no `setupRtl` in Storybook):
196
-
197
- ```tsx
198
- import { MockGamutProvider } from '@codecademy/gamut-tests';
199
- import { ColorMode } from '@codecademy/gamut-styles';
200
-
201
- export const MyComponentMock: React.FC<ComponentProps<typeof MyComponent>> = (
202
- props
203
- ) => (
204
- <MockGamutProvider>
205
- <ColorMode mode="light">
206
- <MyComponent {...props} />
207
- </ColorMode>
208
- </MockGamutProvider>
209
- );
210
- ```
211
-
212
- ---
213
-
214
- ## Common anti-patterns
215
-
216
- | Anti-pattern | Fix |
217
- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
218
- | `jest.mock('@codecademy/gamut', () => ({ ... }))` | Remove; use `setupRtl` (or harness + `setupRtl`) |
219
- | `jest.mock('@codecademy/gamut-styles', ...)` | Remove; `MockGamutProvider` / `setupRtl` supplies theme |
220
- | `GamutProvider` in test files | Use `MockGamutProvider` only when building a harness or story; default tests go through `setupRtl` |
221
- | `import { setupRtl } from 'component-test-setup'` in Gamut / apps | Import `setupRtl` from `@codecademy/gamut-tests` so `MockGamutProvider` is applied |
222
- | Repeated `render(<MockGamutProvider>…` | Harness + `setupRtl`, or a shared `renderView` factory |
223
- | One `setupRtl` call per `it` | Define `renderView` once outside `describe`, call it inside each `it` |
224
- | Asserting raw CSS strings for tokens | Use `theme` from `@codecademy/gamut-styles` |
225
- | Leaking `dir="rtl"` between tests | Reset `document.documentElement` in `afterEach` |
@@ -1,63 +0,0 @@
1
- ---
2
- name: gamut-theming
3
- description: Gamut themes, GamutProvider, theme.d.ts, CreatingThemes. When invoked, read guidelines/setup.md and repo DESIGN.md first. Not for css/variant/states (see gamut-style-utilities).
4
- ---
5
-
6
- # Gamut Theming
7
-
8
- ## Read first
9
-
10
- When this skill applies, read before writing code:
11
-
12
- - [`guidelines/setup.md`](../../guidelines/setup.md)
13
- - Root `DESIGN.md` in the app repo (product tokens and patterns)
14
-
15
- Source: `@codecademy/gamut-styles`
16
-
17
- See also: [`gamut-style-utilities`](../gamut-style-utilities/SKILL.md) (`css`, `variant`, `states`, `StyleProps`, `useTheme` escape hatch). [`gamut-color-mode`](../gamut-color-mode/SKILL.md) (semantic color, `<ColorMode>`, `<Background>`). [`gamut-system-props`](../gamut-system-props/SKILL.md) (`system.*`, responsive `Box` props).
18
-
19
- ## Overview
20
-
21
- Gamut uses Emotion's theme system. Themes are org-specific token bundles (colors, typography, spacing, etc.). The active theme is set at the app root with `<GamutProvider theme={...}>`; child styled components read tokens through Emotion context.
22
-
23
- For authoring component styles (`css`, `variant`, `states`, system props, ColorMode), use the skills linked above and the styleguide [Best practices](../../../../styleguide/src/lib/Meta/Best%20practices.mdx).
24
-
25
- ## Infer theme from the repo
26
-
27
- Do not hardcode a product theme in generic guidance. In an app repo:
28
-
29
- 1. Read root `DESIGN.md` (installed via `gamut plugin install --theme <name>`) for semantic tokens, fonts, and product patterns.
30
- 2. Confirm `<GamutProvider theme={...}>` matches that product (`coreTheme`, `percipioTheme`, `lxStudioTheme`, etc.).
31
- 3. Use Storybook Foundations / Theme stories for the active product when verifying hex ↔ semantic mappings.
32
-
33
- ## Available themes
34
-
35
- | Theme | Used for |
36
- | --------- | ---------------------------------------------------------- |
37
- | Core | Codecademy default |
38
- | Admin | Codecademy admin tools |
39
- | Platform | Codecademy learning environment / shared platform surfaces |
40
- | LX Studio | Learning Experience Studio |
41
- | Percipio | Skillsoft Percipio platform |
42
-
43
- Product-level import names and `theme.d.ts` patterns live in [setup.md](../../guidelines/setup.md).
44
-
45
- ## Theme vs color mode vs style API
46
-
47
- | Concern | Where to read |
48
- | ------------------------------------------------------- | -------------------------------------------------- |
49
- | Which `theme` object to pass to `GamutProvider` | This skill + [setup.md](../../guidelines/setup.md) |
50
- | Light / dark semantic colors, `ColorMode`, `Background` | `gamut-color-mode` |
51
- | `css` / `variant` / `states`, `useTheme` for non-CSS JS | `gamut-style-utilities` |
52
- | Composed `system.*` props on styled primitives / `Box` | `gamut-system-props` |
53
-
54
- ## Creating a new theme
55
-
56
- See `CreatingThemes.mdx` in the styleguide (`packages/styleguide/src/lib/Foundations/Theme/CreatingThemes.mdx`). Themes are defined in `@codecademy/gamut-styles` and must extend the base theme shape with all required token keys.
57
-
58
- ## Key principles
59
-
60
- - Pick the correct theme export for the product (`coreTheme`, `adminTheme`, `platformTheme`, `lxStudioTheme`, `percipioTheme`, etc.) so tokens and fonts match `DESIGN.md` and design intent.
61
- - Align `theme.d.ts` / `Theme extends …` with the same theme interface you pass to `GamutProvider` (see [setup.md](../../guidelines/setup.md)).
62
- - Components stay portable across themes when they use token and semantic aliases rather than one-off hex; authoring rules live in `gamut-style-utilities` and `gamut-color-mode`.
63
- - `GamutProvider` wires theme, color mode, and logical-properties settings at the root; individual components should not hard-code which org theme is active.
@@ -1,79 +0,0 @@
1
- ---
2
- name: gamut-typography
3
- description: Gamut UI text — headlines, body, fontSize, lineHeight, fontWeight title. When invoked, read guidelines/foundations/typography.md and DESIGN.md for the active theme.
4
- ---
5
-
6
- # Gamut Typography
7
-
8
- ## Read first
9
-
10
- When this skill applies, read [`guidelines/foundations/typography.md`](../../guidelines/foundations/typography.md) before writing code. Confirm stacks and `fontWeight.title` against root `DESIGN.md`.
11
-
12
- Implementation source of truth: [`packages/gamut-styles/src/variables/typography.ts`](https://github.com/Codecademy/gamut/blob/main/packages/gamut-styles/src/variables/typography.ts) and themes under [`packages/gamut-styles/src/themes`](https://github.com/Codecademy/gamut/tree/main/packages/gamut-styles/src/themes).
13
-
14
- ## Scope by theme
15
-
16
- | Themes | Fonts | `fontWeight.title` |
17
- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
18
- | Core, Admin, Platform | `base` → Apercu stack; `accent` → Suisse + Apercu stack | 700 |
19
- | Percipio, LX Studio | `base` → Skillsoft Text; `accent` → Skillsoft Sans; Percipio `monospace` → Roboto Mono; LX `monospace` matches Core stack per theme file | 500 |
20
-
21
- Use `fontWeight="title"` for headlines / emphasis roles — never hardcode `700` on Percipio/LX unless SPECIFICALLY noted in Figma designs.
22
-
23
- ## Font size scale (`fontSize`)
24
-
25
- Theme keys: `64`, `44`, `34`, `26`, `22`, `20`, `18`, `16`, `14`.
26
-
27
- ```tsx
28
- import { css } from '@codecademy/gamut-styles';
29
- import styled from '@emotion/styled';
30
- import { system } from '@codecademy/gamut-styles';
31
-
32
- const Paragraph = styled.p(system.typography);
33
- <Paragraph fontSize={16} lineHeight="base" />;
34
-
35
- const Styled = styled.div(css({ fontSize: 14, fontFamily: 'base' }));
36
- ```
37
-
38
- ## Line height (`lineHeight`)
39
-
40
- Tokens: `base` (1.5), `spacedTitle` (1.3), `title` (1.2). Prefer tokens over raw decimals. Only specify `lineHeight` when specified by design.
41
-
42
- ## Line length
43
-
44
- | Context | Target |
45
- | ------------------ | ------------------------ |
46
- | Single-column body | ~66 characters (max ~85) |
47
- | Multi-column | ≤50 characters per line |
48
- | Minimum | ~45 characters |
49
-
50
- ## Accessing typography tokens
51
-
52
- ```tsx
53
- import { system } from '@codecademy/gamut-styles';
54
- import { variance } from '@codecademy/variance';
55
-
56
- const Heading = styled.h2(variance.compose(system.typography, system.space));
57
-
58
- <Heading
59
- fontSize={26}
60
- fontFamily="base"
61
- fontWeight="title"
62
- lineHeight="title"
63
- mb={8}
64
- />;
65
-
66
- import { css } from '@codecademy/gamut-styles';
67
-
68
- const Caption = styled.span(
69
- css({ fontFamily: 'accent', fontSize: 14, color: 'text-secondary' })
70
- );
71
- ```
72
-
73
- Prefer `<Text>` from `@codecademy/gamut` with `variant` / `as` — see Storybook [Typography / Text](https://gamut.codecademy.com/?path=/docs-typography-text--docs).
74
-
75
- ## Semantic vs visual headings
76
-
77
- - `<Text as="h1">` … `<Text as="h6">` gets default heading styles: each tag maps to the same scale as `variant="title-xxl"` … `variant="title-xs"` (`h1` largest through `h6` smallest). Plain `<Text>` defaults to `as="span"` (inherits font size).
78
- - Use `variant` plus `fontSize` / `fontWeight` / `lineHeight` (and other system props) to override element defaults when the outline needs one heading level but the UI needs another visual weight — e.g. `<Text as="h2" variant="title-sm">`.
79
- - Still pick `h1`–`h6` for document structure and assistive tech; overrides are for intentional divergence between semantics and appearance.