Skip to content

Commit 264fadc

Browse files
authored
Refactor Listbox stories for improved structure
1 parent 8b94e04 commit 264fadc

1 file changed

Lines changed: 213 additions & 146 deletions

File tree

Lines changed: 213 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,230 @@
11
/* eslint-disable react/jsx-props-no-spreading */
2-
import type { Meta, StoryObj } from "@storybook/react";
3-
import React, { FC } from "react";
4-
import { FormField } from "../form-field";
2+
import type { Meta, StoryObj } from '@storybook/react-vite'
3+
import { FC, useState } from 'react'
4+
import { FormField } from '../form-field'
5+
6+
type ListboxStoryArgs = {
7+
label: string
8+
description: string
9+
placeholder: string
10+
width: number
11+
disabled: boolean
12+
}
513

6-
const meta: Meta<typeof FormField.Listbox> = {
7-
title: "Input/Listbox",
8-
component: FormField.Listbox,
9-
};
14+
const meta: Meta<ListboxStoryArgs> = {
15+
title: 'Input/Listbox',
16+
args: {
17+
label: 'Label',
18+
description: 'Description',
19+
placeholder: 'Select...',
20+
width: 288,
21+
disabled: false,
22+
},
23+
argTypes: {
24+
label: { control: 'text' },
25+
description: { control: 'text' },
26+
placeholder: { control: 'text' },
27+
width: { control: { type: 'range', min: 200, max: 360, step: 16 } },
28+
disabled: { control: 'boolean' },
29+
},
30+
}
1031

11-
export default meta;
32+
export default meta
1233

13-
type Story = StoryObj<typeof FormField.Listbox>;
34+
type Story = StoryObj<ListboxStoryArgs>
1435

1536
interface Person {
16-
id: number;
17-
name: string;
18-
isDead?: boolean;
37+
id: number
38+
name: string
39+
isDead?: boolean
1940
}
2041

