All checks were successful
continuous-integration/drone/push Build is passing
169 lines
5.0 KiB
TypeScript
169 lines
5.0 KiB
TypeScript
import { useState } from 'react';
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
import { Dropdown } from './Dropdown';
|
|
|
|
const choices = [
|
|
{ id: 'draft', label: 'Draft' },
|
|
{ id: 'review', label: 'In review' },
|
|
{ id: 'published', label: 'Published' },
|
|
];
|
|
|
|
const meta = {
|
|
title: 'Components/Dropdown',
|
|
component: Dropdown,
|
|
tags: ['autodocs'],
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
component:
|
|
'Styled select component with label, error state, stacked/inline layout, and multiple sizes.',
|
|
},
|
|
},
|
|
},
|
|
argTypes: {
|
|
label: {
|
|
description: 'Label text shown above (stacked) or on the left (inline).',
|
|
control: 'text',
|
|
table: { type: { summary: 'string' } },
|
|
},
|
|
value: {
|
|
description: 'Current selected value (must match one `choices[].id`).',
|
|
control: 'text',
|
|
table: { type: { summary: 'string' } },
|
|
},
|
|
choices: {
|
|
description: 'Options list in `{ id: string; label: string }` format.',
|
|
control: 'object',
|
|
table: { type: { summary: 'Array<{ id: string; label: string }>' } },
|
|
},
|
|
size: {
|
|
description: 'Control size.',
|
|
options: ['sm', 'md', 'lg', 'full'],
|
|
control: 'inline-radio',
|
|
table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } },
|
|
},
|
|
width: {
|
|
description: 'Control width constraint.',
|
|
options: ['sm', 'md', 'lg', 'full'],
|
|
control: 'inline-radio',
|
|
table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } },
|
|
},
|
|
layout: {
|
|
description: 'Label/control layout mode.',
|
|
options: ['stacked', 'inline'],
|
|
control: 'inline-radio',
|
|
table: { type: { summary: "'stacked' | 'inline'" } },
|
|
},
|
|
disabled: {
|
|
description: 'Disables the field.',
|
|
control: 'boolean',
|
|
table: { type: { summary: 'boolean' } },
|
|
},
|
|
required: {
|
|
description: 'Sets the native HTML `required` attribute.',
|
|
control: 'boolean',
|
|
table: { type: { summary: 'boolean' } },
|
|
},
|
|
error: {
|
|
description: 'Error message shown below the field.',
|
|
control: 'text',
|
|
table: { type: { summary: 'string' } },
|
|
},
|
|
className: {
|
|
description: 'Extra CSS classes for the wrapper.',
|
|
control: 'text',
|
|
table: { type: { summary: 'string' } },
|
|
},
|
|
selectClassName: {
|
|
description: 'Extra CSS classes for the `<select>` element.',
|
|
control: 'text',
|
|
table: { type: { summary: 'string' } },
|
|
},
|
|
onChange: {
|
|
description: 'Callback fired with the newly selected value.',
|
|
action: 'changed',
|
|
table: { type: { summary: '(value: string) => void' } },
|
|
},
|
|
},
|
|
args: {
|
|
label: 'Status',
|
|
value: 'draft',
|
|
choices,
|
|
size: 'md',
|
|
width: 'md',
|
|
layout: 'stacked',
|
|
},
|
|
} satisfies Meta<typeof Dropdown>;
|
|
|
|
export default meta;
|
|
type Story = StoryObj<typeof meta>;
|
|
|
|
export const Stacked: Story = {
|
|
render: function StackedRender(args) {
|
|
const [value, setValue] = useState(args.value);
|
|
return (
|
|
<Dropdown
|
|
{...args}
|
|
value={value}
|
|
onChange={(next) => {
|
|
setValue(next);
|
|
args.onChange?.(next);
|
|
}}
|
|
/>
|
|
);
|
|
},
|
|
};
|
|
|
|
export const Inline: Story = {
|
|
args: {
|
|
layout: 'inline',
|
|
size: 'sm',
|
|
},
|
|
render: function InlineRender(args) {
|
|
const [value, setValue] = useState(args.value);
|
|
return (
|
|
<Dropdown
|
|
{...args}
|
|
value={value}
|
|
onChange={(next) => {
|
|
setValue(next);
|
|
args.onChange?.(next);
|
|
}}
|
|
/>
|
|
);
|
|
},
|
|
};
|
|
|
|
export const Disabled: Story = {
|
|
args: {
|
|
disabled: true,
|
|
},
|
|
};
|
|
|
|
export const WithError: Story = {
|
|
args: {
|
|
error: 'Please choose a valid status',
|
|
},
|
|
};
|
|
|
|
export const SizeMatrix: Story = {
|
|
render: function SizeMatrixRender(args) {
|
|
const [value, setValue] = useState(args.value);
|
|
return (
|
|
<div className="grid grid-cols-1 gap-3">
|
|
<Dropdown {...args} value={value} size="sm" label="Small" onChange={setValue} />
|
|
<Dropdown {...args} value={value} size="md" label="Medium" onChange={setValue} />
|
|
<Dropdown {...args} value={value} size="lg" label="Large" onChange={setValue} />
|
|
<Dropdown
|
|
{...args}
|
|
value={value}
|
|
size="full"
|
|
width="full"
|
|
label="Full"
|
|
onChange={setValue}
|
|
/>
|
|
</div>
|
|
);
|
|
},
|
|
};
|