@codecademy/styleguide 79.2.2-alpha.422537.0 → 79.2.2-alpha.425c3f.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/CHANGELOG.md +1 -1
- package/package.json +2 -2
- package/src/lib/Atoms/FormInputs/SelectDropdown/SelectDropdown.mdx +1 -4
- package/src/lib/Atoms/PopoverContainer/PopoverContainer.mdx +1 -1
- package/src/lib/Atoms/PopoverContainer/PopoverContainer.stories.tsx +1 -1
- package/src/lib/Atoms/UtilityComponents/DelayedRenderWrapper/DelayedRenderWrapper.mdx +1 -1
- package/src/lib/Foundations/Layout.mdx +2 -1
- package/src/lib/Foundations/shared/elements.tsx +1 -0
- package/src/lib/Layouts/LayoutGrid/examples.tsx +7 -1
- package/src/lib/Meta/Best Practices.mdx +5 -8
- package/src/lib/Molecules/Tips/TipsTable.tsx +2 -2
- package/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx +1 -0
- package/src/lib/Organisms/ConnectedForm/ConnectedFormInputs/ConnectedFormInputsTable.tsx +1 -1
- package/src/lib/Organisms/Lists & Tables/List/List.stories.tsx +3 -3
- package/src/lib/Molecules/DatePicker/Calendar.mdx +0 -26
- package/src/lib/Molecules/DatePicker/Calendar.stories.tsx +0 -60
- package/src/lib/Molecules/DatePicker/DatePicker.stories.tsx +0 -148
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.2-alpha.
|
|
6
|
+
### [79.2.2-alpha.425c3f.0](https://github.com/Codecademy/gamut/compare/@codecademy/styleguide@79.2.1...@codecademy/styleguide@79.2.2-alpha.425c3f.0) (2026-03-25)
|
|
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.2-alpha.
|
|
4
|
+
"version": "79.2.2-alpha.425c3f.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": "5793cabbe51a529723de64c2ec9bf25f37d95005"
|
|
12
12
|
}
|
|
@@ -136,10 +136,7 @@ Some of our forms require special props be passed directly onto the input compon
|
|
|
136
136
|
- `hidden`: Props passed to the hidden input element (used for form submission)
|
|
137
137
|
- `combobox`: Props passed to the visible react-select input element (useful for data-\* attributes, testing, etc.)
|
|
138
138
|
|
|
139
|
-
<Callout
|
|
140
|
-
text=" These props are passed directly to the underlying elements, so they only
|
|
141
|
-
accept `data-*` and `aria-*` attributes to ensure validity."
|
|
142
|
-
/>
|
|
139
|
+
<Callout text="These props are passed directly to the underlying elements, so they only accept data-* and aria-* attributes to ensure validity." />
|
|
143
140
|
|
|
144
141
|
<Canvas of={SelectDropdownStories.CustomInputProps} />
|
|
145
142
|
|
|
@@ -75,7 +75,7 @@ Addition pixel offset from center in the direction of the alignment (e.g. top-le
|
|
|
75
75
|
|
|
76
76
|
### Individual axis offsets `x` and `y`
|
|
77
77
|
|
|
78
|
-
Absolute offset values irrespective of the relative position. (e.g. x={-4} will be 4 pixels to the left in every position unlike offset).
|
|
78
|
+
Absolute offset values irrespective of the relative position. (e.g. `x={-4}` will be 4 pixels to the left in every position unlike offset).
|
|
79
79
|
|
|
80
80
|
<Canvas of={PopoverContainerStories.XandY} />
|
|
81
81
|
|
|
@@ -24,7 +24,7 @@ export const parameters = {
|
|
|
24
24
|
|
|
25
25
|
Use `DelayedRenderWrapper` to wrap around a component that you want to delay rendering for a specified amount of time.
|
|
26
26
|
|
|
27
|
-
The `delay` prop accepts a number in milliseconds. If a `delay`
|
|
27
|
+
The `delay` prop accepts a number in milliseconds. If a `delay` value greater than 0 is provided, `DelayedRenderWrapper` will use a `setTimeout()` to determine when to render its children. If `delay` is 0 or not provided, it will render its children immediately.
|
|
28
28
|
|
|
29
29
|
## Playground
|
|
30
30
|
|
|
@@ -154,6 +154,7 @@ For spacing between components and sections use these as a guide. Each of these
|
|
|
154
154
|
>
|
|
155
155
|
{sizes.map((size) => (
|
|
156
156
|
<Box
|
|
157
|
+
key={`box-${size}`}
|
|
157
158
|
width={`${size}px`}
|
|
158
159
|
height={`${size}px`}
|
|
159
160
|
display="inline-block"
|
|
@@ -161,7 +162,7 @@ For spacing between components and sections use these as a guide. Each of these
|
|
|
161
162
|
/>
|
|
162
163
|
))}
|
|
163
164
|
{sizes.map((size) => (
|
|
164
|
-
<Box textAlign="center" fontSize={14}>
|
|
165
|
+
<Box key={`label-${size}`} textAlign="center" fontSize={14}>
|
|
165
166
|
{size}
|
|
166
167
|
</Box>
|
|
167
168
|
))}
|
|
@@ -499,6 +499,7 @@ export const defaultColumns = [
|
|
|
499
499
|
];
|
|
500
500
|
|
|
501
501
|
export const getPropRows = (key: keyof typeof ALL_PROPS) =>
|
|
502
|
+
// eslint-disable-next-line import/namespace -- dynamic keyof on namespace import
|
|
502
503
|
Object.entries(ALL_PROPS[key]).map(([prop, config]) => ({
|
|
503
504
|
id: prop,
|
|
504
505
|
...config,
|
|
@@ -50,7 +50,13 @@ export const renderColumnChildren = (
|
|
|
50
50
|
{...props}
|
|
51
51
|
rowspan={span ? span[i] : undefined}
|
|
52
52
|
>
|
|
53
|
-
<Example>
|
|
53
|
+
<Example>
|
|
54
|
+
{props?.size !== undefined &&
|
|
55
|
+
props.size !== null &&
|
|
56
|
+
(typeof props.size === 'string' || typeof props.size === 'number')
|
|
57
|
+
? String(props.size)
|
|
58
|
+
: ''}
|
|
59
|
+
</Example>
|
|
54
60
|
</Column>
|
|
55
61
|
));
|
|
56
62
|
};
|
|
@@ -153,12 +153,12 @@ type BreakpointArray<T> = [
|
|
|
153
153
|
T?, // sm
|
|
154
154
|
T?, // md
|
|
155
155
|
T?, // lg
|
|
156
|
-
T
|
|
156
|
+
T?, // xl
|
|
157
157
|
T?, // c_xs
|
|
158
158
|
T?, // c_sm
|
|
159
159
|
T?, // c_md
|
|
160
160
|
T?, // c_lg
|
|
161
|
-
T
|
|
161
|
+
T?, // c_xl
|
|
162
162
|
];
|
|
163
163
|
|
|
164
164
|
type SystemProp<T> = T | BreakpointMap<T> | BreakpointArray<T>;
|
|
@@ -170,16 +170,13 @@ type SystemProp<T> = T | BreakpointMap<T> | BreakpointArray<T>;
|
|
|
170
170
|
import { Box } from '@codecademy/gamut';
|
|
171
171
|
|
|
172
172
|
// Object Syntax
|
|
173
|
-
<Box width={{ _:
|
|
173
|
+
<Box width={{ _: '100%', sm: '50%' }} />
|
|
174
174
|
|
|
175
175
|
// Array Syntax
|
|
176
|
-
<Box width={[
|
|
176
|
+
<Box width={['100%', , '50%']} />
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
<Callout
|
|
180
|
-
text="If you wish to skip a breakpoint in using the
|
|
181
|
-
array shorthand you may specify undefined at the index."
|
|
182
|
-
/>
|
|
179
|
+
<Callout text="If you wish to skip a breakpoint when using the array shorthand you may specify undefined at the index." />
|
|
183
180
|
|
|
184
181
|
## Real-world use cases
|
|
185
182
|
|
|
@@ -77,7 +77,7 @@ const ComponentRow = ({ array }: { array: typeof colTitles }) => {
|
|
|
77
77
|
const badgeVariant = status === 'New' ? 'accent' : 'tertiary';
|
|
78
78
|
|
|
79
79
|
return (
|
|
80
|
-
<BorderRow size="xl">
|
|
80
|
+
<BorderRow key={title} size="xl">
|
|
81
81
|
<FlexBox alignItems="center" flexWrap="wrap" pl={8}>
|
|
82
82
|
<Text mr={8} variant="title-sm">
|
|
83
83
|
{!skipTitle && title} {component}
|
|
@@ -110,7 +110,7 @@ const FeatureRow = ({
|
|
|
110
110
|
<Text fontWeight="bold">{title}</Text>
|
|
111
111
|
</ListCol>
|
|
112
112
|
{features.map((details) => (
|
|
113
|
-
<DetailRow size="xl">
|
|
113
|
+
<DetailRow key={details} size="xl">
|
|
114
114
|
<Text>{details}</Text>
|
|
115
115
|
</DetailRow>
|
|
116
116
|
))}
|
|
@@ -65,7 +65,7 @@ const ListExample: React.FC = (args) => {
|
|
|
65
65
|
return (
|
|
66
66
|
<List {...args}>
|
|
67
67
|
{rows.map(({ name, ship }) => (
|
|
68
|
-
<ListRow>
|
|
68
|
+
<ListRow key={name}>
|
|
69
69
|
<ListCol size="md" type="header">
|
|
70
70
|
{name}
|
|
71
71
|
</ListCol>
|
|
@@ -157,7 +157,7 @@ const ListCardExample: React.FC = (args) => {
|
|
|
157
157
|
return (
|
|
158
158
|
<List {...args}>
|
|
159
159
|
{rows.map(({ name, ship, role }) => (
|
|
160
|
-
<ListRow>
|
|
160
|
+
<ListRow key={name}>
|
|
161
161
|
<ListCol fill>
|
|
162
162
|
<Text truncate="ellipsis" truncateLines={1} variant="title-lg">
|
|
163
163
|
{name}
|
|
@@ -218,7 +218,7 @@ const ColumnExample: React.FC<ListProps> = (args) => {
|
|
|
218
218
|
return (
|
|
219
219
|
<List {...args}>
|
|
220
220
|
{sizes.map((size: 'content' | 'sm' | 'md' | 'lg' | 'xl') => (
|
|
221
|
-
<ListRow>
|
|
221
|
+
<ListRow key={size}>
|
|
222
222
|
<ListCol size={size}>
|
|
223
223
|
<Box bg="background-selected" flex={1} height={1} p={8}>
|
|
224
224
|
{size}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Canvas, Controls, Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import { ComponentHeader } from '~styleguide/blocks';
|
|
4
|
-
|
|
5
|
-
import * as CalendarStories from './Calendar.stories';
|
|
6
|
-
|
|
7
|
-
export const parameters = {
|
|
8
|
-
title: 'DatePicker/Calendar',
|
|
9
|
-
subtitle: `Calendar grid with header (month/year + prev/next), body (day grid), and footer (Clear, Today, quick actions). Used inside DatePickerCalendar.`,
|
|
10
|
-
status: 'current',
|
|
11
|
-
source: {
|
|
12
|
-
repo: 'gamut',
|
|
13
|
-
githubLink:
|
|
14
|
-
'https://github.com/Codecademy/gamut/blob/main/packages/gamut/src/DatePicker/Calendar',
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
<Meta of={CalendarStories} />
|
|
19
|
-
|
|
20
|
-
<ComponentHeader {...parameters} />
|
|
21
|
-
|
|
22
|
-
## Playground
|
|
23
|
-
|
|
24
|
-
<Canvas sourceState="shown" of={CalendarStories.Default} />
|
|
25
|
-
|
|
26
|
-
<Controls />
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Box,
|
|
3
|
-
Calendar,
|
|
4
|
-
CalendarBody,
|
|
5
|
-
CalendarFooter,
|
|
6
|
-
CalendarHeader,
|
|
7
|
-
} from '@codecademy/gamut';
|
|
8
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
9
|
-
import { useId, useState } from 'react';
|
|
10
|
-
|
|
11
|
-
const meta: Meta<typeof Calendar> = {
|
|
12
|
-
component: Calendar,
|
|
13
|
-
title: 'Molecules/DatePicker/Calendar',
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default meta;
|
|
17
|
-
|
|
18
|
-
type Story = StoryObj<typeof Calendar>;
|
|
19
|
-
|
|
20
|
-
export const Default: Story = {
|
|
21
|
-
render: function CalendarStory() {
|
|
22
|
-
const headingId = useId();
|
|
23
|
-
const [displayDate, setDisplayDate] = useState(() => new Date());
|
|
24
|
-
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
|
|
25
|
-
const [focusedDate, setFocusedDate] = useState<Date | null>(
|
|
26
|
-
() => new Date()
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Calendar>
|
|
31
|
-
<Box p={24}>
|
|
32
|
-
<CalendarHeader
|
|
33
|
-
displayDate={displayDate}
|
|
34
|
-
headingId={headingId}
|
|
35
|
-
onDisplayDateChange={setDisplayDate}
|
|
36
|
-
/>
|
|
37
|
-
<CalendarBody
|
|
38
|
-
displayDate={displayDate}
|
|
39
|
-
focusedDate={focusedDate}
|
|
40
|
-
labelledById={headingId}
|
|
41
|
-
selectedDate={selectedDate}
|
|
42
|
-
onDateSelect={setSelectedDate}
|
|
43
|
-
onDisplayDateChange={setDisplayDate}
|
|
44
|
-
onFocusedDateChange={setFocusedDate}
|
|
45
|
-
/>
|
|
46
|
-
</Box>
|
|
47
|
-
<CalendarFooter
|
|
48
|
-
showClearButton
|
|
49
|
-
onClearDate={() => setSelectedDate(null)}
|
|
50
|
-
onTodayClick={() => {
|
|
51
|
-
const today = new Date();
|
|
52
|
-
setSelectedDate(today);
|
|
53
|
-
setDisplayDate(today);
|
|
54
|
-
setFocusedDate(today);
|
|
55
|
-
}}
|
|
56
|
-
/>
|
|
57
|
-
</Calendar>
|
|
58
|
-
);
|
|
59
|
-
},
|
|
60
|
-
};
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Box,
|
|
3
|
-
DatePicker,
|
|
4
|
-
DatePickerCalendar,
|
|
5
|
-
DatePickerInput,
|
|
6
|
-
PopoverContainer,
|
|
7
|
-
useDatePicker,
|
|
8
|
-
} from '@codecademy/gamut';
|
|
9
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
10
|
-
import { useRef, useState } from 'react';
|
|
11
|
-
|
|
12
|
-
const meta: Meta<typeof DatePicker> = {
|
|
13
|
-
component: DatePicker,
|
|
14
|
-
title: 'Molecules/DatePicker/DatePicker',
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export default meta;
|
|
18
|
-
|
|
19
|
-
type Story = StoryObj<typeof DatePicker>;
|
|
20
|
-
|
|
21
|
-
export const Default: Story = {
|
|
22
|
-
render: function DatePickerStory() {
|
|
23
|
-
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
|
|
24
|
-
return (
|
|
25
|
-
<Box>
|
|
26
|
-
<DatePicker
|
|
27
|
-
label="Date"
|
|
28
|
-
locale="de-DE"
|
|
29
|
-
selectedDate={selectedDate}
|
|
30
|
-
setSelectedDate={setSelectedDate}
|
|
31
|
-
translations={{ clearText: 'Löschen' }}
|
|
32
|
-
/>
|
|
33
|
-
</Box>
|
|
34
|
-
);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export const WithInitialDate: Story = {
|
|
39
|
-
render: function DatePickerStory() {
|
|
40
|
-
const [selectedDate, setSelectedDate] = useState<Date | null>(
|
|
41
|
-
() => new Date(2026, 1, 15)
|
|
42
|
-
);
|
|
43
|
-
return (
|
|
44
|
-
<DatePicker
|
|
45
|
-
inputSize="small"
|
|
46
|
-
label="Date"
|
|
47
|
-
selectedDate={selectedDate}
|
|
48
|
-
setSelectedDate={setSelectedDate}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/** Range mode: two inputs for start and end date. First calendar click sets start, second sets end. */
|
|
55
|
-
export const Range: Story = {
|
|
56
|
-
render: function DatePickerStory() {
|
|
57
|
-
const [startDate, setStartDate] = useState<Date | null>(null);
|
|
58
|
-
const [endDate, setEndDate] = useState<Date | null>(null);
|
|
59
|
-
return (
|
|
60
|
-
<Box>
|
|
61
|
-
<DatePicker
|
|
62
|
-
disabledDates={[new Date(2026, 3, 15)]}
|
|
63
|
-
endDate={endDate}
|
|
64
|
-
mode="range"
|
|
65
|
-
setEndDate={setEndDate}
|
|
66
|
-
setStartDate={setStartDate}
|
|
67
|
-
startDate={startDate}
|
|
68
|
-
translations={{
|
|
69
|
-
startDateLabel: 'Beginning date',
|
|
70
|
-
}}
|
|
71
|
-
/>
|
|
72
|
-
</Box>
|
|
73
|
-
);
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export const RangeSmall: Story = {
|
|
78
|
-
render: function DatePickerStory() {
|
|
79
|
-
const [startDate, setStartDate] = useState<Date | null>(null);
|
|
80
|
-
const [endDate, setEndDate] = useState<Date | null>(null);
|
|
81
|
-
return (
|
|
82
|
-
<Box>
|
|
83
|
-
<DatePicker
|
|
84
|
-
disabledDates={[new Date(2026, 3, 15)]}
|
|
85
|
-
endDate={endDate}
|
|
86
|
-
inputSize="small"
|
|
87
|
-
mode="range"
|
|
88
|
-
setEndDate={setEndDate}
|
|
89
|
-
setStartDate={setStartDate}
|
|
90
|
-
startDate={startDate}
|
|
91
|
-
translations={{
|
|
92
|
-
startDateLabel: 'Beginning date',
|
|
93
|
-
}}
|
|
94
|
-
/>
|
|
95
|
-
</Box>
|
|
96
|
-
);
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Composed usage: DatePicker with children provides shared state via context.
|
|
102
|
-
* The child uses useDatePicker() to get open/close and inputRef, then composes
|
|
103
|
-
* DatePickerInput and DatePickerCalendar with a custom PopoverContainer layout.
|
|
104
|
-
*/
|
|
105
|
-
export const ComposedWithContext: Story = {
|
|
106
|
-
render: function DatePickerStory() {
|
|
107
|
-
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
|
|
108
|
-
return (
|
|
109
|
-
<Box p={32}>
|
|
110
|
-
<DatePicker
|
|
111
|
-
label="Start date"
|
|
112
|
-
selectedDate={selectedDate}
|
|
113
|
-
setSelectedDate={setSelectedDate}
|
|
114
|
-
>
|
|
115
|
-
<ComposedDatePickerLayout />
|
|
116
|
-
</DatePicker>
|
|
117
|
-
</Box>
|
|
118
|
-
);
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
function ComposedDatePickerLayout() {
|
|
123
|
-
const { isCalendarOpen, openCalendar, closeCalendar, calendarDialogId } =
|
|
124
|
-
useDatePicker();
|
|
125
|
-
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<>
|
|
129
|
-
<Box width="fit-content" onClick={openCalendar}>
|
|
130
|
-
<DatePickerInput ref={inputRef} />
|
|
131
|
-
</Box>
|
|
132
|
-
<PopoverContainer
|
|
133
|
-
alignment="bottom-left"
|
|
134
|
-
allowPageInteraction
|
|
135
|
-
focusOnProps={{ autoFocus: false, focusLock: false }}
|
|
136
|
-
invertAxis="x"
|
|
137
|
-
isOpen={isCalendarOpen}
|
|
138
|
-
offset={10}
|
|
139
|
-
targetRef={inputRef}
|
|
140
|
-
onRequestClose={closeCalendar}
|
|
141
|
-
>
|
|
142
|
-
<div aria-label="Choose date" id={calendarDialogId} role="dialog">
|
|
143
|
-
<DatePickerCalendar dialogId={calendarDialogId} />
|
|
144
|
-
</div>
|
|
145
|
-
</PopoverContainer>
|
|
146
|
-
</>
|
|
147
|
-
);
|
|
148
|
-
}
|