2142
const people: Person[] = [
22-
{ id: 1, name: "John Lennon", isDead: true },
23-
{ id: 2, name: "Kenton Towne" },
24-
{ id: 3, name: "Therese Wunsch" },
25-
{ id: 4, name: "Benedict Kessler" },
26-
{ id: 5, name: "Katelyn Rohan" },
27-
];
28-
29-
const ListboxTextWithHooks = () => {
30-
const [selectedPerson, setSelectedPerson] = React.useState<null | Person>(null);
31-
32-
return (
33-
<FormField>
34-
<FormField.LabelGroup>
35-
<FormField.Label htmlFor="value">Label</FormField.Label>
36-
<FormField.Description id="value-description">Description</FormField.Description>
37-
</FormField.LabelGroup>
38-
<FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}>
39-
<FormField.Listbox.Button>
40-
<FormField.Listbox.Button.TextValue
41-
value={selectedPerson?.name ?? null}
42-
placeholder="Select..."
43-
/>
44-
</FormField.Listbox.Button>
45-
<FormField.Listbox.Options>
46-
{people.map((person) => (
47-
<FormField.Listbox.Option
48-
value={person}
49-
key={person.id}
50-
disabled={person.isDead}
51-
>
52-
<FormField.Listbox.Option.TextOption>
53-
{person.name}
54-
</FormField.Listbox.Option.TextOption>
55-
</FormField.Listbox.Option>
56-
))}
57-
</FormField.Listbox.Options>
58-
</FormField.Listbox>
59-
</FormField>
60-
);
61-
};
62-
63-
const ListboxTextWithMultiplePropWithHooks = () => {
64-
const [selectedPeople, setSelectedPeople] = React.useState<Person[]>([]);
65-
66-
return (
67-
<FormField>
68-
<FormField.LabelGroup>
69-
<FormField.Label htmlFor="value">Label</FormField.Label>
70-
<FormField.Description id="value-description">Description</FormField.Description>
71-
</FormField.LabelGroup>
72-
<FormField.Listbox<Person> value={selectedPeople} onChange={setSelectedPeople} multiple>
73-
<FormField.Listbox.Button>
74-
<FormField.Listbox.Button.TextValue
75-
value={
76-
selectedPeople.length > 0
77-
? selectedPeople.map((person) => person.name).join(", ")
78-
: null
79-
}
80-
placeholder="Select..."
81-
/>
82-
</FormField.Listbox.Button>
83-
<FormField.Listbox.Options>
84-
{people.map((person) => (
85-
<FormField.Listbox.Option
86-
value={person}
87-
key={person.id}
88-
disabled={person.isDead}
89-
>
90-
<FormField.Listbox.Option.TextOption>
91-
{person.name}
92-
</FormField.Listbox.Option.TextOption>
93-
</FormField.Listbox.Option>
94-
))}
95-
</FormField.Listbox.Options>
96-
</FormField.Listbox>
97-
</FormField>
98-
);
99-
};
100-
101-
const ListboxBadgeWithHooks: FC<{ disabled?: boolean }> = ({ disabled }) => {
102-
const [selectedPerson, setSelectedPerson] = React.useState<null | Person>(null);
103-
104-
return (
105-
<FormField>
106-
<FormField.LabelGroup>
107-
<FormField.Label htmlFor="value">Label</FormField.Label>
108-
<FormField.Description id="value-description">Description</FormField.Description>
109-
</FormField.LabelGroup>
110-
111-
<FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}>
112-
<FormField.Listbox.Button disabled={disabled}>
113-
<FormField.Listbox.Button.BadgeValue
114-
value={selectedPerson?.name ?? null}
115-
placeholder="Select …"
116-
/>
117-
</FormField.Listbox.Button>
118-
119-
<FormField.Listbox.Options>
120-
{people.map((person) => (
121-
<FormField.Listbox.Option value={person} key={person.id}>
122-
<FormField.Listbox.Option.BadgeOption>
123-
{person.name}
124-
</FormField.Listbox.Option.BadgeOption>
125-
</FormField.Listbox.Option>
126-
))}
127-
</FormField.Listbox.Options>
128-
</FormField.Listbox>
129-
</FormField>
130-
);
131-
};
43+
{ id: 1, name: 'John Lennon', isDead: true },
44+
{ id: 2, name: 'Kenton Towne' },
45+
{ id: 3, name: 'Therese Wunsch' },
46+
{ id: 4, name: 'Benedict Kessler' },
47+
{ id: 5, name: 'Katelyn Rohan' },
48+
]
49+
50+
const ListboxTextWithHooks = ({
51+
label,
52+
description,
53+
placeholder,
54+
}: {
55+
label: string
56+
description: string
57+
placeholder: string
58+
}) => {
59+
const [selectedPerson, setSelectedPerson] = useState<null | Person>(null)
60+
61+
return (
62+
<FormField>
63+
<FormField.LabelGroup>
64+
<FormField.Label htmlFor='value'>{label}</FormField.Label>
65+
<FormField.Description id='value-description'>
66+
{description}
67+
</FormField.Description>
68+
</FormField.LabelGroup>
69+
<FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}>
70+
<FormField.Listbox.Button>
71+
<FormField.Listbox.Button.TextValue
72+
value={selectedPerson?.name ?? null}
73+
placeholder={placeholder}
74+
/>
75+
</FormField.Listbox.Button>
76+
<FormField.Listbox.Options>
77+
{people.map((person) => (
78+
<FormField.Listbox.Option
79+
value={person}
80+
key={person.id}
81+
disabled={person.isDead}
82+
>
83+
<FormField.Listbox.Option.TextOption>
84+
{person.name}
85+
</FormField.Listbox.Option.TextOption>
86+
</FormField.Listbox.Option>
87+
))}
88+
</FormField.Listbox.Options>
89+
</FormField.Listbox>
90+
</FormField>
91+
)
92+
}
93+
94+
const ListboxBadgeWithHooks: FC<{
95+
disabled?: boolean
96+
label: string
97+
description: string
98+
placeholder: string
99+
}> = ({ disabled, label, description, placeholder }) => {
100+
const [selectedPerson, setSelectedPerson] = useState<null | Person>(null)
101+
102+
return (
103+
<FormField>
104+
<FormField.LabelGroup>
105+
<FormField.Label htmlFor='value'>{label}</FormField.Label>
106+
<FormField.Description id='value-description'>
107+
{description}
108+
</FormField.Description>
109+
</FormField.LabelGroup>
110+
111+
<FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}>
112+
<FormField.Listbox.Button disabled={disabled}>
113+
<FormField.Listbox.Button.BadgeValue
114+
value={selectedPerson?.name ?? null}
115+
placeholder={placeholder}
116+
/>
117+
</FormField.Listbox.Button>
118+
119+
<FormField.Listbox.Options>
120+
{people.map((person) => (
121+
<FormField.Listbox.Option value={person} key={person.id}>
122+
<FormField.Listbox.Option.BadgeOption>
123+
{person.name}
124+
</FormField.Listbox.Option.BadgeOption>
125+
</FormField.Listbox.Option>
126+
))}
127+
</FormField.Listbox.Options>
128+
</FormField.Listbox>
129+
</FormField>
130+
)
131+
}
132+
133+
const ListboxMultiWithHooks = ({
134+
label,
135+
description,
136+
placeholder,
137+
}: {
138+
label: string
139+
description: string
140+
placeholder: string
141+
}) => {
142+
const [selectedPeople, setSelectedPeople] = useState<Person[]>([])
143+
const selectedLabels = selectedPeople.map((person) => person.name).join(', ')
144+
145+
return (
146+
<FormField>
147+
<FormField.LabelGroup>
148+
<FormField.Label htmlFor='value'>{label}</FormField.Label>
149+
<FormField.Description id='value-description'>
150+
{description}
151+
</FormField.Description>
152+
</FormField.LabelGroup>
153+
<FormField.Listbox
154+
value={selectedPeople}
155+
onChange={setSelectedPeople}
156+
multiple
157+
>
158+
<FormField.Listbox.Button>
159+
<FormField.Listbox.Button.TextValue
160+
value={selectedLabels || null}
161+
placeholder={placeholder}
162+
/>
163+
</FormField.Listbox.Button>
164+
<FormField.Listbox.Options>
165+
{people.map((person) => (
166+
<FormField.Listbox.Option
167+
value={person}
168+
key={person.id}
169+
disabled={person.isDead}
170+
>
171+
<FormField.Listbox.Option.TextOption>
172+
{person.name}
173+
</FormField.Listbox.Option.TextOption>
174+
</FormField.Listbox.Option>
175+
))}
176+
</FormField.Listbox.Options>
177+
</FormField.Listbox>
178+
</FormField>
179+
)
180+
}
132181

