@codecademy/styleguide 79.2.4-alpha.38d1e4.0 → 79.2.4-alpha.9ce37a.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/ImageWrapper.tsx +4 -2
- package/.storybook/preview.ts +2 -22
- package/CHANGELOG.md +1 -1
- package/package.json +2 -2
- package/src/lib/Meta/About.mdx +5 -5
- package/src/lib/Meta/{Best practices.mdx → Best Practices.mdx } +3 -3
- package/src/lib/Meta/{Gamut writing guide/Stories/Component story documentation.mdx → Stories.mdx} +85 -19
- package/src/lib/Meta/{Usage guide.mdx → Usage Guide.mdx } +3 -3
- package/src/lib/Molecules/Tips/InfoTip/InfoTip.mdx +1 -1
- package/src/lib/Organisms/BarChart/BarChart.mdx +463 -0
- package/src/lib/Organisms/BarChart/BarChart.stories.tsx +352 -0
- package/src/static/organisms/barchart.png +0 -0
- package/src/lib/Meta/Gamut writing guide/About.mdx +0 -43
- package/src/lib/Meta/Gamut writing guide/Documentation in code.mdx +0 -134
- package/src/lib/Meta/Gamut writing guide/Formatting.mdx +0 -69
- package/src/lib/Meta/Gamut writing guide/General principles.mdx +0 -46
- package/src/lib/Meta/Gamut writing guide/Language and grammar.mdx +0 -54
- package/src/lib/Meta/Gamut writing guide/Linking.mdx +0 -60
- package/src/lib/Meta/Gamut writing guide/Referencing code.mdx +0 -86
- package/src/lib/Meta/Gamut writing guide/Stories/About pages.mdx +0 -49
- package/src/lib/Meta/Gamut writing guide/Stories/About.mdx +0 -57
- package/src/lib/Meta/Gamut writing guide/Stories/Component code examples.mdx +0 -79
- /package/src/lib/Meta/{Deep Controls add-on.mdx → Deep Controls Add-On.mdx} +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BarChart,
|
|
3
|
+
BarProps,
|
|
4
|
+
Box,
|
|
5
|
+
PartialBarChartTranslations,
|
|
6
|
+
} from '@codecademy/gamut';
|
|
7
|
+
import {
|
|
8
|
+
BookFlipPageIcon,
|
|
9
|
+
DataScienceIcon,
|
|
10
|
+
TerminalIcon,
|
|
11
|
+
} from '@codecademy/gamut-icons';
|
|
12
|
+
import { action } from '@storybook/addon-actions';
|
|
13
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
14
|
+
|
|
15
|
+
const meta: Meta<typeof BarChart> = {
|
|
16
|
+
component: BarChart,
|
|
17
|
+
args: {
|
|
18
|
+
description: 'Chart showing programming language experience levels',
|
|
19
|
+
maxScaleValue: 2000,
|
|
20
|
+
title: 'Skills experience chart',
|
|
21
|
+
unit: 'XP',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof BarChart>;
|
|
27
|
+
|
|
28
|
+
const simpleBarData: BarProps[] = [
|
|
29
|
+
{ categoryLabel: 'Python', seriesOneValue: 1500 },
|
|
30
|
+
{ categoryLabel: 'JavaScript', seriesOneValue: 2000 },
|
|
31
|
+
{ categoryLabel: 'HTML/CSS', seriesOneValue: 800 },
|
|
32
|
+
{ categoryLabel: 'SQL', seriesOneValue: 600 },
|
|
33
|
+
{ categoryLabel: 'React', seriesOneValue: 450 },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const stackedBarData: BarProps[] = [
|
|
37
|
+
{ categoryLabel: 'Python', seriesOneValue: 200, seriesTwoValue: 1500 },
|
|
38
|
+
{
|
|
39
|
+
categoryLabel: 'JavaScript',
|
|
40
|
+
icon: TerminalIcon,
|
|
41
|
+
seriesOneValue: 1800,
|
|
42
|
+
seriesTwoValue: 2000,
|
|
43
|
+
},
|
|
44
|
+
{ categoryLabel: 'HTML/CSS', seriesOneValue: 600, seriesTwoValue: 800 },
|
|
45
|
+
{ categoryLabel: 'SQL', seriesOneValue: 550, seriesTwoValue: 600 },
|
|
46
|
+
{ categoryLabel: 'React', seriesOneValue: 300, seriesTwoValue: 450 },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
const accessibilityBarData: BarProps[] = [
|
|
50
|
+
{ categoryLabel: 'Python', seriesOneValue: 200, seriesTwoValue: 1500 },
|
|
51
|
+
{
|
|
52
|
+
categoryLabel: 'JavaScript',
|
|
53
|
+
seriesOneValue: 1800,
|
|
54
|
+
seriesTwoValue: 2000,
|
|
55
|
+
href: '/javascript',
|
|
56
|
+
},
|
|
57
|
+
{ categoryLabel: 'HTML/CSS', seriesOneValue: 600, seriesTwoValue: 800 },
|
|
58
|
+
{ categoryLabel: 'SQL', seriesOneValue: 550, href: '/sql' },
|
|
59
|
+
{ categoryLabel: 'Rust', seriesOneValue: 400 },
|
|
60
|
+
{ categoryLabel: 'React', seriesOneValue: 300, seriesTwoValue: 450 },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const accessibilityTranslations: PartialBarChartTranslations = {
|
|
64
|
+
accessibility: {
|
|
65
|
+
stackedBarSummary: (ctx) =>
|
|
66
|
+
`${ctx.seriesOneValue} ${ctx.unit} gained — now at ${ctx.seriesTwoValue} ${ctx.unit} in ${ctx.categoryLabel}`,
|
|
67
|
+
singleValueBarSummary: (ctx) =>
|
|
68
|
+
`${ctx.value} ${ctx.unit} in ${ctx.categoryLabel}`,
|
|
69
|
+
},
|
|
70
|
+
locale: 'en',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const barDataWithIcons: BarProps[] = [
|
|
74
|
+
{
|
|
75
|
+
categoryLabel: 'Python',
|
|
76
|
+
seriesOneValue: 200,
|
|
77
|
+
seriesTwoValue: 1500,
|
|
78
|
+
icon: TerminalIcon,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
categoryLabel: 'JavaScript',
|
|
82
|
+
seriesOneValue: 150,
|
|
83
|
+
seriesTwoValue: 2000,
|
|
84
|
+
icon: TerminalIcon,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
categoryLabel: 'Data Science',
|
|
88
|
+
seriesOneValue: 100,
|
|
89
|
+
seriesTwoValue: 800,
|
|
90
|
+
icon: DataScienceIcon,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
categoryLabel: 'Backend',
|
|
94
|
+
seriesOneValue: 50,
|
|
95
|
+
seriesTwoValue: 600,
|
|
96
|
+
icon: TerminalIcon,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
categoryLabel: 'Reading',
|
|
100
|
+
seriesOneValue: 75,
|
|
101
|
+
seriesTwoValue: 450,
|
|
102
|
+
icon: BookFlipPageIcon,
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
export const Default: Story = {
|
|
107
|
+
args: {
|
|
108
|
+
barValues: simpleBarData,
|
|
109
|
+
title: 'Skills experience chart',
|
|
110
|
+
description: 'Chart showing programming language experience levels',
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const Stacked: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
barValues: stackedBarData,
|
|
117
|
+
title: 'Skills progress chart',
|
|
118
|
+
description: 'Progress toward total goals for each programming language',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const WithIcons: Story = {
|
|
123
|
+
args: {
|
|
124
|
+
barValues: barDataWithIcons,
|
|
125
|
+
title: 'Skills progress with icons',
|
|
126
|
+
description: 'Skills progress with visual icons for each category',
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const Animated: Story = {
|
|
131
|
+
args: {
|
|
132
|
+
barValues: stackedBarData,
|
|
133
|
+
animate: true,
|
|
134
|
+
title: 'Animated skills chart',
|
|
135
|
+
description: 'Animated chart showing progress with entrance animations',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const Interactive: Story = {
|
|
140
|
+
args: {
|
|
141
|
+
barValues: simpleBarData.map((bar) => ({
|
|
142
|
+
...bar,
|
|
143
|
+
onClick: action(`Clicked ${bar.categoryLabel}`),
|
|
144
|
+
})),
|
|
145
|
+
title: 'Interactive skills chart',
|
|
146
|
+
description: 'Click on any row to view detailed course information',
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const WithLinks: Story = {
|
|
151
|
+
args: {
|
|
152
|
+
barValues: simpleBarData.map((bar) => ({
|
|
153
|
+
...bar,
|
|
154
|
+
href: `#${bar.categoryLabel.toLowerCase().replace(/\s+/g, '-')}`,
|
|
155
|
+
})),
|
|
156
|
+
title: 'Skills chart with links',
|
|
157
|
+
description: 'Each row links to its corresponding course page',
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const WithVisualTitleAndDescription: Story = {
|
|
162
|
+
args: {
|
|
163
|
+
barValues: simpleBarData,
|
|
164
|
+
title: 'Programming Skills Overview',
|
|
165
|
+
description:
|
|
166
|
+
'Experience points earned across different programming languages',
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export const WithHiddenTitleAndDescription: Story = {
|
|
171
|
+
render: () => {
|
|
172
|
+
return (
|
|
173
|
+
<BarChart
|
|
174
|
+
barValues={simpleBarData}
|
|
175
|
+
description="Experience points earned across different programming languages"
|
|
176
|
+
hideDescription
|
|
177
|
+
hideTitle
|
|
178
|
+
maxScaleValue={2000}
|
|
179
|
+
title="Programming Skills Overview"
|
|
180
|
+
unit="XP"
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const WithExternalTitle: Story = {
|
|
187
|
+
render: () => {
|
|
188
|
+
return (
|
|
189
|
+
<>
|
|
190
|
+
<Box
|
|
191
|
+
as="h2"
|
|
192
|
+
bg="background-selected"
|
|
193
|
+
border={1}
|
|
194
|
+
borderRadius="lg"
|
|
195
|
+
id="external-chart-title"
|
|
196
|
+
p={16}
|
|
197
|
+
textAlign="right"
|
|
198
|
+
>
|
|
199
|
+
Programming Skills Overview
|
|
200
|
+
</Box>
|
|
201
|
+
<BarChart
|
|
202
|
+
aria-labelledby="external-chart-title"
|
|
203
|
+
barValues={simpleBarData}
|
|
204
|
+
description="Experience points earned across different programming languages"
|
|
205
|
+
hideDescription={false}
|
|
206
|
+
maxScaleValue={2000}
|
|
207
|
+
unit="XP"
|
|
208
|
+
/>
|
|
209
|
+
</>
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export const WithSorting: Story = {
|
|
215
|
+
args: {
|
|
216
|
+
barValues: simpleBarData,
|
|
217
|
+
sortFns: ['alphabetically', 'numerically', 'none'],
|
|
218
|
+
title: 'Skills experience chart',
|
|
219
|
+
description: 'Use the dropdown to sort bars by different criteria',
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const customSortingBarValues = [
|
|
224
|
+
{
|
|
225
|
+
categoryLabel: 'Python',
|
|
226
|
+
seriesOneValue: 1500,
|
|
227
|
+
dateAdded: new Date('2023-01-15'),
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
categoryLabel: 'JavaScript',
|
|
231
|
+
seriesOneValue: 2000,
|
|
232
|
+
dateAdded: new Date('2023-03-20'),
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
categoryLabel: 'React',
|
|
236
|
+
seriesOneValue: 450,
|
|
237
|
+
dateAdded: new Date('2023-06-10'),
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
categoryLabel: 'TypeScript',
|
|
241
|
+
seriesOneValue: 300,
|
|
242
|
+
dateAdded: new Date('2023-08-05'),
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
categoryLabel: 'SQL',
|
|
246
|
+
seriesOneValue: 600,
|
|
247
|
+
dateAdded: new Date('2023-02-28'),
|
|
248
|
+
},
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
export const WithCustomSorting: Story = {
|
|
252
|
+
args: {
|
|
253
|
+
barValues: customSortingBarValues,
|
|
254
|
+
sortFns: [
|
|
255
|
+
'none',
|
|
256
|
+
{
|
|
257
|
+
label: 'Recently Added',
|
|
258
|
+
value: 'recent',
|
|
259
|
+
sortFn: (bars) => {
|
|
260
|
+
return [...bars].sort((a, b) => {
|
|
261
|
+
const aDate = a.dateAdded as Date | undefined;
|
|
262
|
+
const bDate = b.dateAdded as Date | undefined;
|
|
263
|
+
if (!aDate && !bDate) return 0;
|
|
264
|
+
if (!aDate) return 1;
|
|
265
|
+
if (!bDate) return -1;
|
|
266
|
+
return bDate.getTime() - aDate.getTime();
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
label: 'Oldest First',
|
|
272
|
+
value: 'oldest',
|
|
273
|
+
sortFn: (bars) => {
|
|
274
|
+
return [...bars].sort((a, b) => {
|
|
275
|
+
const aDate = a.dateAdded as Date | undefined;
|
|
276
|
+
const bDate = b.dateAdded as Date | undefined;
|
|
277
|
+
if (!aDate && !bDate) return 0;
|
|
278
|
+
if (!aDate) return 1;
|
|
279
|
+
if (!bDate) return -1;
|
|
280
|
+
return aDate.getTime() - bDate.getTime();
|
|
281
|
+
});
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
title: 'Skills chart with date sorting',
|
|
286
|
+
description:
|
|
287
|
+
'Custom sort functions can access additional properties on BarProps, such as dates',
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export const CustomStyles: Story = {
|
|
292
|
+
args: {
|
|
293
|
+
barValues: stackedBarData,
|
|
294
|
+
styleConfig: {
|
|
295
|
+
seriesTwoBarColor: 'text',
|
|
296
|
+
seriesOneBarColor: 'primary',
|
|
297
|
+
textColor: 'primary',
|
|
298
|
+
seriesOneLabel: 'feedback-error',
|
|
299
|
+
seriesTwoLabel: 'feedback-success',
|
|
300
|
+
},
|
|
301
|
+
title: 'Custom styled skills chart',
|
|
302
|
+
description: 'Custom color scheme applied to chart elements',
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
export const CustomScale: Story = {
|
|
307
|
+
args: {
|
|
308
|
+
barValues: simpleBarData,
|
|
309
|
+
maxScaleValue: 2000,
|
|
310
|
+
scaleInterval: 250,
|
|
311
|
+
title: 'Skills chart with custom scale',
|
|
312
|
+
description: 'Custom scale intervals for more granular value display',
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export const WithStringTranslations: Story = {
|
|
317
|
+
args: {
|
|
318
|
+
barValues: stackedBarData,
|
|
319
|
+
sortFns: ['alphabetically', 'numerically', 'none'],
|
|
320
|
+
title: 'Gráfico de habilidades',
|
|
321
|
+
description: 'Progreso hacia los objetivos totales por lenguaje',
|
|
322
|
+
unit: 'XP',
|
|
323
|
+
translations: {
|
|
324
|
+
locale: 'es',
|
|
325
|
+
sortLabel: 'Ordenar por:',
|
|
326
|
+
sortOptions: {
|
|
327
|
+
none: 'Ninguno',
|
|
328
|
+
labelAsc: 'Etiqueta (A-Z)',
|
|
329
|
+
labelDesc: 'Etiqueta (Z-A)',
|
|
330
|
+
valueAsc: 'Valor (Bajo-Alto)',
|
|
331
|
+
valueDesc: 'Valor (Alto-Bajo)',
|
|
332
|
+
},
|
|
333
|
+
accessibility: {
|
|
334
|
+
stackedBarSummary: (ctx) =>
|
|
335
|
+
`Valor inicial - ${ctx.seriesOneValue} ${ctx.unit}. ${ctx.gained} ${ctx.unit} ganado - ahora en ${ctx.seriesTwoValue} ${ctx.unit} en ${ctx.categoryLabel}`,
|
|
336
|
+
singleValueBarSummary: (ctx) =>
|
|
337
|
+
`${ctx.value} ${ctx.unit} en ${ctx.categoryLabel}`,
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
export const WithFunctionTranslations: Story = {
|
|
344
|
+
args: {
|
|
345
|
+
barValues: accessibilityBarData,
|
|
346
|
+
description:
|
|
347
|
+
'Custom aria-label summaries via translation functions (stacked, link, and non-interactive bars)',
|
|
348
|
+
title: 'Skills experience (accessibility functions)',
|
|
349
|
+
translations: accessibilityTranslations,
|
|
350
|
+
unit: 'XP',
|
|
351
|
+
},
|
|
352
|
+
};
|
|
Binary file
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
AboutHeader,
|
|
5
|
-
addParentPath,
|
|
6
|
-
LinkTo,
|
|
7
|
-
TableOfContents,
|
|
8
|
-
} from '~styleguide/blocks';
|
|
9
|
-
|
|
10
|
-
import { parameters as documentationInCodeParameters } from './Documentation in code.mdx';
|
|
11
|
-
import { parameters as formattingParameters } from './Formatting.mdx';
|
|
12
|
-
import { parameters as generalPrinciplesParameters } from './General principles.mdx';
|
|
13
|
-
import { parameters as languageAndGrammarParameters } from './Language and grammar.mdx';
|
|
14
|
-
import { parameters as linkingParameters } from './Linking.mdx';
|
|
15
|
-
import { parameters as referencingCodeParameters } from './Referencing code.mdx';
|
|
16
|
-
import { parameters as storiesParameters } from './Stories/About.mdx';
|
|
17
|
-
|
|
18
|
-
export const parameters = {
|
|
19
|
-
id: 'Meta/Gamut writing guide',
|
|
20
|
-
title: 'Gamut writing guide',
|
|
21
|
-
subtitle:
|
|
22
|
-
'Guidelines and standards for creating consistent, clear, and effective documentation.',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
<Meta title="Meta/Gamut writing guide/About" />
|
|
26
|
-
|
|
27
|
-
<AboutHeader {...parameters} />
|
|
28
|
-
|
|
29
|
-
Welcome to the Gamut writing guide! Thanks for taking the time to learn about our documentation standards. This guide helps keep our documentation clear, consistent, and useful across the Gamut design system.
|
|
30
|
-
|
|
31
|
-
The <LinkTo id="Meta/Gamut writing guide/General principles">General principles</LinkTo> is a great place to get an overview of our documentation philosophy and best practices. For specific topics like formatting, code documentation, or writing Storybook stories, check out the other pages below.
|
|
32
|
-
|
|
33
|
-
<TableOfContents
|
|
34
|
-
links={addParentPath(parameters.id, [
|
|
35
|
-
generalPrinciplesParameters,
|
|
36
|
-
documentationInCodeParameters,
|
|
37
|
-
formattingParameters,
|
|
38
|
-
languageAndGrammarParameters,
|
|
39
|
-
linkingParameters,
|
|
40
|
-
referencingCodeParameters,
|
|
41
|
-
storiesParameters,
|
|
42
|
-
])}
|
|
43
|
-
/>
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import { AboutHeader } from '~styleguide/blocks';
|
|
4
|
-
|
|
5
|
-
export const parameters = {
|
|
6
|
-
title: 'Documentation in code',
|
|
7
|
-
subtitle: `Guidelines for documenting code in Gamut component files`,
|
|
8
|
-
status: 'static',
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
<Meta title="Meta/Gamut writing guide/Documentation in code" />
|
|
12
|
-
|
|
13
|
-
<AboutHeader {...parameters} />
|
|
14
|
-
|
|
15
|
-
Good documentation starts in the code itself. By documenting components, props, and functions directly in source files, we create a single source of truth that stays synchronized with the implementation and surfaces automatically in developer tools and Storybook.
|
|
16
|
-
|
|
17
|
-
## Naming conventions
|
|
18
|
-
|
|
19
|
-
Clear, descriptive names reduce the need for comments and make code self-documenting. Choose names that reveal intent and follow established patterns.
|
|
20
|
-
|
|
21
|
-
### Variables and constants
|
|
22
|
-
|
|
23
|
-
- Use `camelCase` for variables: `userName`, `isLoading`, `itemCount`
|
|
24
|
-
- Use descriptive names that reveal purpose: `filteredResults` not `arr`
|
|
25
|
-
- Boolean variables should use `is`, `has`, `should`, or `can` prefixes: `isVisible`, `hasError`, `shouldRender`
|
|
26
|
-
- Use `SCREAMING_SNAKE_CASE` for true constants: `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT`
|
|
27
|
-
- Avoid single-letter names except for short loops or mathematical operations
|
|
28
|
-
- Use plural names for arrays and collections: `users`, `menuItems`
|
|
29
|
-
|
|
30
|
-
### Functions and methods
|
|
31
|
-
|
|
32
|
-
- Use `camelCase` for function names: `getUserData`, `calculateTotal`, `handleClick`
|
|
33
|
-
- Start with verbs that describe the action: `get`, `set`, `fetch`, `handle`, `render`, `calculate`
|
|
34
|
-
- Event handlers should use `handle` prefix: `handleSubmit`, `handleClickOutside`
|
|
35
|
-
- Boolean-returning functions should ask a question: `isValidEmail`, `canAccessResource`, `hasPermission`
|
|
36
|
-
- Keep names concise but descriptive: `fetchUserProfile` not `getUserProfileDataFromAPI`
|
|
37
|
-
|
|
38
|
-
### Components
|
|
39
|
-
|
|
40
|
-
- Use `PascalCase` for component names: `Button`, `UserProfile`, `NavigationMenu`
|
|
41
|
-
- Name folders to match the component: `Button`, `UserProfile`
|
|
42
|
-
- Subsequently, name files within the folder to match the component: `Button.tsx`, `UserProfile.tsx`
|
|
43
|
-
- Use descriptive names that indicate purpose: `SkipToContent`, `RadialProgress`, `Toggle`
|
|
44
|
-
- Avoid generic names like `Component`, `Container`, `Wrapper` without context
|
|
45
|
-
|
|
46
|
-
## Code comments
|
|
47
|
-
|
|
48
|
-
Comments should explain _why_ code exists, not _what_ it does. Well-named variables and functions handle the "what." Reserve comments for non-obvious decisions, complex logic, and important context.
|
|
49
|
-
|
|
50
|
-
### When to comment
|
|
51
|
-
|
|
52
|
-
- **Complex logic**: Explain algorithms or non-obvious implementations
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
// Use binary search for O(log n) performance on sorted arrays
|
|
56
|
-
const index = binarySearch(sortedArray, target);
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
- **Business logic**: Document requirements or constraints
|
|
60
|
-
|
|
61
|
-
```tsx
|
|
62
|
-
// Per WCAG 2.2, focus must return to trigger element on close
|
|
63
|
-
previousFocusRef.current?.focus();
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
- **Workarounds**: Explain temporary fixes or browser-specific code
|
|
67
|
-
|
|
68
|
-
```tsx
|
|
69
|
-
// Safari doesn't support :focus-visible, fallback to :focus
|
|
70
|
-
// TODO: Remove when Safari 15+ is minimum supported version
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
- **Non-obvious decisions**: Clarify choices that might seem strange
|
|
74
|
-
```tsx
|
|
75
|
-
// Delay state update to avoid race condition with async validation
|
|
76
|
-
setTimeout(() => setIsValid(true), 0);
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### When NOT to comment
|
|
80
|
-
|
|
81
|
-
- **Self-explanatory code**: Good names eliminate the need
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
// ❌ Bad: Comment restates the code
|
|
85
|
-
// Set loading to true
|
|
86
|
-
setIsLoading(true);
|
|
87
|
-
|
|
88
|
-
// ✅ Good: Code is self-documenting
|
|
89
|
-
setIsLoading(true);
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
- **Commented-out code**: Delete it; Git tracks history
|
|
93
|
-
```tsx
|
|
94
|
-
// ❌ Bad: Dead code clutters the file
|
|
95
|
-
// const oldImplementation = () => { ... };
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Comment style
|
|
99
|
-
|
|
100
|
-
- Use `//` for single-line comments, add a space after the `//` before commenting
|
|
101
|
-
- Use `/** */` for JSDoc comments on exports (functions, types, components)
|
|
102
|
-
- Write complete sentences with proper punctuation
|
|
103
|
-
- Keep comments up-to-date when code changes
|
|
104
|
-
|
|
105
|
-
## API reference
|
|
106
|
-
|
|
107
|
-
Well-documented APIs make components easier to use and understand. Clear prop descriptions and type information help developers implement components correctly without needing to read the source code.
|
|
108
|
-
|
|
109
|
-
### Props documentation:
|
|
110
|
-
|
|
111
|
-
Add [JSDoc](https://jsdoc.app/) comments to the props to provide additional clarity for what these props do — these comments is used by TypeScript when hovering over a prop, additional it also shows up in the props table of a component's story in Storybook.
|
|
112
|
-
|
|
113
|
-
```tsx
|
|
114
|
-
export type ButtonProps = {
|
|
115
|
-
/**
|
|
116
|
-
* The visual style variant of the button.
|
|
117
|
-
*/
|
|
118
|
-
variant: 'primary' | 'secondary';
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Whether the button is disabled.
|
|
122
|
-
*/
|
|
123
|
-
disabled?: boolean;
|
|
124
|
-
};
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Guidelines:
|
|
128
|
-
|
|
129
|
-
- Use full sentence descriptions
|
|
130
|
-
- Start boolean descriptions with "Whether"
|
|
131
|
-
- Document required vs. optional props
|
|
132
|
-
- Include type information
|
|
133
|
-
- Use discretion for whether a comment is needed or not
|
|
134
|
-
- If unsure, include a comment
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import { AboutHeader } from '~styleguide/blocks';
|
|
4
|
-
|
|
5
|
-
export const parameters = {
|
|
6
|
-
id: 'Formatting',
|
|
7
|
-
title: 'Formatting',
|
|
8
|
-
subtitle: 'Standards for formatting text and content in documentation',
|
|
9
|
-
status: 'static',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
<Meta title="Meta/Gamut writing guide/Formatting" />
|
|
13
|
-
|
|
14
|
-
<AboutHeader {...parameters} />
|
|
15
|
-
|
|
16
|
-
Consistent formatting makes documentation easier to scan, understand, and implement. These standards ensure our content is predictable and professional across all Gamut components.
|
|
17
|
-
|
|
18
|
-
## Numbers
|
|
19
|
-
|
|
20
|
-
- Use numerals for all numbers
|
|
21
|
-
- Use commas for thousands: 1,000
|
|
22
|
-
|
|
23
|
-
## Units of Measurement
|
|
24
|
-
|
|
25
|
-
- Use standard units: px, rem, em, %
|
|
26
|
-
- Include space between number and unit in prose: "16 pixels"
|
|
27
|
-
- No space in code: `16px`, `2rem`
|
|
28
|
-
|
|
29
|
-
## Lists
|
|
30
|
-
|
|
31
|
-
Lists help break down complex information into digestible pieces. Use them to organize features, steps, or related concepts.
|
|
32
|
-
|
|
33
|
-
### Bulleted lists:
|
|
34
|
-
|
|
35
|
-
- Use for unordered items
|
|
36
|
-
- Use parallel structure
|
|
37
|
-
- End with periods if items are complete sentences
|
|
38
|
-
- No periods if items are fragments
|
|
39
|
-
|
|
40
|
-
### Numbered lists:
|
|
41
|
-
|
|
42
|
-
- Use for sequential steps or prioritized items
|
|
43
|
-
- Start each item with a capital letter
|
|
44
|
-
|
|
45
|
-
## Code Blocks
|
|
46
|
-
|
|
47
|
-
- Use triple backticks (` ``` `) with language identifier (e.g., `tsx`, `javascript`, `css`)
|
|
48
|
-
- Include comments for complex examples
|
|
49
|
-
- Keep examples concise and focused
|
|
50
|
-
|
|
51
|
-
Example:
|
|
52
|
-
|
|
53
|
-
````
|
|
54
|
-
```tsx
|
|
55
|
-
<TextButton onClick={handleClick}> Click me </TextButton>
|
|
56
|
-
```
|
|
57
|
-
````
|
|
58
|
-
|
|
59
|
-
## Headings Hierarchy
|
|
60
|
-
|
|
61
|
-
- Start with second-level headings (`<h2>` in HTML, `##` in Markdown). The first level heading is automatically set by the title parameter.
|
|
62
|
-
- Don't skip heading levels. This ensures a logical reading order.
|
|
63
|
-
|
|
64
|
-
## Whitespace
|
|
65
|
-
|
|
66
|
-
- Use blank lines to separate sections
|
|
67
|
-
- Don't use multiple consecutive blank lines
|
|
68
|
-
- Indent code consistently (2 spaces for TypeScript/TSX)
|
|
69
|
-
- When using tabs, set them to 2 spaces
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import { AboutHeader } from '~styleguide/blocks';
|
|
4
|
-
|
|
5
|
-
export const parameters = {
|
|
6
|
-
id: 'General principles',
|
|
7
|
-
title: 'General principles',
|
|
8
|
-
subtitle: 'Core principles for writing effective documentation',
|
|
9
|
-
status: 'static',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
<Meta title="Meta/Gamut writing guide/General principles" />
|
|
13
|
-
|
|
14
|
-
<AboutHeader {...parameters} />
|
|
15
|
-
|
|
16
|
-
Good documentation does more than describe—it helps people succeed. These principles guide how we write about Gamut components, with a focus on clarity, accessibility, and helpfulness. Whether documenting a new component or updating existing content, prioritize being clear about what something does and honest about its limitations, accessible to the users who will interact with it, and helpful in showing how to use it effectively. We want to remove barriers and make it easier for designers and developers to do great work. Like our design system itself, this guide is a living document—it will continue to evolve as we add new features and learn from our users.
|
|
17
|
-
|
|
18
|
-
## Voice and tone
|
|
19
|
-
|
|
20
|
-
- Friendly and conversational: Write as if explaining to a colleague
|
|
21
|
-
- Prefer "we" when a pronoun is needed
|
|
22
|
-
- "You" is acceptable when necessary, e.g., "Use your best judgement"
|
|
23
|
-
- Encouraging without overpromising: Be supportive but realistic
|
|
24
|
-
- Global audience awareness: Avoid idioms, slang, and culturally-specific references
|
|
25
|
-
|
|
26
|
-
## Inclusivity
|
|
27
|
-
|
|
28
|
-
- Use inclusive language that makes all contributors feel welcome
|
|
29
|
-
- Define terms when first introduced
|
|
30
|
-
- Consider contributors of varying experience levels and roles (designers and developers)
|
|
31
|
-
|
|
32
|
-
## Transparency
|
|
33
|
-
|
|
34
|
-
- Clearly indicate component status:
|
|
35
|
-
- `current`: Stable, recommended for use
|
|
36
|
-
- `updating`: In progress, API may change
|
|
37
|
-
- `deprecated`: Still supported but slated for deletion — do not use for new work
|
|
38
|
-
- `static`: Reference material, no active development
|
|
39
|
-
- Link to source code and design files (GitHub, Figma)
|
|
40
|
-
|
|
41
|
-
## Consistency
|
|
42
|
-
|
|
43
|
-
- Use a single term for the same concept, including how it's referred to between the heading, body copy, and code examples.
|
|
44
|
-
- Do not use the same term for 2 different concepts.
|
|
45
|
-
- Maintain consistent component naming across packages
|
|
46
|
-
- Follow established patterns from existing components
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/blocks';
|
|
2
|
-
|
|
3
|
-
import { AboutHeader } from '~styleguide/blocks';
|
|
4
|
-
|
|
5
|
-
export const parameters = {
|
|
6
|
-
id: 'Language and grammar',
|
|
7
|
-
title: 'Language and grammar',
|
|
8
|
-
subtitle: 'Guidelines for language usage and grammar in documentation',
|
|
9
|
-
status: 'static',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
<Meta title="Meta/Gamut writing guide/Language and grammar" />
|
|
13
|
-
|
|
14
|
-
<AboutHeader {...parameters} />
|
|
15
|
-
|
|
16
|
-
## Voice
|
|
17
|
-
|
|
18
|
-
Use active voice rather than passive voice — it makes clear who should do what and eliminates ambiguity about responsibilities. Passive voice obscures who handles what and makes documentation harder to follow. E.g. "The component renders..." not "The component is rendered by..."
|
|
19
|
-
|
|
20
|
-
Use imperative mood for instructions: "Add the component" not "You should add the component"
|
|
21
|
-
|
|
22
|
-
## Tense
|
|
23
|
-
|
|
24
|
-
Use present tense for current functionality — it's the simplest and most direct form of a verb, making writing more clearer. The more conditional or future tense is used, the harder the audience has to work to understand the meaning. E.g. "The `StrokeButton` component accepts a `variant` prop."
|
|
25
|
-
|
|
26
|
-
- Use future tense sparingly, only for confirmed features
|
|
27
|
-
- Avoid past tense except in changelogs or historical context
|
|
28
|
-
|
|
29
|
-
## Pronouns
|
|
30
|
-
|
|
31
|
-
With active voice and imperative mood, we can often forgo pronouns entirely. However, if a pronoun is still necessary, consider these rules:
|
|
32
|
-
|
|
33
|
-
- Prefer "we" when a pronoun is needed
|
|
34
|
-
- "You" is acceptable when necessary, e.g., "Use your best judgement"
|
|
35
|
-
- Avoid "I/my/me" entirely
|
|
36
|
-
|
|
37
|
-
## Articles
|
|
38
|
-
|
|
39
|
-
- Use articles (a, an, the) for clarity
|
|
40
|
-
- Omit articles in lists when appropriate for brevity
|
|
41
|
-
|
|
42
|
-
## Abbreviations and Acronyms
|
|
43
|
-
|
|
44
|
-
- Spell out on first use: "Web Content Accessibility Guidelines (WCAG)"
|
|
45
|
-
- Use abbreviations for common terms in the domain of web design and development:
|
|
46
|
-
- HTML, CSS, API, UI, UX, etc.
|
|
47
|
-
- Avoid uncommon abbreviations without definition
|
|
48
|
-
|
|
49
|
-
## Capitalization
|
|
50
|
-
|
|
51
|
-
- Sentence case for all headings, buttons, and UI text
|
|
52
|
-
- PascalCase for component names: `MyComponent`, `ButtonGroup`
|
|
53
|
-
- camelCase for props and variables: `onClick`, `backgroundColor`
|
|
54
|
-
- Capitalize proper nouns: Codecademy, Storybook, Figma, GitHub
|