-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor Listbox stories for improved structure #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,163 +1,230 @@ | ||
| /* eslint-disable react/jsx-props-no-spreading */ | ||
| import type { Meta, StoryObj } from "@storybook/react"; | ||
| import React, { FC } from "react"; | ||
| import { FormField } from "../form-field"; | ||
| import type { Meta, StoryObj } from '@storybook/react-vite' | ||
|
Check failure on line 2 in src/components/form-field/listbox/listbox.stories.tsx
|
||
| import { FC, useState } from 'react' | ||
| import { FormField } from '../form-field' | ||
|
|
||
| type ListboxStoryArgs = { | ||
| label: string | ||
| description: string | ||
| placeholder: string | ||
| width: number | ||
| disabled: boolean | ||
| } | ||
|
|
||
| const meta: Meta<typeof FormField.Listbox> = { | ||
| title: "Input/Listbox", | ||
| component: FormField.Listbox, | ||
| }; | ||
| const meta: Meta<ListboxStoryArgs> = { | ||
| title: 'Input/Listbox', | ||
| args: { | ||
| label: 'Label', | ||
| description: 'Description', | ||
| placeholder: 'Select...', | ||
| width: 288, | ||
| disabled: false, | ||
| }, | ||
| argTypes: { | ||
| label: { control: 'text' }, | ||
| description: { control: 'text' }, | ||
| placeholder: { control: 'text' }, | ||
| width: { control: { type: 'range', min: 200, max: 360, step: 16 } }, | ||
| disabled: { control: 'boolean' }, | ||
| }, | ||
| } | ||
|
Comment on lines
+14
to
+30
|
||
|
|
||
| export default meta; | ||
| export default meta | ||
|
|
||
| type Story = StoryObj<typeof FormField.Listbox>; | ||
| type Story = StoryObj<ListboxStoryArgs> | ||
|
|
||
| interface Person { | ||
| id: number; | ||
| name: string; | ||
| isDead?: boolean; | ||
| id: number | ||
| name: string | ||
| isDead?: boolean | ||
| } | ||
|
|
||
| const people: Person[] = [ | ||
| { id: 1, name: "John Lennon", isDead: true }, | ||
| { id: 2, name: "Kenton Towne" }, | ||
| { id: 3, name: "Therese Wunsch" }, | ||
| { id: 4, name: "Benedict Kessler" }, | ||
| { id: 5, name: "Katelyn Rohan" }, | ||
| ]; | ||
|
|
||
| const ListboxTextWithHooks = () => { | ||
| const [selectedPerson, setSelectedPerson] = React.useState<null | Person>(null); | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor="value">Label</FormField.Label> | ||
| <FormField.Description id="value-description">Description</FormField.Description> | ||
| </FormField.LabelGroup> | ||
| <FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}> | ||
| <FormField.Listbox.Button> | ||
| <FormField.Listbox.Button.TextValue | ||
| value={selectedPerson?.name ?? null} | ||
| placeholder="Select..." | ||
| /> | ||
| </FormField.Listbox.Button> | ||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option | ||
| value={person} | ||
| key={person.id} | ||
| disabled={person.isDead} | ||
| > | ||
| <FormField.Listbox.Option.TextOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.TextOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ); | ||
| }; | ||
|
|
||
| const ListboxTextWithMultiplePropWithHooks = () => { | ||
| const [selectedPeople, setSelectedPeople] = React.useState<Person[]>([]); | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor="value">Label</FormField.Label> | ||
| <FormField.Description id="value-description">Description</FormField.Description> | ||
| </FormField.LabelGroup> | ||
| <FormField.Listbox<Person> value={selectedPeople} onChange={setSelectedPeople} multiple> | ||
| <FormField.Listbox.Button> | ||
| <FormField.Listbox.Button.TextValue | ||
| value={ | ||
| selectedPeople.length > 0 | ||
| ? selectedPeople.map((person) => person.name).join(", ") | ||
| : null | ||
| } | ||
| placeholder="Select..." | ||
| /> | ||
| </FormField.Listbox.Button> | ||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option | ||
| value={person} | ||
| key={person.id} | ||
| disabled={person.isDead} | ||
| > | ||
| <FormField.Listbox.Option.TextOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.TextOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ); | ||
| }; | ||
|
|
||
| const ListboxBadgeWithHooks: FC<{ disabled?: boolean }> = ({ disabled }) => { | ||
| const [selectedPerson, setSelectedPerson] = React.useState<null | Person>(null); | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor="value">Label</FormField.Label> | ||
| <FormField.Description id="value-description">Description</FormField.Description> | ||
| </FormField.LabelGroup> | ||
|
|
||
| <FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}> | ||
| <FormField.Listbox.Button disabled={disabled}> | ||
| <FormField.Listbox.Button.BadgeValue | ||
| value={selectedPerson?.name ?? null} | ||
| placeholder="Select …" | ||
| /> | ||
| </FormField.Listbox.Button> | ||
|
|
||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option value={person} key={person.id}> | ||
| <FormField.Listbox.Option.BadgeOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.BadgeOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ); | ||
| }; | ||
| { id: 1, name: 'John Lennon', isDead: true }, | ||
| { id: 2, name: 'Kenton Towne' }, | ||
| { id: 3, name: 'Therese Wunsch' }, | ||
| { id: 4, name: 'Benedict Kessler' }, | ||
| { id: 5, name: 'Katelyn Rohan' }, | ||
| ] | ||
|
|
||
| const ListboxTextWithHooks = ({ | ||
| label, | ||
| description, | ||
| placeholder, | ||
| }: { | ||
| label: string | ||
| description: string | ||
| placeholder: string | ||
| }) => { | ||
| const [selectedPerson, setSelectedPerson] = useState<null | Person>(null) | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor='value'>{label}</FormField.Label> | ||
| <FormField.Description id='value-description'> | ||
| {description} | ||
| </FormField.Description> | ||
| </FormField.LabelGroup> | ||
| <FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}> | ||
| <FormField.Listbox.Button> | ||
| <FormField.Listbox.Button.TextValue | ||
| value={selectedPerson?.name ?? null} | ||
| placeholder={placeholder} | ||
| /> | ||
| </FormField.Listbox.Button> | ||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option | ||
| value={person} | ||
| key={person.id} | ||
| disabled={person.isDead} | ||
| > | ||
| <FormField.Listbox.Option.TextOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.TextOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ) | ||
| } | ||
|
|
||
| const ListboxBadgeWithHooks: FC<{ | ||
| disabled?: boolean | ||
| label: string | ||
| description: string | ||
| placeholder: string | ||
| }> = ({ disabled, label, description, placeholder }) => { | ||
| const [selectedPerson, setSelectedPerson] = useState<null | Person>(null) | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor='value'>{label}</FormField.Label> | ||
| <FormField.Description id='value-description'> | ||
| {description} | ||
| </FormField.Description> | ||
| </FormField.LabelGroup> | ||
|
|
||
| <FormField.Listbox value={selectedPerson} onChange={setSelectedPerson}> | ||
| <FormField.Listbox.Button disabled={disabled}> | ||
| <FormField.Listbox.Button.BadgeValue | ||
| value={selectedPerson?.name ?? null} | ||
| placeholder={placeholder} | ||
| /> | ||
| </FormField.Listbox.Button> | ||
|
|
||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option value={person} key={person.id}> | ||
| <FormField.Listbox.Option.BadgeOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.BadgeOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ) | ||
| } | ||
|
|
||
| const ListboxMultiWithHooks = ({ | ||
| label, | ||
| description, | ||
| placeholder, | ||
| }: { | ||
| label: string | ||
| description: string | ||
| placeholder: string | ||
| }) => { | ||
| const [selectedPeople, setSelectedPeople] = useState<Person[]>([]) | ||
| const selectedLabels = selectedPeople.map((person) => person.name).join(', ') | ||
|
|
||
| return ( | ||
| <FormField> | ||
| <FormField.LabelGroup> | ||
| <FormField.Label htmlFor='value'>{label}</FormField.Label> | ||
| <FormField.Description id='value-description'> | ||
| {description} | ||
| </FormField.Description> | ||
| </FormField.LabelGroup> | ||
| <FormField.Listbox | ||
| value={selectedPeople} | ||
| onChange={setSelectedPeople} | ||
| multiple | ||
| > | ||
| <FormField.Listbox.Button> | ||
| <FormField.Listbox.Button.TextValue | ||
| value={selectedLabels || null} | ||
| placeholder={placeholder} | ||
| /> | ||
| </FormField.Listbox.Button> | ||
| <FormField.Listbox.Options> | ||
| {people.map((person) => ( | ||
| <FormField.Listbox.Option | ||
| value={person} | ||
| key={person.id} | ||
| disabled={person.isDead} | ||
| > | ||
| <FormField.Listbox.Option.TextOption> | ||
| {person.name} | ||
| </FormField.Listbox.Option.TextOption> | ||
| </FormField.Listbox.Option> | ||
| ))} | ||
| </FormField.Listbox.Options> | ||
| </FormField.Listbox> | ||
| </FormField> | ||
| ) | ||
| } | ||
|
|
||
| export const Default: Story = { | ||
| render: () => ( | ||
| <div className="w-72"> | ||
| <ListboxTextWithHooks /> | ||
| </div> | ||
| ), | ||
| }; | ||
| render: ({ label, description, placeholder, width }) => ( | ||
| <div style={{ width }}> | ||
| <ListboxTextWithHooks | ||
| label={label} | ||
| description={description} | ||
| placeholder={placeholder} | ||
| /> | ||
| </div> | ||
| ), | ||
| } | ||
|
|
||
| export const Badge: Story = { | ||
| render: () => ( | ||
| <div className="w-72"> | ||
| <ListboxBadgeWithHooks /> | ||
| </div> | ||
| ), | ||
| }; | ||
| render: ({ label, description, placeholder, width, disabled }) => ( | ||
| <div style={{ width }}> | ||
| <ListboxBadgeWithHooks | ||
| label={label} | ||
| description={description} | ||
| placeholder={placeholder} | ||
| disabled={disabled} | ||
| /> | ||
| </div> | ||
| ), | ||
| } | ||
|
|
||
| export const Disabled: Story = { | ||
| render: () => ( | ||
| <div className="w-72"> | ||
| <ListboxBadgeWithHooks disabled /> | ||
| </div> | ||
| ), | ||
| }; | ||
| render: ({ label, description, placeholder, width }) => ( | ||
| <div style={{ width }}> | ||
| <ListboxBadgeWithHooks | ||
| label={label} | ||
| description={description} | ||
| placeholder={placeholder} | ||
| disabled | ||
| /> | ||
| </div> | ||
| ), | ||
| } | ||
|
|
||
| export const Multiple: Story = { | ||
| render: () => ( | ||
| <div className="w-72"> | ||
| <ListboxTextWithMultiplePropWithHooks /> | ||
| </div> | ||
| ), | ||
| }; | ||
| render: ({ label, description, placeholder, width }) => ( | ||
| <div style={{ width }}> | ||
| <ListboxMultiWithHooks | ||
| label={label} | ||
| description={description} | ||
| placeholder={placeholder} | ||
| /> | ||
| </div> | ||
| ), | ||
| } | ||
|
Comment on lines
+2
to
+230
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import should use '@storybook/react' instead of '@storybook/react-vite' to maintain consistency with all other story files in the codebase. All other story files import from '@storybook/react'.