import type { Meta, StoryFn } from '@storybook/react' import React from 'react' import { Avatar } from './index' type ComponentProps = React.ComponentProps const meta: Meta = { title: 'Avatar', component: Avatar, parameters: { layout: 'centered', }, } export default meta const Template: StoryFn = (args) => { return (
) } // Loose single stories (Default/WithoutImage/Starred) are each a cell of the // States grid; the per-size stories (SmallSize…ExtraLargeSize) are cells of the // VariousSizes grid; AIActive is the size=40 cell of AIActiveVariousSizes. // Keep them in Storybook for browsing but skip in Chromatic. const skipInChromatic = { chromatic: { disableSnapshot: true } } // Deterministic local avatar for the States grid so a pravatar network flake // can't diff the snapshot. Individual stories keep their remote images (they're // skipped in Chromatic anyway). const LOCAL_AVATAR = '/image-thumbnail.jpg' export const Default: StoryFn = Template.bind({}) Default.args = { id: 'user-1', name: 'Alice Johnson', image: 'https://i.pravatar.cc/150?img=1', } Default.parameters = skipInChromatic export const AIActive: StoryFn = Template.bind({}) AIActive.args = { id: 'ai-agent', name: 'AI Assistant', image: 'https://i.pravatar.cc/150?img=12', dmAgentEnabled: true, } AIActive.parameters = skipInChromatic export const WithoutImage: StoryFn = Template.bind({}) WithoutImage.args = { id: 'user-2', name: 'Bob Smith', } WithoutImage.parameters = skipInChromatic export const Starred: StoryFn = Template.bind({}) Starred.args = { id: 'user-9', name: 'Kaiya Korsgaard', starred: true, } Starred.parameters = skipInChromatic export const States: StoryFn = () => { const cells: { label: string; props: ComponentProps }[] = [ { label: 'Default (image)', props: { id: 'user-1', name: 'Alice Johnson', image: LOCAL_AVATAR }, }, { label: 'Without image', props: { id: 'user-2', name: 'Bob Smith' }, }, { label: 'Starred', props: { id: 'user-9', name: 'Kaiya Korsgaard', starred: true }, }, ] return (
{cells.map(({ label, props }) => (
{label}
))}
) } export const SmallSize: StoryFn = Template.bind({}) SmallSize.args = { id: 'user-3', name: 'Carol Williams', size: 20, } SmallSize.parameters = skipInChromatic export const MediumSize: StoryFn = Template.bind({}) MediumSize.args = { id: 'user-4', name: 'David Brown', size: 32, } MediumSize.parameters = skipInChromatic export const DefaultSize: StoryFn = Template.bind({}) DefaultSize.args = { id: 'user-5', name: 'Emma Davis', size: 40, } DefaultSize.parameters = skipInChromatic export const LargeSize: StoryFn = Template.bind({}) LargeSize.args = { id: 'user-6', name: 'Frank Miller', size: 56, } LargeSize.parameters = skipInChromatic export const ExtraLargeSize: StoryFn = Template.bind({}) ExtraLargeSize.args = { id: 'user-7', name: 'Grace Lee', size: 80, } ExtraLargeSize.parameters = skipInChromatic // Avatars don't render the participant name in the bubble — only the initial. // LongName stays as a Storybook fixture for documentation but adds no visual // regression value beyond what Default + WithoutImage already cover. export const LongName: StoryFn = Template.bind({}) LongName.args = { id: 'user-8', name: 'Alexander Christopher Wellington-Montgomery III', } LongName.parameters = { chromatic: { disableSnapshot: true } } export const DifferentColors: StoryFn = () => { const users = [ { id: 'user-1', name: 'Alice Anderson' }, { id: 'user-2', name: 'Bob Brown' }, { id: 'user-3', name: 'Carol Chen' }, { id: 'user-4', name: 'David Davis' }, { id: 'user-5', name: 'Emma Evans' }, { id: 'user-6', name: 'Frank Foster' }, { id: 'user-7', name: 'Grace Green' }, { id: 'user-8', name: 'Henry Harris' }, ] return (
{users.map((user) => (
{user.name}
))}
) } // Showcase grid that crosses image-present/absent with different users. // Each individual case is already covered by `Default` (image) and // `WithoutImage` (initial) — skip the showcase in Chromatic so a single // pravatar avatar flake doesn't diff the whole grid. export const MixedAvatars: StoryFn = () => { const users = [ { id: 'user-1', name: 'Alice Anderson', image: 'https://i.pravatar.cc/150?img=1', }, { id: 'user-2', name: 'Bob Brown' }, { id: 'user-3', name: 'Carol Chen', image: 'https://i.pravatar.cc/150?img=3', }, { id: 'user-4', name: 'David Davis' }, { id: 'user-5', name: 'Emma Evans', image: 'https://i.pravatar.cc/150?img=5', }, { id: 'user-6', name: 'Frank Foster' }, ] return (
{users.map((user) => (
{user.name}
))}
) } MixedAvatars.parameters = { chromatic: { disableSnapshot: true } } export const VariousSizes: StoryFn = () => { const sizes = [20, 32, 40, 56, 80] return (
{sizes.map((size) => (
{size}px
))}
) } export const AIActiveVariousSizes: StoryFn = () => { const sizes = [20, 32, 40, 56, 80] return (
{sizes.map((size) => (
{size}px
))}
) }