import { Meta, StoryObj } from '@storybook/react-vite';
import { AgenticButton } from './AgenticButton';
const meta: Meta<typeof AgenticButton> = {
tags: ['new-pattern', 'ready-for-dev'],
title: 'Component Proposals/Buttons/Agentic Button',
component: AgenticButton,
parameters: {
docs: {
description: {
component:
'**New pattern:** not in PDS v2 today. A button for an action the agent does: the secondary Button look with the AI gradient as its border and a gradient working spinner. It takes every Button prop except `variant`.',
},
},
},
argTypes: {
label: { control: 'text', table: { category: 'Content' } },
iconName: { table: { category: 'Content' } },
tooltipText: { table: { category: 'Content' } },
tally: { table: { category: 'Content' } },
statusDot: { control: 'select', table: { category: 'Content' } },
size: {
control: 'select',
table: { category: 'Component configuration' },
},
displayType: {
control: 'select',
table: { category: 'Component configuration' },
},
isAnimated: {
control: 'boolean',
table: { category: 'Component configuration' },
},
isFullWidth: {
control: 'boolean',
table: { category: 'Component configuration' },
},
isLoading: { control: 'boolean', table: { category: 'Status' } },
isWorking: { control: 'boolean', table: { category: 'Status' } },
disableWhenWorking: { table: { category: 'Status' } },
disabled: { table: { category: 'Base attributes' } },
buttonType: { table: { category: 'Base attributes' } },
className: { table: { category: 'Base attributes' } },
onClick: { table: { category: 'Functions' } },
},
args: {
label: 'Button',
size: 's',
displayType: 'label-only',
buttonType: 'button',
disabled: false,
isAnimated: true,
isLoading: false,
isWorking: false,
disableWhenWorking: true,
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const WithIcon: Story = {
args: {
displayType: 'icon-start',
iconName: 'zappy',
},
};
export const WithTally: Story = {
args: {
tally: { label: 4, type: 'neutral' },
},
};
export const WithStatusDot: Story = {
args: {
statusDot: 'discovery',
},
};
export const LoadingState: Story = {
args: {
isLoading: true,
tooltipText: 'Loading...',
},
};
export const WorkingState: Story = {
parameters: {
docs: {
description: {
story:
'`isWorking` shows the gradient spinner alongside the label while the agent works.',
},
},
},
args: {
isWorking: true,
tooltipText: 'This button is waiting for an action to complete',
},
};
export const WorkingStateInteractive: Story = {
parameters: {
docs: {
description: {
story:
'Set `disableWhenWorking` to `false` for an ongoing, interactive working state where the button must stay clickable (for example to stop it).',
},
},
},
args: {
displayType: 'icon-end',
iconName: 'pause',
isWorking: true,
disableWhenWorking: false,
label: 'Investigating',
},
};
export const AllStates: Story = {
parameters: {
docs: {
description: {
story: 'Default, disabled, with icon and working.',
},
},
},
render: (args) => (
<div
style={{
display: 'flex',
flexWrap: 'wrap',
gap: 'var(--pds-spacing-m)',
padding: 'var(--pds-spacing-m)',
}}
>
<AgenticButton {...args} label='Button' />
<AgenticButton {...args} disabled label='Button' />
<AgenticButton
{...args}
displayType='icon-start'
iconName='zappy'
label='Button'
/>
<AgenticButton {...args} isWorking label='Button' />
</div>
),
};
export const AllSizes: Story = {
parameters: {
docs: {
description: {
story: 'Quick reference for all button sizes, smallest to largest.',
},
},
},
render: (args) => {
const sizes = [
{ label: 'Extra small button', size: 'xs' },
{ label: 'Small button', size: 's' },
{ label: 'Medium button', size: 'm' },
{ label: 'Large button', size: 'l' },
] as const;
return (
<div
style={{
alignItems: 'center',
display: 'flex',
flexWrap: 'wrap',
gap: 'var(--pds-spacing-m)',
padding: 'var(--pds-spacing-m)',
}}
>
{sizes.map(({ label, size }) => (
<AgenticButton {...args} key={size} label={label} size={size} />
))}
</div>
);
},
};
Agentic Button
A separate component, `AgenticButton`, for an action the agent does:
Net-new componentOpen in Storybook