Files
web-ui/src/components/Button.stories.tsx
Beatrice Dellacà 29a4e8c2ee
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
add width, v0.1.10
2026-02-23 19:57:19 +01:00

146 lines
4.3 KiB
TypeScript

import type { Meta, StoryObj } from '@storybook/react';
import { PlusIcon } from '@heroicons/react/24/solid';
import { Button } from './Button';
const meta = {
title: 'Components/Button',
component: Button,
tags: ['autodocs'],
parameters: {
docs: {
description: {
component:
'Polymorphic button component: renders a native `<button>` or a React Router `<Link>` when `to` is provided.',
},
},
},
argTypes: {
label: {
description: 'Visible button label text.',
control: 'text',
table: { type: { summary: 'string' } },
},
type: {
description: 'Base visual style.',
options: ['solid', 'outlined', 'noborder'],
control: 'inline-radio',
table: { type: { summary: "'solid' | 'outlined' | 'noborder'" } },
},
variant: {
description:
'Color variant. If omitted: `primary` for `solid`, `secondary` for the other types.',
options: ['primary', 'secondary', 'important'],
control: 'inline-radio',
table: { type: { summary: "'primary' | 'secondary' | 'important'" } },
},
size: {
description: 'Button size.',
options: ['sm', 'md', 'lg', 'full'],
control: 'inline-radio',
table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } },
},
width: {
description: 'Button width behavior.',
options: ['sm', 'md', 'lg', 'full'],
control: 'inline-radio',
table: { type: { summary: "'sm' | 'md' | 'lg' | 'full'" } },
},
to: {
description: 'Navigation path. When set, the component renders a `<Link>`.',
control: 'text',
table: { type: { summary: 'string' } },
},
htmlType: {
description: 'HTML button type used when rendering a native `<button>`.',
options: ['button', 'submit', 'reset'],
control: 'inline-radio',
table: { type: { summary: "'button' | 'submit' | 'reset'" } },
},
disabled: {
description: 'Disables interaction and hover/click states.',
control: 'boolean',
table: { type: { summary: 'boolean' } },
},
icon: {
description: 'Optional icon component (for example Heroicons).',
control: false,
table: { type: { summary: 'ElementType' } },
},
ariaLabel: {
description: 'Accessible label. Falls back to `label` when not provided.',
control: 'text',
table: { type: { summary: 'string' } },
},
className: {
description: 'Extra CSS classes for the root element.',
control: 'text',
table: { type: { summary: 'string' } },
},
onClick: {
description: 'Click handler callback.',
action: 'clicked',
table: { type: { summary: 'MouseEventHandler<HTMLElement>' } },
},
},
args: {
type: 'solid',
variant: 'primary',
size: 'md',
width: 'md',
label: 'Save',
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const SolidPrimary: Story = {};
export const SolidImportant: Story = {
args: {
type: 'solid',
variant: 'important',
label: 'Delete',
},
};
export const OutlinedSecondary: Story = {
args: {
type: 'outlined',
variant: 'secondary',
label: 'Cancel',
},
};
export const IconOnly: Story = {
args: {
icon: PlusIcon,
label: undefined,
ariaLabel: 'Add item',
},
};
export const LinkButton: Story = {
args: {
to: '/demo',
label: 'Go to demo',
},
};
export const Disabled: Story = {
args: {
disabled: true,
},
};
export const SizeMatrix: Story = {
render: (args) => (
<div className="grid grid-cols-1 gap-3">
<Button {...args} size="sm" label="Small" />
<Button {...args} size="md" label="Medium" />
<Button {...args} size="lg" label="Large" />
<Button {...args} size="md" width="full" label="Full width" />
</div>
),
};