import { useEffect, useState } from 'react';
import { Meta, StoryObj } from '@storybook/react-vite';
import { ThinkingState } from './ThinkingState';
const meta: Meta<typeof ThinkingState> = {
tags: ['new-pattern'],
title: 'Proposals/Thinking State',
component: ThinkingState,
parameters: {
docs: {
description: {
component:
'**New pattern:** not in PDS v2 today. Shows that an agent is working: an icon, what it is doing, and how long it has been at it.',
},
},
},
argTypes: {
className: { table: { category: 'Base attributes' } },
iconName: {
control: 'select',
options: ['zappy', 'sparklesSolid'],
table: { category: 'Content' },
},
label: { control: 'text', table: { category: 'Content' } },
size: {
control: 'select',
options: ['xs', 's', 'm'],
table: { category: 'Component configuration' },
},
showTimer: {
control: 'boolean',
table: { category: 'Component configuration' },
},
state: {
control: 'select',
options: ['active', 'completed', 'stopped'],
table: { category: 'State' },
},
time: { control: 'text', table: { category: 'Content' } },
},
args: {
iconName: 'zappy',
label: 'Thinking...',
showTimer: false,
size: 's',
state: 'active',
time: '17.1s',
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {};
export const Completed: Story = {
args: {
label: 'Thought for 17.1s',
state: 'completed',
},
parameters: {
docs: {
description: {
story:
'When the agent has finished, set `state` to `completed` and pass a past-tense label. The shimmer and the icon pulse stop. The consumer writes the wording, including the duration.',
},
},
},
};
export const Stopped: Story = {
args: {
label: 'Stopped after 17.1s',
showTimer: false,
state: 'stopped',
},
parameters: {
docs: {
description: {
story:
'When the user stops the agent, set `state` to `stopped`. There is no motion, and the icon and label are muted so it reads as cut off, not finished. The consumer writes the wording.',
},
},
},
};
export const LiveTimer: Story = {
parameters: {
docs: {
description: {
story:
'The consumer owns the timer and passes the formatted time. Here a story-only counter ticks every 100ms while `state` is `active`.',
},
},
},
render: (args) => {
const [tenths, setTenths] = useState(0);
useEffect(() => {
if (args.state !== 'active') return;
const timer = setInterval(() => setTenths((t) => t + 1), 100);
return () => clearInterval(timer);
}, [args.state]);
return (
<ThinkingState
{...args}
showTimer
time={`${(tenths / 10).toFixed(1)}s`}
/>
);
},
};
Thinking State
A small inline status: the agent icon (Zappy by default), a label ("Thinking..."), and the elapsed time in the code font ("17.1s").
Net-new componentOpen in Storybook