Refactor Listbox stories for improved structure#22
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the Listbox component stories to improve their structure and interactivity. The refactoring introduces Storybook controls for label, description, placeholder, width, and disabled state, allowing for better interactive documentation and testing.
Key changes:
- Added typed story args with controls for dynamic story configuration
- Refactored story components to accept props from Storybook controls instead of hardcoded values
- Improved component naming (e.g.,
ListboxTextWithMultiplePropWithHooks→ListboxMultiWithHooks)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 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' |
There was a problem hiding this comment.
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'.
| import type { Meta, StoryObj } from '@storybook/react-vite' | |
| import type { Meta, StoryObj } from '@storybook/react' |
| 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' }, | ||
| }, | ||
| } |
There was a problem hiding this comment.
The meta configuration is missing the 'component' property. While using custom args for story controls is valid, the meta object should still include a reference to the component being documented. Add component: FormField.Listbox to the meta configuration to maintain consistency with Storybook best practices and other story files in the codebase.
| import type { Meta, StoryObj } from '@storybook/react-vite' | ||
| 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' }, | ||
| }, | ||
| } | ||
|
|
||
| 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> | ||
| ), | ||
| } |
There was a problem hiding this comment.
The code uses single quotes for string literals, which is inconsistent with the rest of the codebase that predominantly uses double quotes. Update all string literals to use double quotes to maintain consistency with the project's coding style.
| import type { Meta, StoryObj } from '@storybook/react-vite' | ||
| 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' }, | ||
| }, | ||
| } | ||
|
|
||
| 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> | ||
| ), | ||
| } |
There was a problem hiding this comment.
The code omits semicolons at the end of statements, which is inconsistent with the rest of the codebase that uses semicolons. Add semicolons to maintain consistency with the project's coding style.
No description provided.