import { useState } from 'react';
import { FlexContainer } from '@pantheon-systems/pds-toolkit-react';
import { Meta, StoryObj } from '@storybook/react-vite';
import { SendButton, SendButtonState } from './SendButton';
const SIZES = ['xs', 's', 'm'] as const;
const STATES: {
ariaLabel: string;
name: string;
state: SendButtonState;
}[] = [
{ ariaLabel: 'Send message', name: 'Send', state: 'send' },
{ ariaLabel: 'Sending message', name: 'Working', state: 'working' },
{ ariaLabel: 'Stop generating', name: 'Stop', state: 'stop' },
];
const meta: Meta<typeof SendButton> = {
tags: ['new-pattern'],
title: 'Proposals/Buttons/Send Button',
component: SendButton,
parameters: {
docs: {
description: {
component:
'**New pattern:** not in PDS v2 today. Submits a prompt from a chat input. Same shape and sizes as `IconButton`, filled like a primary `Button`, with three states: send, working and stop.',
},
},
},
argTypes: {
ariaLabel: { control: 'text', table: { category: 'Content' } },
buttonType: { control: 'select', table: { category: 'Base attributes' } },
className: { table: { category: 'Base attributes' } },
disabled: { control: 'boolean', table: { category: 'Base attributes' } },
hasTooltip: {
control: 'boolean',
table: { category: 'Component configuration' },
},
onClick: { table: { category: 'Functions' } },
size: {
control: 'select',
options: SIZES,
table: { category: 'Component configuration' },
},
spinnerColor: {
control: 'select',
mapping: {
agentic: 'agentic',
currentColor: 'currentColor',
discovery: 'var(--pds-color-status-discovery-fill)',
},
options: ['currentColor', 'agentic', 'discovery'],
table: { category: 'Spinner' },
},
state: {
control: 'select',
options: ['send', 'working', 'stop'],
table: { category: 'State' },
},
},
args: {
ariaLabel: 'Send message',
buttonType: 'button',
disabled: false,
hasTooltip: true,
onClick: () => {
console.log('Send button clicked');
},
size: 'm',
state: 'send',
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const AllStates: Story = {
parameters: {
docs: {
description: {
story:
'The three states at each size: `send`, `working` (spinner, disabled) and `stop`.',
},
},
},
render: (args) => (
<FlexContainer flexDirection='column' gap='m'>
{STATES.map(({ ariaLabel, name, state }) => (
<FlexContainer alignItems='center' gap='m' key={name}>
<span style={{ width: '8rem' }}>{name}</span>
{SIZES.map((size) => (
<SendButton
{...args}
ariaLabel={ariaLabel}
key={size}
size={size}
state={state}
/>
))}
</FlexContainer>
))}
</FlexContainer>
),
};
export const Interactive: Story = {
parameters: {
docs: {
description: {
story:
'How the three states chain in a chat input: click to send, it shows `working` until the request starts, then `stop` while the response streams. Clicking stop returns to `send`.',
},
},
},
render: (args) => {
const [state, setState] = useState<SendButtonState>('send');
const current = STATES.find((s) => s.state === state);
const handleClick = () => {
if (state === 'send') {
setState('working');
setTimeout(() => setState('stop'), 400);
} else if (state === 'stop') {
setState('send');
}
};
return (
<SendButton
{...args}
ariaLabel={current?.ariaLabel ?? ''}
onClick={handleClick}
state={state}
/>
);
},
};
Send Button
A square, filled icon button (primary Button colors, IconButton shape and sizes) with three states:
Net-new componentOpen in Storybook