import { useState } from 'react';
import { FlexContainer } from '@pantheon-systems/pds-toolkit-react';
import { Meta, StoryObj } from '@storybook/react-vite';
import { ModelSelector, ModelSelectorOption } from './ModelSelector';
const SIZES = ['xs', 's', 'm'] as const;
// Sample models: Zappy first, then other agents.
const MODELS: ModelSelectorOption[] = [
{ id: 'zappy', label: 'Zappy' },
{ id: 'haiku', label: 'Claude Haiku 5.5' },
{ id: 'sonnet', label: 'Claude Sonnet 5.5' },
{ id: 'opus', label: 'Claude Opus 5.5' },
];
const MODELS_WITH_DETAILS: ModelSelectorOption[] = [
{
description: 'Pantheon agent for your sites',
id: 'zappy',
label: 'Zappy',
},
{
description: 'Fastest, for quick answers',
id: 'haiku',
label: 'Claude Haiku 5.5',
},
{
description: 'Balanced speed and depth',
id: 'sonnet',
label: 'Claude Sonnet 5.5',
},
{
description: 'Most capable, slower',
disabled: true,
id: 'opus',
label: 'Claude Opus 5.5',
},
];
const meta: Meta<typeof ModelSelector> = {
tags: ['new-pattern'],
title: 'Proposals/Buttons/Model Selector',
component: ModelSelector,
parameters: {
docs: {
description: {
component:
'**New pattern:** not in PDS v2 today. Picks which model or agent answers, from a chat input or similar. Built on `MenuButton` (menu, keyboard and focus behavior), with a trigger that has no fill in any state and a check on the selected model.',
},
},
},
argTypes: {
className: { table: { category: 'Base attributes' } },
disabled: { control: 'boolean', table: { category: 'Base attributes' } },
id: { control: 'text', table: { category: 'Base attributes' } },
onValueChange: { table: { category: 'Functions' } },
options: { control: 'object', table: { category: 'Content' } },
size: {
control: 'select',
options: SIZES,
table: { category: 'Component configuration' },
},
value: { control: 'text', table: { category: 'Content' } },
},
args: {
disabled: false,
id: 'model-selector',
options: MODELS,
size: 's',
value: 'zappy',
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
render: (args) => {
const [value, setValue] = useState(args.value);
return <ModelSelector {...args} onValueChange={setValue} value={value} />;
},
};
export const Sizes: Story = {
parameters: {
docs: {
description: {
story: 'The three trigger sizes, matching `MenuButton`.',
},
},
},
render: (args) => (
<FlexContainer alignItems='center' gap='l'>
{SIZES.map((size) => (
<ModelSelector
{...args}
id={`model-selector-${size}`}
key={size}
size={size}
/>
))}
</FlexContainer>
),
};
export const WithDescriptions: Story = {
parameters: {
docs: {
description: {
story:
'Options can carry a short description (and an `iconName`). One option is `disabled`.',
},
},
},
render: (args) => {
const [value, setValue] = useState('zappy');
return (
<ModelSelector
{...args}
onValueChange={setValue}
options={MODELS_WITH_DETAILS}
value={value}
/>
);
},
};
export const Disabled: Story = {
args: { disabled: true },
};
Model Selector
A new component built on the local MenuButton (trigger, popover, keyboard and focus behavior come from it).
Net-new componentOpen in Storybook