@codecademy/styleguide 79.1.3-alpha.9d6407.0 → 79.1.3-alpha.b3546f.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/.storybook/components/index.tsx +0 -1
- package/CHANGELOG.md +1 -1
- package/package.json +2 -2
- package/src/lib/Meta/Installation.mdx +30 -7
- package/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +70 -3
- package/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +0 -36
- package/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx +0 -40
- package/.storybook/components/Elements/DetailedCode/elements.tsx +0 -39
- package/.storybook/components/Elements/DetailedCode/index.tsx +0 -57
- package/.storybook/components/Elements/DetailedCode/types.ts +0 -25
- package/src/lib/Organisms/ConnectedForm/ConnectedForm/example.ts +0 -67
|
@@ -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.1.3-alpha.
|
|
6
|
+
### [79.1.3-alpha.b3546f.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@79.1.2...@codecademy/styleguide@79.1.3-alpha.b3546f.0) (2026-02-26)
|
|
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.1.3-alpha.
|
|
4
|
+
"version": "79.1.3-alpha.b3546f.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": "
|
|
11
|
+
"gitHead": "6fd80274674f1235f1f359dea4dfeb8b5e46df5b"
|
|
12
12
|
}
|
|
@@ -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 {
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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,
|
|
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
|
-
|
|
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,36 +0,0 @@
|
|
|
1
|
-
import { Source } from '@storybook/blocks';
|
|
2
|
-
import { ComponentProps } from 'react';
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
|
|
5
|
-
import { DetailedCodeBodyWrapper, FloatingExpandButton } from '../elements';
|
|
6
|
-
import { DetailedCodeBodyProps } from '../types';
|
|
7
|
-
|
|
8
|
-
type SourceLanguage = ComponentProps<typeof Source>['language'];
|
|
9
|
-
|
|
10
|
-
export const DetailedCodeBody: React.FC<DetailedCodeBodyProps> = ({
|
|
11
|
-
code,
|
|
12
|
-
language,
|
|
13
|
-
showFloatingBadge = false,
|
|
14
|
-
isExpanded = false,
|
|
15
|
-
setIsExpanded,
|
|
16
|
-
}) => {
|
|
17
|
-
const handleClick = () => {
|
|
18
|
-
if (setIsExpanded) {
|
|
19
|
-
setIsExpanded((prev) => !prev);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<DetailedCodeBodyWrapper hasFloatingBadge={showFloatingBadge}>
|
|
25
|
-
<Source code={code} dark language={language as SourceLanguage} />
|
|
26
|
-
{showFloatingBadge && (
|
|
27
|
-
<FloatingExpandButton
|
|
28
|
-
onClick={handleClick}
|
|
29
|
-
size="normal"
|
|
30
|
-
>
|
|
31
|
-
{isExpanded ? 'Show less code' : 'Show more code'}
|
|
32
|
-
</FloatingExpandButton>
|
|
33
|
-
)}
|
|
34
|
-
</DetailedCodeBodyWrapper>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
@@ -1,40 +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
|
-
setIsExpanded,
|
|
10
|
-
}) => {
|
|
11
|
-
const handleClick = () => {
|
|
12
|
-
if (setIsExpanded) {
|
|
13
|
-
setIsExpanded((prev: boolean) => !prev);
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<Anchor
|
|
19
|
-
aria-expanded={isExpanded}
|
|
20
|
-
height="100%"
|
|
21
|
-
px={16}
|
|
22
|
-
py={12}
|
|
23
|
-
variant="interface"
|
|
24
|
-
width="100%"
|
|
25
|
-
onClick={handleClick}
|
|
26
|
-
>
|
|
27
|
-
<FlexBox
|
|
28
|
-
columnGap={16}
|
|
29
|
-
flexDirection="row"
|
|
30
|
-
justifyContent="space-between"
|
|
31
|
-
width="100%"
|
|
32
|
-
>
|
|
33
|
-
<Text>{isExpanded ? 'Show Less Code' : 'Show More Code'}</Text>
|
|
34
|
-
<Rotation height={16} rotated={isExpanded} width={16}>
|
|
35
|
-
<MiniChevronDownIcon aria-hidden size={16} />
|
|
36
|
-
</Rotation>
|
|
37
|
-
</FlexBox>
|
|
38
|
-
</Anchor>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { css } from '@codecademy/gamut-styles';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import { FlexBox, TextButton } 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 FloatingExpandButton = styled(TextButton)(
|
|
31
|
-
css({
|
|
32
|
-
position: 'absolute',
|
|
33
|
-
bottom: 16,
|
|
34
|
-
left: '50%',
|
|
35
|
-
transform: 'translateX(-50%)',
|
|
36
|
-
zIndex: 1,
|
|
37
|
-
bg: 'white',
|
|
38
|
-
})
|
|
39
|
-
);
|
|
@@ -1,57 +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 = 10;
|
|
9
|
-
const DEFAULT_LANGUAGE = 'tsx';
|
|
10
|
-
|
|
11
|
-
const getPreviewCode = (code: string, previewLines: number) => {
|
|
12
|
-
const lines = code.split('\n');
|
|
13
|
-
|
|
14
|
-
if (lines.length <= previewLines) {
|
|
15
|
-
return code;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return lines.slice(0, previewLines).join('\n');
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const DetailedCode: React.FC<DetailedCodeProps> = ({
|
|
22
|
-
code,
|
|
23
|
-
initiallyExpanded = false,
|
|
24
|
-
language = DEFAULT_LANGUAGE,
|
|
25
|
-
preview = false,
|
|
26
|
-
previewLines = DEFAULT_PREVIEW_LINES,
|
|
27
|
-
}) => {
|
|
28
|
-
const [isExpanded, setIsExpanded] = useState(initiallyExpanded);
|
|
29
|
-
const normalizedPreviewLines = Math.max(0, previewLines);
|
|
30
|
-
const previewEnabled = preview && normalizedPreviewLines > 0;
|
|
31
|
-
const previewCode = previewEnabled
|
|
32
|
-
? getPreviewCode(code, normalizedPreviewLines)
|
|
33
|
-
: code;
|
|
34
|
-
|
|
35
|
-
const hasMoreCode =
|
|
36
|
-
previewEnabled && code.split('\n').length > normalizedPreviewLines;
|
|
37
|
-
|
|
38
|
-
const displayedCode = isExpanded ? code : previewCode;
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<DetailedCodeWrapper>
|
|
42
|
-
<DetailedCodeBody
|
|
43
|
-
code={displayedCode}
|
|
44
|
-
language={language}
|
|
45
|
-
showFloatingBadge={hasMoreCode}
|
|
46
|
-
isExpanded={isExpanded}
|
|
47
|
-
setIsExpanded={setIsExpanded}
|
|
48
|
-
/>
|
|
49
|
-
{/* {hasMoreCode && (
|
|
50
|
-
<DetailedCodeButton
|
|
51
|
-
isExpanded={isExpanded}
|
|
52
|
-
setIsExpanded={setIsExpanded}
|
|
53
|
-
/>
|
|
54
|
-
)} */}
|
|
55
|
-
</DetailedCodeWrapper>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
@@ -1,25 +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
|
-
setIsExpanded?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface DetailedCodeBodyProps {
|
|
20
|
-
code: string;
|
|
21
|
-
language: string;
|
|
22
|
-
showFloatingBadge?: boolean;
|
|
23
|
-
isExpanded?: boolean;
|
|
24
|
-
setIsExpanded?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
25
|
-
}
|
|
@@ -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
|
-
};`;
|