import React, { useState } from 'react';
import { Meta, StoryObj } from '@storybook/react-vite';
import { FlexContainer, iconList } from '@pantheon-systems/pds-toolkit-react';
import { IconButton } from './IconButton';
const SIZES = ['xs', 's', 'm'] as const;
const meta: Meta<typeof IconButton> = {
title: 'Proposals/Buttons/Icon Button',
component: IconButton,
parameters: {
docs: {
description: {
component: 'Icon-only button implementation',
},
},
},
argTypes: {
ariaLabel: {
control: 'text',
table: { category: 'Content' },
},
iconName: {
control: 'select',
options: iconList,
table: { category: 'Component configuration' },
},
buttonType: {
control: 'select',
table: { category: 'Base attributes' },
},
disabled: {
control: 'boolean',
table: { category: 'Base attributes' },
},
onClick: {
table: { category: 'Functions' },
},
className: {
table: {
category: 'Base attributes',
},
},
hasBorder: {
control: 'boolean',
table: { category: 'Component configuration' },
},
hasTooltip: {
control: 'boolean',
table: { category: 'Component configuration' },
},
size: {
control: 'select',
options: SIZES,
table: { category: 'Component configuration' },
},
variant: {
control: 'select',
table: { category: 'Component configuration' },
},
icon2Name: {
control: 'select',
options: iconList,
table: { category: 'Component configuration' },
},
isAgentic: {
control: 'boolean',
table: { category: 'Component configuration' },
},
isPressed: {
control: 'boolean',
table: { category: 'State' },
},
pressedIconName: {
control: 'select',
options: iconList,
table: { category: 'Component configuration' },
},
},
args: {
ariaLabel: 'Ask Zappy',
buttonType: 'button',
disabled: false,
iconName: 'zappy',
hasBorder: true,
isAgentic: true,
onClick: () => {
console.log('Icon button clicked');
},
size: 'm',
hasTooltip: true,
variant: 'standard',
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const Sizes: Story = {
parameters: {
docs: {
description: {
story:
'All available `size` values, smallest to largest: `xs`, `s`, `m`, borderless (the default) and with a border. The bordered row follows the `isAgentic` control: on gives the AI gradient border, off gives the default gray border.',
},
},
},
render: (args) => {
const looks = [
{ hasBorder: false, isAgentic: false, name: 'Borderless' },
{ hasBorder: true, isAgentic: args.isAgentic, name: 'With border' },
];
return (
<FlexContainer flexDirection='column' gap='m'>
{looks.map(({ hasBorder, isAgentic, name }) => (
<FlexContainer alignItems='center' gap='m' key={name}>
<span style={{ width: '8rem' }}>{name}</span>
{SIZES.map((size) => (
<IconButton
key={size}
{...args}
hasBorder={hasBorder}
isAgentic={isAgentic}
size={size}
/>
))}
</FlexContainer>
))}
</FlexContainer>
);
},
};
export const WithBorder: Story = {
args: {
hasBorder: true,
},
};
export const Pressed: Story = {
parameters: {
docs: {
description: {
story:
'Demonstrates the `isPressed` toggle pattern. Pressed fills the button, and is announced to screen readers through `aria-pressed`. Pass `pressedIconName` to swap the icon as well. Use the `isAgentic` control to toggle the agentic treatment.',
},
},
},
render: ({ isAgentic }) => {
const [isPressed, setIsPressed] = useState(false);
return (
<IconButton
hasBorder
ariaLabel='Ask Zappy'
iconName='zappy'
isAgentic={isAgentic}
isPressed={isPressed}
onClick={() => setIsPressed((v) => !v)}
/>
);
},
};
Icon Button
Starting point for an IconButton proposal.
Extends a PDS componentOpen in Storybook