@codecademy/styleguide 79.2.1-alpha.cb2cfc.0 → 79.2.1-alpha.f4b2b2.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.
@@ -3,7 +3,7 @@ import { GamutIconProps } from '@codecademy/gamut-icons';
3
3
  import { IllustrationProps } from '@codecademy/gamut-illustrations';
4
4
  import { PatternProps } from '@codecademy/gamut-patterns';
5
5
  import { css, timingValues } from '@codecademy/gamut-styles';
6
- import { motion, AnimatePresence } from 'framer-motion';
6
+ import { motion, AnimatePresence } from 'motion/react';
7
7
  import * as React from 'react';
8
8
  import { useState } from 'react';
9
9
  import styled from '@emotion/styled';
@@ -2,7 +2,6 @@ export * from './ImageWrapper';
2
2
  export * from './TokenTable';
3
3
  export * from './Headers';
4
4
  export * from './Elements/Callout';
5
- export * from './Elements/DetailedCode';
6
5
  export * from './Elements/KeyboardKey';
7
6
  export * from './Elements/Markdown';
8
7
  export * from './Elements/ImageGallery';
package/CHANGELOG.md CHANGED
@@ -3,7 +3,7 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ### [79.2.1-alpha.cb2cfc.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@79.2.0...@codecademy/styleguide@79.2.1-alpha.cb2cfc.0) (2026-03-16)
6
+ ### [79.2.1-alpha.f4b2b2.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@79.2.0...@codecademy/styleguide@79.2.1-alpha.f4b2b2.0) (2026-03-16)
7
7
 
8
8
  **Note:** Version bump only for package @codecademy/styleguide
9
9
 
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@codecademy/styleguide",
3
3
  "description": "Styleguide & Component library for codecademy.com",
4
- "version": "79.2.1-alpha.cb2cfc.0",
4
+ "version": "79.2.1-alpha.f4b2b2.0",
5
5
  "author": "Codecademy Engineering",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
10
10
  "repository": "git@github.com:Codecademy/gamut.git",
11
- "gitHead": "8f7b19e053cc39e26d9be621c1b408d692e012f5"
11
+ "gitHead": "05dffa01ea7348becd1074075040204794f0fdaf"
12
12
  }
@@ -5,7 +5,7 @@ import {
5
5
  FlexBox,
6
6
  } from '@codecademy/gamut';
7
7
  import type { Meta } from '@storybook/react';
8
- import { AnimatePresence } from 'framer-motion';
8
+ import { AnimatePresence } from 'motion/react';
9
9
  import { PropsWithChildren, useState } from 'react';
10
10
 
