|
| 1 | +import { |
| 2 | + Canvas, |
| 3 | + ColorItem, |
| 4 | + ColorPalette, |
| 5 | + Controls, |
| 6 | + Markdown, |
| 7 | + Meta, |
| 8 | + Subtitle, |
| 9 | + Title, |
| 10 | +} from '@storybook/addon-docs/blocks' |
| 11 | + |
| 12 | +import * as AvatarStories from './avatar.stories' |
| 13 | + |
| 14 | +<Meta of={AvatarStories} /> |
| 15 | + |
| 16 | +<Title /> |
| 17 | + |
| 18 | +<Subtitle>Image, initials, and empty-state avatar primitive.</Subtitle> |
| 19 | + |
| 20 | +## Basic usage |
| 21 | + |
| 22 | +Use `Avatar` for people by default. Pass `size`, `name`, and an optional |
| 23 | +`image`; `name` supplies the default accessible label, the initials fallback, |
| 24 | +and the deterministic meta color used when initials render. |
| 25 | + |
| 26 | +<Canvas of={AvatarStories.Default} /> |
| 27 | + |
| 28 | +## Migrating from the legacy API |
| 29 | + |
| 30 | +The previous Avatar API accepted `user`, `avatarUrl`, `colorList`, string or |
| 31 | +responsive `size` values, and a deprecated `className`. The current API uses |
| 32 | +direct identity props instead: |
| 33 | + |
| 34 | +<Markdown>{` |
| 35 | +| Legacy prop | Current API | |
| 36 | +| ------------------------------ | ------------------------------------------------------------------------ | |
| 37 | +| \`user.name\` | \`name\` | |
| 38 | +| \`avatarUrl\` | \`image\` | |
| 39 | +| \`user.email\` | No replacement. Email is no longer used for initials or color selection. | |
| 40 | +| \`colorList\` | Customize the CSS custom properties listed below. | |
| 41 | +| \`size="l"\` or responsive sizes | Pass one supported numeric CSS-pixel \`size\`. | |
| 42 | +| \`className\` | \`exceptionallySetClassName\` | |
| 43 | +`}</Markdown> |
| 44 | + |
| 45 | +```tsx |
| 46 | +<Avatar size={36} name={user.name} image={avatarUrl} exceptionallySetClassName={className} /> |
| 47 | +``` |
| 48 | + |
| 49 | +## Initials fallback |
| 50 | + |
| 51 | +When `image` is not supplied, cannot be resolved, or every responsive image |
| 52 | +candidate fails, Avatar falls back to initials derived from `name`. Names are |
| 53 | +normalized before initials are generated. |
| 54 | + |
| 55 | +<Canvas of={AvatarStories.InitialsFallback} /> |
| 56 | + |
| 57 | +## Workspace avatars |
| 58 | + |
| 59 | +Use `shape="rounded"` for workspace-like entities. Product code can wrap |
| 60 | +Avatar with a small convention component when a surface always represents the |
| 61 | +same kind of entity. |
| 62 | + |
| 63 | +<Canvas of={AvatarStories.WorkspaceAvatar} /> |
| 64 | + |
| 65 | +## Image sources |
| 66 | + |
| 67 | +Pass a string for a single image URL, or a source map keyed by intrinsic image |
| 68 | +width. Source maps render native `srcSet` width descriptors and a `sizes` hint |
| 69 | +based on the selected avatar size. |
| 70 | + |
| 71 | +<Canvas of={AvatarStories.ImageSources} /> |
| 72 | + |
| 73 | +## Sizes |
| 74 | + |
| 75 | +Avatar supports a fixed set of CSS pixel sizes. Use one of the supported |
| 76 | +numeric values instead of styling the avatar dimensions from the outside. |
| 77 | + |
| 78 | +<Canvas of={AvatarStories.Sizes} /> |
| 79 | + |
| 80 | +## Accessibility |
| 81 | + |
| 82 | +Images default to `name` for alt text. Pass `alt` when the visual needs a more |
| 83 | +specific label, and pass `alt=""` when the avatar is decorative. |
| 84 | + |
| 85 | +<Canvas of={AvatarStories.Accessibility} /> |
| 86 | + |
| 87 | +## Playground |
| 88 | + |
| 89 | +Use the controls to inspect the component API and common image/name |
| 90 | +combinations. |
| 91 | + |
| 92 | +<Canvas of={AvatarStories.Playground} /> |
| 93 | + |
| 94 | +### API |
| 95 | + |
| 96 | +<Controls of={AvatarStories.Playground} /> |
| 97 | + |
| 98 | +## Custom properties |
| 99 | + |
| 100 | +The following CSS custom properties are available to customize the avatar |
| 101 | +component appearance. The values shown below are the default values. |
| 102 | + |
| 103 | +<Canvas of={AvatarStories.MetaColors} /> |
| 104 | + |
| 105 | +### Customizable properties |
| 106 | + |
| 107 | +#### Avatar colors |
| 108 | + |
| 109 | +<ColorPalette> |
| 110 | + <ColorItem title="--reactist-avatar-initials-color" colors={['#ffffff']} /> |
| 111 | + <ColorItem title="--reactist-avatar-border-tint" colors={['#0000001a']} /> |
| 112 | + <ColorItem title="--reactist-avatar-empty-fill" colors={['#e6e6e6']} /> |
| 113 | +</ColorPalette> |
| 114 | + |
| 115 | +#### Avatar meta colors |
| 116 | + |
| 117 | +<ColorPalette> |
| 118 | + <ColorItem title="--reactist-avatar-meta-0-fill" colors={['#b8255f']} /> |
| 119 | + <ColorItem title="--reactist-avatar-meta-0-on-idle-tint" colors={['#ffffff']} /> |
| 120 | + <ColorItem title="--reactist-avatar-meta-1-fill" colors={['#dc4c3e']} /> |
| 121 | + <ColorItem title="--reactist-avatar-meta-1-on-idle-tint" colors={['#ffffff']} /> |
| 122 | + <ColorItem title="--reactist-avatar-meta-2-fill" colors={['#f48318']} /> |
| 123 | + <ColorItem title="--reactist-avatar-meta-2-on-idle-tint" colors={['#ffffff']} /> |
| 124 | + <ColorItem title="--reactist-avatar-meta-3-fill" colors={['#fecf05']} /> |
| 125 | + <ColorItem title="--reactist-avatar-meta-3-on-idle-tint" colors={['#202020']} /> |
| 126 | + <ColorItem title="--reactist-avatar-meta-4-fill" colors={['#aeb83a']} /> |
| 127 | + <ColorItem title="--reactist-avatar-meta-4-on-idle-tint" colors={['#ffffff']} /> |
| 128 | + <ColorItem title="--reactist-avatar-meta-5-fill" colors={['#7ecc48']} /> |
| 129 | + <ColorItem title="--reactist-avatar-meta-5-on-idle-tint" colors={['#ffffff']} /> |
| 130 | + <ColorItem title="--reactist-avatar-meta-6-fill" colors={['#369307']} /> |
| 131 | + <ColorItem title="--reactist-avatar-meta-6-on-idle-tint" colors={['#ffffff']} /> |
| 132 | + <ColorItem title="--reactist-avatar-meta-7-fill" colors={['#52ccb8']} /> |
| 133 | + <ColorItem title="--reactist-avatar-meta-7-on-idle-tint" colors={['#ffffff']} /> |
| 134 | + <ColorItem title="--reactist-avatar-meta-8-fill" colors={['#148fad']} /> |
| 135 | + <ColorItem title="--reactist-avatar-meta-8-on-idle-tint" colors={['#ffffff']} /> |
| 136 | + <ColorItem title="--reactist-avatar-meta-9-fill" colors={['#3ab9e2']} /> |
| 137 | + <ColorItem title="--reactist-avatar-meta-9-on-idle-tint" colors={['#202020']} /> |
| 138 | + <ColorItem title="--reactist-avatar-meta-10-fill" colors={['#96c3eb']} /> |
| 139 | + <ColorItem title="--reactist-avatar-meta-10-on-idle-tint" colors={['#ffffff']} /> |
| 140 | + <ColorItem title="--reactist-avatar-meta-11-fill" colors={['#2a67e2']} /> |
| 141 | + <ColorItem title="--reactist-avatar-meta-11-on-idle-tint" colors={['#ffffff']} /> |
| 142 | + <ColorItem title="--reactist-avatar-meta-12-fill" colors={['#692ec2']} /> |
| 143 | + <ColorItem title="--reactist-avatar-meta-12-on-idle-tint" colors={['#ffffff']} /> |
| 144 | + <ColorItem title="--reactist-avatar-meta-13-fill" colors={['#ac30cc']} /> |
| 145 | + <ColorItem title="--reactist-avatar-meta-13-on-idle-tint" colors={['#ffffff']} /> |
| 146 | + <ColorItem title="--reactist-avatar-meta-14-fill" colors={['#eb96c8']} /> |
| 147 | + <ColorItem title="--reactist-avatar-meta-14-on-idle-tint" colors={['#ffffff']} /> |
| 148 | + <ColorItem title="--reactist-avatar-meta-15-fill" colors={['#e05095']} /> |
| 149 | + <ColorItem title="--reactist-avatar-meta-15-on-idle-tint" colors={['#ffffff']} /> |
| 150 | + <ColorItem title="--reactist-avatar-meta-16-fill" colors={['#c9766f']} /> |
| 151 | + <ColorItem title="--reactist-avatar-meta-16-on-idle-tint" colors={['#ffffff']} /> |
| 152 | + <ColorItem title="--reactist-avatar-meta-17-fill" colors={['#808080']} /> |
| 153 | + <ColorItem title="--reactist-avatar-meta-17-on-idle-tint" colors={['#ffffff']} /> |
| 154 | + <ColorItem title="--reactist-avatar-meta-18-fill" colors={['#999999']} /> |
| 155 | + <ColorItem title="--reactist-avatar-meta-18-on-idle-tint" colors={['#ffffff']} /> |
| 156 | + <ColorItem title="--reactist-avatar-meta-19-fill" colors={['#ccae96']} /> |
| 157 | + <ColorItem title="--reactist-avatar-meta-19-on-idle-tint" colors={['#ffffff']} /> |
| 158 | +</ColorPalette> |
| 159 | + |
| 160 | +### Component-owned variables |
| 161 | + |
| 162 | +Avatar's size classes set these variables from the `size` prop. They are |
| 163 | +listed for completeness, but consumers should prefer the component props |
| 164 | +instead of overriding them directly. |
| 165 | + |
| 166 | +```css |
| 167 | +.avatar { |
| 168 | + --reactist-avatar-size: 36px; |
| 169 | + --reactist-avatar-rounded-radius: 5px; |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +## What the consumer owns |
| 174 | + |
| 175 | +- **Identity data** — choose the `name`, `image`, and any custom `alt` text. |
| 176 | +- **Source selection** — provide either one URL or a width-keyed source map. |
| 177 | +- **Entity convention** — choose `shape="circle"` for people and |
| 178 | + `shape="rounded"` for workspace-like entities. |
| 179 | +- **Decorative usage** — pass `alt=""` when surrounding UI already names the |
| 180 | + represented entity. |
| 181 | +- **Persistence and fetching** — Avatar does not load, cache, or persist remote |
| 182 | + user/workspace data. |
| 183 | + |
| 184 | +## Accessibility |
| 185 | + |
| 186 | +- `name` becomes the default image `alt` text and initials `aria-label`. |
| 187 | +- `alt` overrides the accessible label for both image and initials rendering. |
| 188 | +- `alt=""` marks image and initials avatars as decorative. |
| 189 | +- An avatar with no `name` and no `image` renders as an empty decorative visual. |
0 commit comments