Skip to content

Commit ab29e58

Browse files
docs(storybook): align live component stories
1 parent ad46fea commit ab29e58

File tree

16 files changed

+1556
-150
lines changed

16 files changed

+1556
-150
lines changed

packages/react-components/src/components/Autocomplete/Autocomplete.stories.tsx

Lines changed: 205 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,91 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
2-
import { Autocomplete } from './Autocomplete';
2+
import { Autocomplete, type AutocompleteProps } from './Autocomplete';
33

4-
const options = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
4+
type AutocompleteOptionSet = 'countries' | 'cities' | 'empty';
55

6-
const meta: Meta<typeof Autocomplete> = {
6+
type AutocompleteStoryArgs = AutocompleteProps & {
7+
optionSet?: AutocompleteOptionSet;
8+
};
9+
10+
const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
11+
12+
const citiesOptions = [
13+
'London',
14+
'Manchester',
15+
'Birmingham',
16+
'Leeds',
17+
'Liverpool',
18+
];
19+
20+
const optionSets: Record<AutocompleteOptionSet, string[]> = {
21+
countries: countriesOptions,
22+
cities: citiesOptions,
23+
empty: [],
24+
};
25+
26+
const defaultStoryCode = `import { Autocomplete } from '@ourfuturehealth/react-components';
27+
28+
const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
29+
30+
<Autocomplete
31+
hint="Start typing to filter the list."
32+
label="Country"
33+
name="country"
34+
options={countriesOptions}
35+
/>;
36+
`;
37+
38+
const withErrorStoryCode = `import { Autocomplete } from '@ourfuturehealth/react-components';
39+
40+
const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
41+
42+
<Autocomplete
43+
errorMessage="Select a country from the list or enter a new one."
44+
hint="Start typing to filter the list."
45+
label="Country"
46+
name="country"
47+
options={countriesOptions}
48+
/>;
49+
`;
50+
51+
const fixedWidthStoryCode = `import { Autocomplete } from '@ourfuturehealth/react-components';
52+
53+
const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
54+
55+
<Autocomplete
56+
hint="Start typing to filter the list."
57+
inputWidth={20}
58+
label="Country"
59+
name="country"
60+
options={countriesOptions}
61+
/>;
62+
`;
63+
64+
const customNoResultsStoryCode = `import { Autocomplete } from '@ourfuturehealth/react-components';
65+
66+
const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
67+
68+
<Autocomplete
69+
hint="Start typing to filter the list."
70+
label="Country"
71+
name="country"
72+
noResultsText="No matching countries. Enter a new country instead."
73+
options={countriesOptions}
74+
/>;
75+
`;
76+
77+
const renderAutocompleteStory = ({
78+
optionSet,
79+
options = countriesOptions,
80+
...args
81+
}: AutocompleteStoryArgs) => {
82+
const resolvedOptions =
83+
optionSet === undefined ? options : optionSets[optionSet];
84+
85+
return <Autocomplete {...args} options={resolvedOptions} />;
86+
};
87+
88+
const meta: Meta<AutocompleteStoryArgs> = {
789
title: 'Components/Input/Autocomplete',
890
component: Autocomplete,
991
parameters: {
@@ -12,15 +94,15 @@ const meta: Meta<typeof Autocomplete> = {
1294
docs: {
1395
description: {
1496
component:
15-
'An input with inline suggestions that reuses the toolkit autocomplete classes, shared input-family label treatment, and suggestions list styling. The component manages the suggestion menu internally and supports both controlled and uncontrolled input values.',
97+
'Use Autocomplete for a text field that suggests matches while the user types. The React API stays small: pass a label, an array of suggestion strings, and the usual form-field props such as hint, error message, width, and `defaultValue` or `value` when you need them. Use the `Builder` story to explore the component with friendly preset controls, and use the other stories as fixed examples.',
1698
},
1799
},
18100
},
19101
tags: ['autodocs'],
20102
args: {
21103
label: 'Country',
22104
name: 'country',
23-
options,
105+
options: countriesOptions,
24106
},
25107
argTypes: {
26108
label: {
@@ -29,28 +111,41 @@ const meta: Meta<typeof Autocomplete> = {
29111
},
30112
hint: {
31113
control: 'text',
32-
description: 'Optional supporting text shown below the label and above any error message.',
114+
description:
115+
'Optional supporting text shown below the label and above any error message.',
33116
},
34117
errorMessage: {
35118
control: 'text',
36-
description: 'Validation message shown above the input. When present, the input is marked invalid and linked with `aria-describedby`.',
119+
description:
120+
'Validation message shown above the input. When present, the input is marked invalid and linked with `aria-describedby`.',
37121
},
38122
name: {
39123
control: 'text',
40124
description: 'HTML name submitted with the form.',
41125
},
42126
options: {
43-
control: 'object',
44-
description: 'Plain-text options used to build the suggestions list. Edit this as a simple array of strings.',
127+
control: false,
128+
description:
129+
'Suggestion strings used to build the autocomplete menu. Pass a plain array of labels, for example country names or common answers.',
45130
table: {
46131
type: {
47132
summary: 'string[]',
48133
},
49134
},
50135
},
136+
optionSet: {
137+
control: 'select',
138+
options: ['countries', 'cities', 'empty'],
139+
description:
140+
'Storybook-only helper for the Builder story. Switches between preset suggestion lists without editing the real `options` array.',
141+
table: {
142+
disable: true,
143+
},
144+
},
51145
noResultsText: {
52146
control: 'text',
53-
description: 'Override for the no-results message shown when the query matches no suggestions.',
147+
description:
148+
'Override for the no-results message shown when the query matches no suggestions.',
54149
},
55150
width: {
56151
control: 'select',
@@ -62,16 +157,24 @@ const meta: Meta<typeof Autocomplete> = {
62157
'one-third',
63158
'one-quarter',
64159
],
65-
description: 'Responsive width utility for the autocomplete field, including its suggestions dropdown.',
160+
description:
161+
'Responsive width utility for the autocomplete field, including its suggestions dropdown.',
66162
},
67163
inputWidth: {
68164
control: 'select',
69165
options: [2, 3, 4, 5, 10, 20, 30],
70-
description: 'Fixed character-width modifier that helps signal the expected answer length and also constrains the suggestions dropdown width.',
166+
description:
167+
'Fixed character-width modifier that helps signal the expected answer length and also constrains the suggestions dropdown width.',
71168
},
72169
describedBy: {
73170
control: 'text',
74-
description: 'Additional element IDs to append to the component-generated `aria-describedby` value.',
171+
description:
172+
'Additional element IDs to append to the component-generated `aria-describedby` value.',
173+
},
174+
isPageHeading: {
175+
control: 'boolean',
176+
description:
177+
'Wrap the label in an `h1` when this question is also the page heading.',
75178
},
76179
onOptionSelect: {
77180
control: false,
@@ -133,25 +236,114 @@ export const Default: Story = {
133236
args: {
134237
hint: 'Start typing to filter the list.',
135238
},
239+
parameters: {
240+
controls: {
241+
disable: true,
242+
},
243+
docs: {
244+
description: {
245+
story:
246+
'A realistic autocomplete example with a small set of country suggestions.',
247+
},
248+
source: {
249+
code: defaultStoryCode,
250+
},
251+
},
252+
},
253+
};
254+
255+
export const Builder: Story = {
256+
args: {
257+
hint: 'Start typing to filter the list.',
258+
label: 'Country',
259+
name: 'country',
260+
optionSet: 'countries',
261+
options: countriesOptions,
262+
},
263+
render: renderAutocompleteStory,
264+
parameters: {
265+
controls: {
266+
include: [
267+
'label',
268+
'hint',
269+
'errorMessage',
270+
'name',
271+
'optionSet',
272+
'noResultsText',
273+
'width',
274+
'inputWidth',
275+
'describedBy',
276+
'isPageHeading',
277+
],
278+
},
279+
docs: {
280+
description: {
281+
story:
282+
'Use the friendly controls here to explore the component with preset suggestion lists and the most useful visible props.',
283+
},
284+
},
285+
},
136286
};
137287

138288
export const WithError: Story = {
139289
args: {
140290
errorMessage: 'Select a country from the list or enter a new one.',
141291
hint: 'Start typing to filter the list.',
142292
},
293+
parameters: {
294+
controls: {
295+
disable: true,
296+
},
297+
docs: {
298+
description: {
299+
story:
300+
'Shows how the component presents a validation message above the input.',
301+
},
302+
source: {
303+
code: withErrorStoryCode,
304+
},
305+
},
306+
},
143307
};
144308

145309
export const FixedWidth: Story = {
146310
args: {
147311
hint: 'Start typing to filter the list.',
148312
inputWidth: 20,
149313
},
314+
parameters: {
315+
controls: {
316+
disable: true,
317+
},
318+
docs: {
319+
description: {
320+
story:
321+
'Shows the fixed character-width modifier that signals the expected answer length.',
322+
},
323+
source: {
324+
code: fixedWidthStoryCode,
325+
},
326+
},
327+
},
150328
};
151329

152330
export const CustomNoResultsText: Story = {
153331
args: {
154332
hint: 'Start typing to filter the list.',
155333
noResultsText: 'No matching countries. Enter a new country instead.',
156334
},
335+
parameters: {
336+
controls: {
337+
disable: true,
338+
},
339+
docs: {
340+
description: {
341+
story:
342+
'Shows how to override the empty-results message when you need service-specific wording.',
343+
},
344+
source: {
345+
code: customNoResultsStoryCode,
346+
},
347+
},
348+
},
157349
};

0 commit comments

Comments
 (0)