feat(ui): migrate Avatar from Base UI with updated size scale

Removed Base UI dependency from Avatar component and reimplemented
with native HTML elements. Updated size scale with new x-small and
x-large options.

Breaking changes:

- Base UI-specific props (render, etc.) are no longer supported
- Component now uses native div/img elements instead of Base UI primitives
- Size scale updated: large changed from 3rem to 2.5rem
- Added x-small (1.25rem) and x-large (3rem) sizes

Migration:

- <Avatar src="..." name="..." render={...} />
+ <Avatar src="..." name="..." />

- <Avatar size="large" />
+ <Avatar size="x-large" />

New features:

- Added purpose prop with 'informative' (default) and 'decoration' options
- Informative avatars announce name to screen readers
- Decorative avatars hidden from screen readers (use when name appears adjacent)
- Five size options: x-small, small, medium, large, x-large

Documentation updates:

- Updated size examples to show all five sizes
- Added Purpose story and documentation
- Updated prop definitions and usage examples
- Updated changeset with migration guide for size changes

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2025-10-24 17:53:00 +02:00
parent 8524186b21
commit 539cf2690a
8 changed files with 202 additions and 39 deletions
+12
View File
@@ -7,6 +7,7 @@ import {
snippetUsage,
snippetSizes,
snippetFallback,
snippetPurpose,
} from './avatar.props';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
@@ -58,6 +59,17 @@ If the image is not available, the avatar will show the initials of the name.
code={snippetFallback}
/>
### The `purpose` prop
Control how the avatar is announced to screen readers using the `purpose` prop.
<Snippet
align="center"
py={4}
preview={<AvatarSnippet story="Purpose" />}
code={snippetPurpose}
/>
<Theming component="Avatar" />
<ChangelogComponent component="avatar" />
+44 -1
View File
@@ -10,10 +10,15 @@ export const avatarPropDefs: Record<string, PropDef> = {
},
size: {
type: 'enum',
values: ['small', 'medium', 'large'],
values: ['x-small', 'small', 'medium', 'large', 'x-large'],
default: 'medium',
responsive: true,
},
purpose: {
type: 'enum',
values: ['informative', 'decoration'],
default: 'informative',
},
...classNamePropDefs,
...stylePropDefs,
};
@@ -26,6 +31,10 @@ export const snippetUsage = `import { Avatar } from '@backstage/ui';
/>`;
export const snippetSizes = `<Flex gap="4" direction="column">
<Avatar
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille" size="x-small"
/>
<Avatar
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille" size="small"
@@ -38,9 +47,43 @@ export const snippetSizes = `<Flex gap="4" direction="column">
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille" size="large"
/>
<Avatar
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille" size="x-large"
/>
</Flex>`;
export const snippetFallback = `<Avatar
src="https://avatars.githubusercontent.com/u/15406AAAAAAAAA"
name="Charles de Dreuille"
/>`;
export const snippetPurpose = `<Flex direction="column" gap="4">
<Flex direction="column" gap="1">
<Text variant="title-x-small">Informative (default)</Text>
<Text variant="body-medium">
Use when avatar appears alone. Announced as "Charles de Dreuille" to screen readers:
</Text>
<Flex gap="2" align="center">
<Avatar
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille"
purpose="informative"
/>
</Flex>
</Flex>
<Flex direction="column" gap="1">
<Text variant="title-x-small">Decoration</Text>
<Text variant="body-medium">
Use when name appears adjacent to avatar. Hidden from screen readers to avoid redundancy:
</Text>
<Flex gap="2" align="center">
<Avatar
src="https://avatars.githubusercontent.com/u/1540635?v=4"
name="Charles de Dreuille"
purpose="decoration"
/>
<Text>Charles de Dreuille</Text>
</Flex>
</Flex>
</Flex>`;