← All proposals

Agent avatar

Start from the PDS v2 Avatar (src/components/identity/Avatar, branch v2.x), renamed AgentAvatar (class pds-agent-avatar).

Net-new componentOpen in Storybook

proposals/AgentAvatar/AgentAvatar.stories.tsx141 lines · View on GitHub
import { Avatar, FlexContainer } from '@pantheon-systems/pds-toolkit-react';
import { Meta, StoryObj } from '@storybook/react-vite';

import { AgentAvatar } from './AgentAvatar';

const meta: Meta<typeof AgentAvatar> = {
	title: 'Proposals/Identity/Agent Avatar',
	component: AgentAvatar,
	tags: ['new-pattern'],
	parameters: {
		docs: {
			description: {
				component:
					'New pattern. Based on the PDS Avatar. Identifies an AI agent as the actor in activity logs, comment threads and similar places. A dark circle with a lightning-bolt icon and an AI-gradient ring, so it is never mistaken for a human avatar (an image or per-user color, no ring).',
			},
		},
	},
	argTypes: {
		ariaLabel: { table: { category: 'Base attributes' } },
		className: { table: { category: 'Base attributes' } },
		hasHalo: { table: { category: 'Component configuration' } },
		iconName: {
			control: 'select',
			options: ['zappy', 'sparklesSolid'],
			table: { category: 'Component configuration' },
		},
		label: { table: { category: 'Content' } },
		linkContent: { table: { category: 'Content' } },
		shape: {
			control: 'select',
			table: { category: 'Component configuration' },
		},
		size: {
			control: 'select',
			options: ['xs', 's', 'm', 'l', 'xl'],
			table: { category: 'Component configuration' },
		},
	},
	args: {
		hasHalo: true,
		iconName: 'zappy',
		label: 'Agent',
		size: 'm',
	},
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {};

export const WithLink: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Wraps the avatar in a navigable element using `linkContent` and `ariaLabel`, for example to the agent’s settings or run history.',
			},
		},
	},
	args: {
		ariaLabel: 'Go to agent details',
		linkContent: <a href='#'></a>,
	},
};

export const Icons: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'`iconName` picks the icon: `zappy` (default) for Pantheon agents, `sparklesSolid` for other (third-party) agents.',
			},
		},
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='l'>
			<FlexContainer alignItems='center' gap='s'>
				<AgentAvatar {...args} iconName='zappy' />
				<span>zappy: Pantheon agent</span>
			</FlexContainer>
			<FlexContainer alignItems='center' gap='s'>
				<AgentAvatar {...args} iconName='sparklesSolid' />
				<span>sparklesSolid: other (third-party) agent</span>
			</FlexContainer>
		</FlexContainer>
	),
};

export const Square: Story = {
	args: { shape: 'square' },
};

export const Sizes: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'`size` sets the avatar to `xs` (16px), `s` (20px, the default), `m` (24px), `l` (32px), or `xl` (40px).',
			},
		},
	},
	render: (args) => (
		<FlexContainer alignItems='center' gap='m'>
			<AgentAvatar {...args} size='xs' />
			<AgentAvatar {...args} size='s' />
			<AgentAvatar {...args} size='m' />
			<AgentAvatar {...args} size='l' />
			<AgentAvatar {...args} size='xl' />
		</FlexContainer>
	),
};

export const NextToHumans: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'The point of the pattern: a human avatar (circle, per-user color) beside the agent avatar (dark fill, gradient ring, bolt) in a short activity log.',
			},
		},
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='m'>
			<FlexContainer alignItems='center' gap='s'>
				<Avatar hasUserFallback size={args.size} uniqueId='bella@example.com' />
				<span>Bella updated the environment variables</span>
			</FlexContainer>
			<FlexContainer alignItems='center' gap='s'>
				<AgentAvatar {...args} />
				<span>Agent merged the dependency update</span>
			</FlexContainer>
			<FlexContainer alignItems='center' gap='s'>
				<Avatar hasUserFallback size={args.size} uniqueId='louis@example.com' />
				<span>Louis approved the deploy</span>
			</FlexContainer>
		</FlexContainer>
	),
};