← All proposals

Avatar Label

The PDS v2 AvatarLabel (src/components/identity/AvatarLabel, branch v2.x) with every Avatar replaced by the Agent Avatar proposal.

Net-new componentOpen in Storybook

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

import { AvatarLabel } from './AvatarLabel';

const meta: Meta<typeof AvatarLabel> = {
	title: 'Proposals/Identity/Avatar Label',
	component: AvatarLabel,
	parameters: {
		docs: {
			description: {
				component:
					'Proposal, based on the PDS Avatar Label, with the Agent Avatar in place of the human Avatar. An agent avatar paired with the agent\u2019s name.',
			},
		},
	},
	argTypes: {
		attribution: {
			control: 'text',
			table: {
				category: 'Content',
			},
		},
		avatarProps: {
			table: {
				category: 'Content',
			},
		},
		label: {
			table: {
				category: 'Content',
			},
		},
		linkContent: {
			table: {
				category: 'Content',
			},
		},
		hasAvatar: {
			control: 'boolean',
			table: {
				category: 'Component configuration',
			},
		},
		ariaLabel: {
			table: {
				category: 'Base attributes',
			},
		},
		size: {
			control: 'select',
			options: ['xs', 's', 'm'],
			table: {
				category: 'Component configuration',
			},
		},
		className: {
			table: {
				category: 'Base attributes',
			},
		},
	},
	args: {
		avatarProps: { label: 'Agent' },
		hasAvatar: true,
		label: 'Zappy',
		size: 's',
	},
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
	args: {},
};

export const Sizes: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'`size` controls the avatar size and the label text size together. Use `xs` in dense contexts like table cells, `m` on larger surfaces.',
			},
		},
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='m'>
			<AvatarLabel {...args} size='xs' />
			<AvatarLabel {...args} size='s' />
			<AvatarLabel {...args} size='m' />
		</FlexContainer>
	),
};

export const WithAttribution: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'`attribution` says who the agent is acting for. Pass the whole phrase, translated: the label shows the agent, and the attribution follows in the secondary text color. It truncates before the name does.',
			},
		},
	},
	args: {
		attribution: 'on behalf of alex@example.com',
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='m'>
			<AvatarLabel {...args} size='xs' />
			<AvatarLabel {...args} size='s' />
			<AvatarLabel {...args} size='m' />
		</FlexContainer>
	),
};

export const WithoutAvatar: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Set `hasAvatar` to `false` to show only the name and attribution, for example when the avatar is already shown on a neighboring item. The avatar `label` stays in the page as screen-reader-only text, so it is still announced as an agent.',
			},
		},
	},
	args: {
		attribution: 'on behalf of alex@example.com',
		hasAvatar: false,
	},
	render: (args) => (
		<FlexContainer flexDirection='column' gap='m'>
			<AvatarLabel {...args} size='xs' />
			<AvatarLabel {...args} size='s' />
			<AvatarLabel {...args} size='m' />
		</FlexContainer>
	),
};

export const ThirdPartyAgent: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'`avatarProps` passes through directly to the underlying Agent Avatar, for example `iconName` to show `sparklesSolid` for an other (third-party) agent.',
			},
		},
	},
	args: {
		avatarProps: { iconName: 'sparklesSolid', label: 'Agent' },
		label: 'Sonnet 5.5',
	},
};

export const WithLink: Story = {
	parameters: {
		docs: {
			description: {
				story:
					'Wraps the whole component in a navigable element using `linkContent` and `ariaLabel`. Unlike wrapping just the avatar, clicking anywhere on the avatar or label navigates.',
			},
		},
	},
	args: {
		linkContent: <a href='#'></a>,
		ariaLabel: 'Go to agent details',
	},
};