133182
export const Default: Story = {
134-
render: () => (
135-
<div className="w-72">
136-
<ListboxTextWithHooks />
137-
</div>
138-
),
139-
};
183+
render: ({ label, description, placeholder, width }) => (
184+
<div style={{ width }}>
185+
<ListboxTextWithHooks
186+
label={label}
187+
description={description}
188+
placeholder={placeholder}
189+
/>
190+
</div>
191+
),
192+
}
140193

141194
export const Badge: Story = {
142-
render: () => (
143-
<div className="w-72">
144-
<ListboxBadgeWithHooks />
145-
</div>
146-
),
147-
};
195+
render: ({ label, description, placeholder, width, disabled }) => (
196+
<div style={{ width }}>
197+
<ListboxBadgeWithHooks
198+
label={label}
199+
description={description}
200+
placeholder={placeholder}
201+
disabled={disabled}
202+
/>
203+
</div>
204+
),
205+
}
148206

149207
export const Disabled: Story = {
150-
render: () => (
151-
<div className="w-72">
152-
<ListboxBadgeWithHooks disabled />
153-
</div>
154-
),
155-
};
208+
render: ({ label, description, placeholder, width }) => (
209+
<div style={{ width }}>
210+
<ListboxBadgeWithHooks
211+
label={label}
212+
description={description}
213+
placeholder={placeholder}
214+
disabled
215+
/>
216+
</div>
217+
),
218+
}
156219

157220
export const Multiple: Story = {
158-
render: () => (
159-
<div className="w-72">
160-
<ListboxTextWithMultiplePropWithHooks />
161-
</div>
162-
),
163-
};
221+
render: ({ label, description, placeholder, width }) => (
222+
<div style={{ width }}>
223+
<ListboxMultiWithHooks
224+
label={label}
225+
description={description}
226+
placeholder={placeholder}
227+
/>
228+
</div>
229+
),
230+
}

0 commit comments

Comments
 (0)