Skip to content

Commit 9496011

Browse files
docs(storybook): deepen component story docs
1 parent ab29e58 commit 9496011

File tree

16 files changed

+1359
-50
lines changed

16 files changed

+1359
-50
lines changed

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

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
2+
import { ArgTypes, Description, Source, Stories, Title } from '@storybook/addon-docs/blocks';
23
import { Autocomplete, type AutocompleteProps } from './Autocomplete';
34

45
type AutocompleteOptionSet = 'countries' | 'cities' | 'empty';
@@ -74,15 +75,42 @@ const countriesOptions = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
7475
/>;
7576
`;
7677

78+
const autocompleteUsageExample = `import { Autocomplete } from '@ourfuturehealth/react-components';
79+
80+
const options = ['England', 'Scotland', 'Wales', 'Northern Ireland'];
81+
82+
<Autocomplete
83+
hint="Start typing to filter the list."
84+
label="Country"
85+
name="country"
86+
options={options}
87+
/>;
88+
`;
89+
90+
const autocompleteOptionsShapeExample = `const options = [
91+
'England',
92+
'Scotland',
93+
'Wales',
94+
'Northern Ireland',
95+
];
96+
`;
97+
7798
const renderAutocompleteStory = ({
7899
optionSet,
79100
options = countriesOptions,
80101
...args
81102
}: AutocompleteStoryArgs) => {
82103
const resolvedOptions =
83104
optionSet === undefined ? options : optionSets[optionSet];
105+
const resolvedArgs = {
106+
...args,
107+
describedBy: args.describedBy || undefined,
108+
errorMessage: args.errorMessage || undefined,
109+
hint: args.hint || undefined,
110+
noResultsText: args.noResultsText || undefined,
111+
};
84112

85-
return <Autocomplete {...args} options={resolvedOptions} />;
113+
return <Autocomplete {...resolvedArgs} options={resolvedOptions} />;
86114
};
87115

88116
const meta: Meta<AutocompleteStoryArgs> = {
@@ -96,6 +124,62 @@ const meta: Meta<AutocompleteStoryArgs> = {
96124
component:
97125
'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.',
98126
},
127+
page: () => (
128+
<>
129+
<Title />
130+
<Description />
131+
132+
<h2>How to use the React component</h2>
133+
<p>
134+
Pass a required <code>label</code>, <code>name</code>, and an{' '}
135+
<code>options</code> array of suggestion strings. Add{' '}
136+
<code>hint</code> when the user needs extra guidance, and use{' '}
137+
<code>errorMessage</code> when you need to show validation feedback.
138+
</p>
139+
<p>
140+
Use <code>noResultsText</code> when your service needs custom empty
141+
state wording, and use <code>width</code> or <code>inputWidth</code>{' '}
142+
to control the visible field width.
143+
</p>
144+
<Source code={autocompleteUsageExample} language="tsx" />
145+
146+
<h2>Component props</h2>
147+
<ArgTypes
148+
of={Default}
149+
include={[
150+
'label',
151+
'hint',
152+
'errorMessage',
153+
'name',
154+
'options',
155+
'noResultsText',
156+
'width',
157+
'inputWidth',
158+
'describedBy',
159+
'isPageHeading',
160+
]}
161+
/>
162+
163+
<h2>
164+
<code>options</code> shape
165+
</h2>
166+
<p>
167+
Pass a plain array of strings. Each string becomes one suggestion in
168+
the filtered results list.
169+
</p>
170+
<Source code={autocompleteOptionsShapeExample} language="tsx" />
171+
172+
<h2>Storybook builder helpers</h2>
173+
<p>
174+
<code>optionSet</code> is only used by the Storybook{' '}
175+
<code>Builder</code> story so you can swap between preset suggestion
176+
lists without editing the real <code>options</code> prop. It is not
177+
a React prop accepted by <code>Autocomplete</code>.
178+
</p>
179+
180+
<Stories title="Examples" />
181+
</>
182+
),
99183
},
100184
},
101185
tags: ['autodocs'],
@@ -108,20 +192,32 @@ const meta: Meta<AutocompleteStoryArgs> = {
108192
label: {
109193
control: 'text',
110194
description: 'Question or field label shown above the autocomplete input.',
195+
table: {
196+
category: 'AutocompleteProps',
197+
},
111198
},
112199
hint: {
113200
control: 'text',
114201
description:
115202
'Optional supporting text shown below the label and above any error message.',
203+
table: {
204+
category: 'AutocompleteProps',
205+
},
116206
},
117207
errorMessage: {
118208
control: 'text',
119209
description:
120210
'Validation message shown above the input. When present, the input is marked invalid and linked with `aria-describedby`.',
211+
table: {
212+
category: 'AutocompleteProps',
213+
},
121214
},
122215
name: {
123216
control: 'text',
124217
description: 'HTML name submitted with the form.',
218+
table: {
219+
category: 'AutocompleteProps',
220+
},
125221
},
126222
options: {
127223
control: false,
@@ -131,6 +227,7 @@ const meta: Meta<AutocompleteStoryArgs> = {
131227
type: {
132228
summary: 'string[]',
133229
},
230+
category: 'AutocompleteProps',
134231
},
135232
},
136233
optionSet: {
@@ -139,13 +236,16 @@ const meta: Meta<AutocompleteStoryArgs> = {
139236
description:
140237
'Storybook-only helper for the Builder story. Switches between preset suggestion lists without editing the real `options` array.',
141238
table: {
142-
disable: true,
239+
category: 'Builder story only',
143240
},
144241
},
145242
noResultsText: {
146243
control: 'text',
147244
description:
148245
'Override for the no-results message shown when the query matches no suggestions.',
246+
table: {
247+
category: 'AutocompleteProps',
248+
},
149249
},
150250
width: {
151251
control: 'select',
@@ -159,22 +259,34 @@ const meta: Meta<AutocompleteStoryArgs> = {
159259
],
160260
description:
161261
'Responsive width utility for the autocomplete field, including its suggestions dropdown.',
262+
table: {
263+
category: 'AutocompleteProps',
264+
},
162265
},
163266
inputWidth: {
164267
control: 'select',
165268
options: [2, 3, 4, 5, 10, 20, 30],
166269
description:
167270
'Fixed character-width modifier that helps signal the expected answer length and also constrains the suggestions dropdown width.',
271+
table: {
272+
category: 'AutocompleteProps',
273+
},
168274
},
169275
describedBy: {
170276
control: 'text',
171277
description:
172278
'Additional element IDs to append to the component-generated `aria-describedby` value.',
279+
table: {
280+
category: 'AutocompleteProps',
281+
},
173282
},
174283
isPageHeading: {
175284
control: 'boolean',
176285
description:
177286
'Wrap the label in an `h1` when this question is also the page heading.',
287+
table: {
288+
category: 'AutocompleteProps',
289+
},
178290
},
179291
onOptionSelect: {
180292
control: false,
@@ -257,6 +369,10 @@ export const Builder: Story = {
257369
hint: 'Start typing to filter the list.',
258370
label: 'Country',
259371
name: 'country',
372+
describedBy: '',
373+
errorMessage: '',
374+
isPageHeading: false,
375+
noResultsText: '',
260376
optionSet: 'countries',
261377
options: countriesOptions,
262378
},

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
2+
import { ArgTypes, Description, Source, Stories, Title } from '@storybook/addon-docs/blocks';
23
import { Button, type ButtonProps } from './Button';
34

5+
const buttonUsageExample = `import { Button } from '@ourfuturehealth/react-components';
6+
7+
<Button variant="contained">
8+
Continue
9+
</Button>;
10+
`;
11+
412
const meta: Meta<ButtonProps> = {
513
title: 'Components/Button',
614
component: Button,
@@ -11,6 +19,33 @@ const meta: Meta<ButtonProps> = {
1119
component:
1220
'A flexible button component based on the OFH Design System with multiple variants and states. If `href` is provided, the component renders as an anchor instead of a button. The `variant` changes the visual prominence only, not the semantic element.',
1321
},
22+
page: () => (
23+
<>
24+
<Title />
25+
<Description />
26+
27+
<h2>How to use the React component</h2>
28+
<p>
29+
Use <code>Button</code> for the main action on a page or step. Pass
30+
the visible label as <code>children</code> and choose a{' '}
31+
<code>variant</code> when you need a different visual emphasis.
32+
</p>
33+
<p>
34+
Add <code>href</code> when the action should navigate to another
35+
page. Leave <code>href</code> unset when the action should behave as
36+
a real button inside your app or form.
37+
</p>
38+
<Source code={buttonUsageExample} language="tsx" />
39+
40+
<h2>Component props</h2>
41+
<ArgTypes
42+
of={Default}
43+
include={['variant', 'children', 'href', 'type', 'disabled']}
44+
/>
45+
46+
<Stories title="Examples" />
47+
</>
48+
),
1449
},
1550
},
1651
tags: ['autodocs'],
@@ -27,21 +62,33 @@ const meta: Meta<ButtonProps> = {
2762
],
2863
description:
2964
'Changes the visual style and prominence of the button. It does not change whether the component renders as a button or link.',
65+
table: {
66+
category: 'ButtonProps',
67+
},
3068
},
3169
children: {
3270
control: 'text',
3371
description: 'Visible label content for the button or link.',
72+
table: {
73+
category: 'ButtonProps',
74+
},
3475
},
3576
href: {
3677
control: 'text',
3778
description:
3879
'Navigation destination. When this is set, the component renders as an anchor (`<a>`) instead of a button.',
80+
table: {
81+
category: 'ButtonProps',
82+
},
3983
},
4084
type: {
4185
control: 'select',
4286
options: ['button', 'submit', 'reset'],
4387
description:
4488
'Button type for real `<button>` elements. This has no effect when `href` is set and the component renders as a link.',
89+
table: {
90+
category: 'ButtonProps',
91+
},
4592
},
4693
onClick: {
4794
control: false,
@@ -55,6 +102,9 @@ const meta: Meta<ButtonProps> = {
55102
control: 'boolean',
56103
description:
57104
'Disables the button. This only applies to real `<button>` elements and has no effect when `href` is set.',
105+
table: {
106+
category: 'ButtonProps',
107+
},
58108
},
59109
className: {
60110
control: false,
@@ -95,9 +145,11 @@ export const Default: Story = {
95145

96146
export const Builder: Story = {
97147
args: {
98-
variant: 'contained',
99148
children: 'Continue',
149+
disabled: false,
150+
href: '',
100151
type: 'button',
152+
variant: 'contained',
101153
},
102154
parameters: {
103155
controls: {

0 commit comments

Comments
 (0)