11
11
  const meta: Meta<typeof ExpandInCollapseOut> = {
@@ -1,6 +1,6 @@
1
1
  import { Box, FadeInSlideOut, FillButton, FlexBox } from '@codecademy/gamut';
2
2
  import type { Meta } from '@storybook/react';
3
- import { AnimatePresence } from 'framer-motion';
3
+ import { AnimatePresence } from 'motion/react';
4
4
  import { useState } from 'react';
5
5
 
6
6
  const meta: Meta<typeof FadeInSlideOut> = {
@@ -79,7 +79,7 @@ const ExpandableContainer = styled.Box(
79
79
 
80
80
  #### Disabling the rule
81
81
 
82
- For third-party components or edge cases where inline styles are necessary (e.g., framer-motion animations), you can disable the rule:
82
+ For third-party components or edge cases where inline styles are necessary (e.g., motion animations), you can disable the rule:
83
83
 
84
84
  ```tsx
85
85
  // eslint-disable-next-line gamut/no-inline-style
@@ -39,21 +39,44 @@ yarn add @codecademy/gamut-kit @emotion/react @emotion/styled
39
39
 
40
40
  3. Wrap your application root with `GamutProvider` and give it the theme you would like to use for your app.
41
41
 
42
+ **React 19:**
43
+
42
44
  ```tsx
43
45
  import React from 'react';
44
- import { render } from 'react-dom';
46
+ import { createRoot } from 'react-dom/client';
45
47
  import { GamutProvider, theme } from '@codecademy/gamut-styles';
46
48
 
47
49
  import { App } from './App';
48
50
 
49
51
  const rootElement = document.getElementById('root');
52
+ if (rootElement) {
53
+ const root = createRoot(rootElement);
54
+ root.render(
55
+ <GamutProvider>
56
+ <App />
57
+ </GamutProvider>
58
+ );
59
+ }
60
+ ```
50
61
 
51
- render(
52
- <GamutProvider>
53
- <App />
54
- </GamutProvider>,
55
- rootElement
56
- );
62
+ **React 18:**
63
+
64
+ ```tsx
65
+ import React from 'react';
66
+ import { render } from 'react-dom';
67
+ import { GamutProvider, theme } from '@codecademy/gamut-styles';
68
+
69
+ import { App } from './App';
70
+
71
+ const rootElement = document.getElementById('root');
72
+ if (rootElement) {
73
+ render(
74
+ <GamutProvider>
75
+ <App />
76
+ </GamutProvider>,
77
+ rootElement
78
+ );
79
+ }
57
80
  ```
58
81
 
59
82
  GamutProvider handles a few critical tasks that need to happen in order for components to work.
@@ -1,9 +1,8 @@
1
1
  import { Canvas, Controls, Meta } from '@storybook/blocks';
2
2
 
3
- import { ComponentHeader, DetailedCode, LinkTo } from '~styleguide/blocks';
3
+ import { ComponentHeader, LinkTo } from '~styleguide/blocks';
4
4
 
5
5
  import * as ConnectedFormStories from './ConnectedForm.stories';
6
- import { example } from './example';
7
6
 
8
7
  export const parameters = {
9
8
  title: 'ConnectedForm',
@@ -41,7 +40,75 @@ This hook also returns the `FormRequiredText` component - include this before yo
41
40
 
42
41
  ### Example code
43
42
 
44
- <DetailedCode code={example} language="tsx" preview />
43
+ ```tsx
44
+ import {
45
+ ConnectedCheckbox,
46
+ ConnectedInput,
47
+ ConnectedSelect,
48
+ useConnectedForm,
49
+ } from '@codecademy/gamut';
50
+
51
+ import { TerminalIcon } from '@codecademy/gamut-icons';
52
+
53
+ export const GoodForm = () => {
54
+ const {
55
+ ConnectedFormGroup,
56
+ ConnectedForm,
57
+ connectedFormProps,
58
+ FormRequiredText,
59
+ } = useConnectedForm({
60
+ defaultValues: {
61
+ thisField: true,
62
+ thatField: 'zero',
63
+ anotherField: 'state your name.',
64
+ },
65
+ validationRules: {
66
+ thisField: { required: 'you need to check this.' },
67
+ thatField: {
68
+ pattern: {
69
+ value: /^(?:(?!zero).)*$/,
70
+ message: 'literally anything but zero',
71
+ },
72
+ },
73
+ },
74
+ });
75
+
76
+ return (
77
+ <ConnectedForm
78
+ onSubmit={({ thisField }) => console.log(thisField)}
79
+ resetOnSubmit
80
+ {...connectedFormProps}
81
+ >
82
+ <SubmitButton>submit this form.</SubmitButton>
83
+ <ConnectedFormGroup
84
+ name="thisField"
85
+ label="cool checkbox bruh"
86
+ field={{
87
+ component: ConnectedCheckbox,
88
+ label: 'check it ouuut',
89
+ }}
90
+ />
91
+ <ConnectedFormGroup
92
+ name="thatField"
93
+ label="cool select dude"
94
+ field={{
95
+ component: ConnectedSelect,
96
+ options: ['one', 'two', 'zero'],
97
+ }}
98
+ />
99
+ <ConnectedFormGroup
100
+ name="anotherField"
101
+ label="cool input"
102
+ field={{
103
+ component: ConnectedInput,
104
+ icon: TerminalIcon,
105
+ }}
106
+ />
107
+ <FormRequiredText />
108
+ </ConnectedForm>
109
+ );
110
+ };
111
+ ```
45
112
 
46
113
  ## Variants
47
114
 
@@ -1,19 +0,0 @@
1
- import { Source } from '@storybook/blocks';
2
-
3
- import { DetailedCodeBodyWrapper, FloatingIndicator } from '../elements';
4
- import { DetailedCodeBodyProps } from '../types';
5
-
6
- export const DetailedCodeBody: React.FC<DetailedCodeBodyProps> = ({
7
- code,
8
- language,
9
- showFloatingBadge = false,
10
- }) => {
11
- return (
12
- <DetailedCodeBodyWrapper hasFloatingBadge={showFloatingBadge}>
13
- <Source code={code} dark language={language} />
14
- {showFloatingBadge && (
15
- <FloatingIndicator aria-label="More code below">...</FloatingIndicator>
16
- )}
17
- </DetailedCodeBodyWrapper>
18
- );
19
- };
@@ -1,32 +0,0 @@
1
- import { MiniChevronDownIcon } from '@codecademy/gamut-icons';
2
- import * as React from 'react';
3
- import { Anchor, Rotation, FlexBox, Text } from '@codecademy/gamut';
4
-
5
- import { DetailedCodeButtonProps } from '../types';
6
-
7
- export const DetailedCodeButton: React.FC<DetailedCodeButtonProps> = ({
8
- isExpanded,
9
- onToggle,
10
- language,
11
- }) => {
12
- return (
13
- <Anchor
14
- aria-expanded={isExpanded}
15
- px={16}
16
- py={12}
17
- variant="interface"
18
- width="100%"
19
- onClick={onToggle}
20
- >
21
- <FlexBox columnGap={16} justifyContent="space-between">
22
- <Text>{language}</Text>
23
- <FlexBox columnGap={8} flexDirection="row" alignItems="center">
24
- <Text>{isExpanded ? 'Show Less Code' : 'Show More Code'}</Text>
25
- <Rotation rotated={isExpanded}>
26
- <MiniChevronDownIcon aria-hidden size={16} />
27
- </Rotation>
28
- </FlexBox>
29
- </FlexBox>
30
- </Anchor>
31
- );
32
- };
@@ -1,46 +0,0 @@
1
- import { css } from '@codecademy/gamut-styles';
2
- import styled from '@emotion/styled';
3
- import { FlexBox } from '@codecademy/gamut';
4
-
5
- export const DetailedCodeWrapper = styled(FlexBox)(
6
- css({
7
- width: '100%',
8
- flexDirection: 'column',
9
- borderRadius: 'md',
10
- border: 1,
11
- bg: 'background',
12
- })
13
- );
14
-
15
- export const DetailedCodeBodyWrapper = styled(FlexBox)<{
16
- hasFloatingBadge?: boolean;
17
- }>(({ hasFloatingBadge }) =>
18
- css({
19
- position: 'relative',
20
- flexDirection: 'column',
21
- /* Override Storybook's Source component default styles to remove unwanted spacing and borders in the container */
22
- '& .docblock-source': {
23
- borderRadius: 'none',
24
- margin: 0,
25
- pb: hasFloatingBadge ? 48 : 0,
26
- },
27
- })
28
- );
29
-
30
- export const FloatingIndicator = styled(FlexBox)(
31
- css({
32
- position: 'absolute',
33
- bottom: 16,
34
- left: '50%',
35
- transform: 'translateX(-50%)',
36
- zIndex: 1,
37
- bg: 'inherit',
38
- px: 12,
39
- py: 4,
40
- borderRadius: 'lg',
41
- fontSize: 26,
42
- fontWeight: 700,
43
- color: 'white',
44
- letterSpacing: '0.1em',
45
- })
46
- );
@@ -1,48 +0,0 @@
1
- import React, { useState } from 'react';
2
-
3
- import { DetailedCodeBody } from './DetailedCodeBody';
4
- import { DetailedCodeButton } from './DetailedCodeButton';
5
- import { DetailedCodeWrapper } from './elements';
6
- import { DetailedCodeProps } from './types';
7
-
8
- const DEFAULT_PREVIEW_LINES = 20;
9
- const DEFAULT_LANGUAGE = 'tsx';
10
-
11
- export const DetailedCode: React.FC<DetailedCodeProps> = ({
12
- code,
13
- initiallyExpanded = false,
14
- language = DEFAULT_LANGUAGE,
15
- preview = false,
16
- previewLines = DEFAULT_PREVIEW_LINES,
17
- }) => {
18
- const [isExpanded, setIsExpanded] = useState(initiallyExpanded);
19
- const normalizedPreviewLines = Math.max(0, previewLines);
20
- const previewEnabled = preview && normalizedPreviewLines > 0;
21
-
22
- const codeLines = code.split('\n');
23
- const hasMoreCode =
24
- previewEnabled && codeLines.length > normalizedPreviewLines;
25
-
26
- const previewCode = previewEnabled
27
- ? codeLines.slice(0, normalizedPreviewLines).join('\n')
28
- : code;
29
-
30
- const displayedCode = isExpanded ? code : previewCode;
31
-
32
- return (
33
- <DetailedCodeWrapper>
34
- <DetailedCodeBody
35
- code={displayedCode}
36
- language={language}
37
- showFloatingBadge={hasMoreCode && !isExpanded}
38
- />
39
- {hasMoreCode && (
40
- <DetailedCodeButton
41
- isExpanded={isExpanded}
42
- onToggle={() => setIsExpanded((prev) => !prev)}
43
- language={language}
44
- />
45
- )}
46
- </DetailedCodeWrapper>
47
- );
48
- };
@@ -1,24 +0,0 @@
1
- import { Source } from '@storybook/blocks';
2
- import { ComponentProps } from 'react';
3
-
4
- type SourceLanguage = ComponentProps<typeof Source>['language'];
5
-
6
- export interface DetailedCodeProps {
7
- code: string;
8
- language?: SourceLanguage;
9
- initiallyExpanded?: boolean;
10
- preview?: boolean;
11
- previewLines?: number;
12
- }
13
-
14
- export interface DetailedCodeButtonProps {
15
- isExpanded: boolean;
16
- onToggle: () => void;
17
- language: SourceLanguage;
18
- }
19
-
20
- export interface DetailedCodeBodyProps {
21
- code: string;
22
- language: SourceLanguage;
23
- showFloatingBadge?: boolean;
24
- }
@@ -1,67 +0,0 @@
1
- export const example = `import {
2
- ConnectedCheckbox,
3
- ConnectedInput,
4
- ConnectedSelect,
5
- useConnectedForm,
6
- } from '@codecademy/gamut';
7
-
8
- import { TerminalIcon } from '@codecademy/gamut-icons';
9
-
10
- export const GoodForm = () => {
11
- const {
12
- ConnectedFormGroup,
13
- ConnectedForm,
14
- connectedFormProps,
15
- FormRequiredText,
16
- } = useConnectedForm({
17
- defaultValues: {
18
- thisField: true,
19
- thatField: 'zero',
20
- anotherField: 'state your name.',
21
- },
22
- validationRules: {
23
- thisField: { required: 'you need to check this.' },
24
- thatField: {
25
- pattern: {
26
- value: /^(?:(?!zero).)*$/,
27
- message: 'literally anything but zero',
28
- },
29
- },
30
- },
31
- });
32
-
33
- return (
34
- <ConnectedForm
35
- onSubmit={({ thisField }) => console.log(thisField)}
36
- resetOnSubmit
37
- {...connectedFormProps}
38
- >
39
- <SubmitButton>submit this form.</SubmitButton>
40
- <ConnectedFormGroup
41
- name="thisField"
42
- label="cool checkbox bruh"
43
- field={{
44
- component: ConnectedCheckbox,
45
- label: 'check it ouuut',
46
- }}
47
- />
48
- <ConnectedFormGroup
49
- name="thatField"
50
- label="cool select dude"
51
- field={{
52
- component: ConnectedSelect,
53
- options: ['one', 'two', 'zero'],
54
- }}
55
- />
56
- <ConnectedFormGroup
57
- name="anotherField"
58
- label="cool input"
59
- field={{
60
- component: ConnectedInput,
61
- icon: TerminalIcon,
62
- }}
63
- />
64
- <FormRequiredText />
65
- </ConnectedForm>
66
- );
67
- };`;