跳到主要内容
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
开始使用WebReactSwiftUIJetpack ComposeFlutterReact Native预设你自己的设计系统与 AI 代理一起使用 Tanrei品牌设计令牌设计系统与定制Theme Studio颜色字体排印图标形状层级动效交互状态行为布局无障碍文字颜色令牌字阶令牌形状令牌层级令牌动效令牌状态令牌间距与度量令牌组件按钮主操作按钮分段按钮按钮组带菜单的按钮工具栏复制按钮复选框单选按钮开关纸片(Chip)菜单滑块滑块字段日历DateTimePicker字段组单选组复选框组下拉选择框下拉选择字段菜单栏文件上传文件选择器 进阶放置区文本输入框 进阶文本字段纸片字段字段组合框 进阶组合框字段数字输入框 进阶数字字段颜色输入框 进阶颜色字段一次性验证码输入框 进阶一次性验证码字段嵌入式文本输入框 进阶聊天输入栏卡片分隔线模态层 进阶对话框列表列表行底部面板侧边面板轮播代码块表格弹出框步骤折叠面板描述列表图示应用外壳页头树视图时间线图片预览调整手柄可调整大小的框滚动区域徽标进度指示器计量条数字滚动器加载指示器消息条(Snackbar)工具提示键盘快捷键标签(Tag)行内代码提示块(Callout)头像空状态标签组(Tag group)骨架屏文件项色块跑马灯文本标签页标签页视图应用栏导航栏导航抽屉搜索链接分页上一页/下一页链接步骤条面包屑目录链接卡片FAB 菜单状态Tanrei 是如何构建的参与贡献许可与致谢
首页组件头像

头像

用一张小图片代表一个人、一个团队或一个项目;没有图片时,用姓名缩写或一个字形;形状是圆形或圆角方形,有三种尺寸。多个头像可以显示成相互交叠的一组,并数出其余的数量。它是一张图片,从不是控件。

content_copy以 Markdown 格式查看
类别
信息传达
令牌
comp.avatar
层级
基础

概览

Web
tanrei-avatar
schedule
SwiftUI
TanreiAvatar
radio_button_unchecked
Jetpack Compose
TanreiAvatar
radio_button_unchecked
Flutter
TanreiAvatar
radio_button_unchecked
React Native
Avatar
radio_button_unchecked

生成自 docs/status/status.json, specs/avatar.spec.json

姓名缩写、字形、方形,以及一组

头像表明某样东西属于谁:帖子的作者、对话中的人、任务的负责人。它绘制一张图片,没有图片时也总有东西可画。它从不响应指针、按键或焦点。

在 Web 上它是 <tanrei-avatar>,多个放在一起则是 <tanrei-avatar-group>。其他平台尚未实现。

用法

<!-- 单独使用:由它的标签命名。 -->
<tanrei-avatar label="李华" initials="李" src="/people/lihua.jpg"></tanrei-avatar>

<!-- 在写着同一个姓名的文本旁边:设为装饰性的,这样姓名只读一次。 -->
<p>
  <tanrei-avatar decorative size="small" initials="李" src="/people/lihua.jpg"></tanrei-avatar>
  李华
</p>

<!-- 不是某一个人:用方形,并配上你自己的字形。 -->
<tanrei-avatar label="构建服务" shape="square"><span slot="icon">smart_toy</span></tanrei-avatar>

<!-- 六名成员,最多四个方框:三名成员和“+3”。 -->
<tanrei-avatar-group label="评审人" max="4" overflow-label="还有 {count} 人">
  <tanrei-avatar label="李华" initials="李"></tanrei-avatar>
  <tanrei-avatar label="王芳" initials="王"></tanrei-avatar>
  <!-- … -->
</tanrei-avatar-group>

<!-- 在脚本到达之前,这份样式表为每个头像保留位置。 -->
<link rel="stylesheet" href="@tanrei/web/avatar.css" />
<script type="module">
  import '@tanrei/web/components/avatar';
</script>
import { Avatar, AvatarGroup } from '@tanrei/react';

<Avatar label={person.name} initials={person.initials} src={person.picture} />

<AvatarGroup label="评审人" max={4} total={reviewerCount} overflowLabel="还有 {count} 人">
  {reviewers.slice(0, 3).map((person) => (
    <Avatar key={person.id} label={person.name} initials={person.initials} src={person.picture} />
  ))}
</AvatarGroup>

规格

三种尺寸,两种形状

构成

部件 说明
1 container The square box of the avatar's size, clipped to a circle or to a rounded square, with a quiet fill that shows behind the initials, the glyph, a picture that is still loading and the transparent parts of a picture. It carries no state: nothing about it answers a pointer, a press or focus.
2 image · 可选 The picture the product names by its address, filling the box and clipped to its shape. Drawn once it has loaded.
3 label · 可选 The initials the product gives, drawn at the centre of the box where there is no picture to show. A picture of a name, not text to be read: the name is the avatar's label.
4 icon · 可选 The fallback glyph, at the centre of the box, where there is neither a picture nor initials: the glyph the product names, or the system's own (a person for a circle, a neutral mark for a square).
5 group · 可选 Several avatars drawn as one row in which each lies a little over the one before it, with a gap around each so that two pictures are read as two. The group gives its avatars their size and shape.
6 overflow · 可选 The last box of a group that does not draw all its members: an avatar-sized box in the fallback's colors holding a plus sign and the number of members not drawn.

属性

属性 类型 默认值 说明
src string "" The address of the picture. Empty, or a picture that has not loaded or cannot be loaded, draws the fallback: initials where the product gave some, otherwise a glyph.
label string "" The name of the person or the thing the avatar stands for, in full ("Ada Lovelace", "Design team"). Not drawn: it is the avatar's accessible name while decorative is false. In the group form it is the group's name ("Reviewers").
initials string "" The one or two characters drawn where there is no picture ("AL", "山"). The product makes them: which characters stand for a name depends on its writing system and its order, which the avatar cannot know. Never read by assistive technology.
decorative boolean false True hides the avatar from assistive technology, for an avatar that stands beside the same name in visible text (a byline, a list row, a comment's header), so the name is read once. False, for an avatar that stands alone, exposes it as an image named by label. Ignored for the members of a group.
size small | medium | large "medium" Small (24) stands beside one line of text: a byline, a table cell, a mention. Medium (40) is a list row's or a comment's avatar. Large (56) heads a person's own page or card. A group gives its size to every member. A design system may add values.
shape circle | square "circle" Circle is a person. Square, a rounded square, is something that is not one person: a team, a project, an organisation, a bot. A group gives its shape to every member. A design system may add values.
max number 0 Group form only. The most boxes the group draws, the overflow box included; 0 draws every member. A whole number of 2 or more: with more members than this, the group draws one fewer member than max and then the overflow box.
total number null Group form only. How many members there are, where the product gives the group fewer than exist (the first five of a team of two hundred). Null counts the members given.
overflowLabel string "" Group form only. What assistive technology reads for the overflow box: the whole sentence in the product's language, with one place, {count}, which the group fills with the number of members not drawn ("{count} more", "ほか{count}人"). Written once as the product's words, it serves every group. A sentence that is right for every number, or a prop set per count where the language needs another form for one. Empty reads the product's words; with neither, the drawn text ("+12").

插槽

插槽 说明
icon The fallback glyph: a glyph of the system's icon set, by name, drawn through the platform's icon helper where there is neither a picture nor initials. Empty draws the system's own fallback glyph.

条目

该组件重复排列的条目种类。测试样例按顺序列出条目;各平台以各自的惯用方式为每个种类命名。

member

One avatar of a group: an avatar with its own picture, name, initials and glyph, drawn at the group's size and shape.

属性 类型 默认值 说明
src string "" The address of the member's picture.
label string "" The member's name. Always exposed in a group: the names are what the group says.
initials string "" The member's initials, drawn where there is no picture.
规格 Web SwiftUI Jetpack Compose Flutter React Native
条目 tanrei-avatar TanreiAvatar TanreiAvatar TanreiAvatar Avatar
src · 属性 src url model image source
label · 属性 label name name name name
initials · 属性 initials initials initials initials initials
备注 A <tanrei-avatar> child of <tanrei-avatar-group>, with all of an avatar's own attributes and its icon slot. The group sets the member's size and shape and makes it named. A TanreiAvatar in the group's builder. A TanreiAvatar call in the group's content. A TanreiAvatar in the group's children. An <Avatar> child of <AvatarGroup>.

状态

行为

以 EARS 形式写成的需求。每个平台的实现都按这些 ID 逐条测试。需求原文取自规格文件,原样以英文呈现。

ID 需求
AVT-1 THE avatar SHALL draw a square box whose side is the container size of its size (comp.avatar.container.size.small for small, comp.avatar.container.size.medium for medium, comp.avatar.container.size.large for large), with the corners of its shape (comp.avatar.container.shape.circle for circle, comp.avatar.container.shape.square for square), never larger than half the box's side (a circle where the value is sys.shape.corner.full) and eased by sys.shape.corner-smoothing, filled with comp.avatar.container.color, and SHALL clip everything it draws to that shape. THE avatar SHALL lay itself out inline with the text or the row it is placed in, as one unbreakable box that the layout neither stretches nor shrinks, and SHALL draw no edge and no elevation.
AVT-2 THE avatar SHALL draw exactly one of three things at the centre of its box (and two only for the cross-fade in which its picture arrives, AVT-4), the first of these that it has: the picture src names, once that picture has loaded (AVT-3, AVT-4); else initials, where initials is not empty (AVT-5); else a glyph (AVT-6). THE avatar SHALL never draw an empty box, a broken-picture mark or the picture's address, and SHALL NOT make initials out of label.
AVT-3 WHILE the picture of src has loaded THE avatar SHALL draw it over the whole box, scaled so that it covers the box with its proportions kept and its centre on the box's centre, clipped to the box's shape, over comp.avatar.container.color (which shows through the picture's transparent parts), and SHALL draw neither initials nor a glyph. THE avatar SHALL NOT mirror, tint or otherwise change the picture in any layout direction or scheme.
AVT-4 WHILE src is not empty and its picture has not yet loaded THE avatar SHALL draw its fallback (AVT-2) in the box, at the avatar's full size, so that nothing changes place when the picture arrives; WHEN the picture has loaded THE avatar SHALL fade it in over the fallback while the fallback fades out beneath it, one cross-fade of opacity over comp.avatar.motion.picture-duration on comp.avatar.motion.picture-easing (sys.motion.role.state.default and sys.motion.easing.state), in which nothing changes place or size; reduced motion keeps it, as a change of opacity is not motion (MOT-6). WHERE the picture loads while the avatar draws its first frames (MOT-3), or the platform already holds it when the avatar asks for it (in its memory of the pictures it has loaded), THE avatar SHALL draw it at once, in the fallback's place. IF the picture cannot be loaded THE avatar SHALL keep the fallback, SHALL NOT ask for the picture again by itself, and in debug builds SHALL report the address that failed. WHEN src changes THE avatar SHALL draw the fallback at once, until the new picture has loaded and fades in. WHILE src is empty THE avatar SHALL ask for nothing.
AVT-5 WHERE the avatar draws initials THE avatar SHALL set them on one line at the centre of the box, in the text style of its size (comp.avatar.label.typescale.small for small, comp.avatar.label.typescale.medium for medium, comp.avatar.label.typescale.large for large) and in comp.avatar.label.color, as the product wrote them: it SHALL NOT change their case, and SHALL draw no more than the first two characters as a reader counts them (grapheme clusters), reporting in debug builds a value that is longer. THE avatar SHALL lay the initials out as text of their own direction, isolated from the text around the avatar, and SHALL keep them from assistive technology.
AVT-6 WHERE the avatar draws a glyph THE avatar SHALL draw the glyph of its icon slot, or, where the slot is empty, the system's fallback glyph for its shape (person for circle, category for square), in a box of the icon size of its size (comp.avatar.icon.size.small for small, comp.avatar.icon.size.medium for medium, comp.avatar.icon.size.large for large) at the centre of the avatar, in comp.avatar.icon.color, with sys.icon.family.unselected and sys.icon.fill.unselected, sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max, and SHALL keep it from assistive technology.
AVT-7 THE avatar SHALL NOT take pointer, touch or keyboard input, SHALL NOT take focus or be a stop in the focus order, and SHALL NOT change anything it draws under a pointer, a press or focus: it has no hovered, focused, pressed, selected or disabled state, draws no state layer, no ripple and no focus indicator, and emits no event.
AVT-8 WHERE the avatar is placed inside an element that takes input (a link, a Button, a list item, a chip, a card that is pressed as a whole) THE avatar SHALL let input over it reach that element, SHALL stay as it is drawn while that element is hovered, focused or pressed (the state and the focus indicator are drawn by that element, on its own container), and SHALL NOT become a second target inside it; WHILE decorative is false THE avatar SHALL add its label to that element's content in reading order, so that a link or a Button that holds an avatar and nothing else is named by the avatar's label. An avatar that leads somewhere or opens something is that composition: the avatar has no destination and no action of its own.
AVT-9 WHILE decorative is false and label is not empty THE avatar SHALL be exposed to assistive technology as one image named by label, whether it draws a picture, initials or a glyph, and SHALL expose nothing else: not the initials, not the glyph's name, not the picture's address, and not its size or shape. WHILE decorative is true THE avatar SHALL expose nothing. IF decorative is false, label is empty and the product gives it no name (AVT-24) THE avatar SHALL expose nothing and in debug builds report that an avatar has no name.
AVT-10 WHEN label, initials, the icon slot's glyph, size or shape changes THE avatar SHALL draw and expose the new value at once, without a motion, and SHALL NOT announce the change by itself.
AVT-11 WHILE the text size is enlarged THE avatar SHALL keep its box at the container size of its size and its glyph at the size of AVT-6, and SHALL let its initials, and a group's count (AVT-17), follow their text style as it grows, no larger than the glyph's box of the same size (comp.avatar.icon.size.small for small, comp.avatar.icon.size.medium for medium, comp.avatar.icon.size.large for large), so that they still stand whole inside the box: an avatar is a picture and is enlarged with the page, not with the text, as a glyph's box is, while the letters it holds grow as far as the box leaves room for them.
AVT-12 WHERE the avatar is the anchor of a badge THE avatar SHALL be drawn exactly as it is without one: its square box is the anchor's bounds, the badge is placed by that box's top-end corner and drawn outside the avatar's clip (BDG-1, BDG-3, BDG-7), and the badge's label is added to the avatar's description after its name (BDG-8). THE avatar SHALL have no dot, count or status of its own.
AVT-13 WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE avatar SHALL draw an edge sys.border.hairline wide in the platform's text color inside its box, following its shape, and its initials or its glyph in that text color, so that a fallback whose fill the mode removes is still a bounded mark; THE avatar SHALL leave a picture's own colors as they are.
AVT-14 THE avatar SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the avatar is shown THE avatar SHALL draw itself for the new direction at once, without a motion of its own, keeping what it shows. A single avatar is the same in both directions but for its glyph (AVT-15): its picture is never mirrored and its initials keep their own order (AVT-5).
AVT-15 WHERE the layout direction is right-to-left THE avatar SHALL draw the glyph of its icon slot mirrored left to right exactly when the system's icon set marks that glyph's name as mirrored or the product forces mirroring for that use, and unmirrored when the product forbids it: the icon helper mirrors the glyph inside its own box, about the box's vertical centre line, changing neither its place nor its size, color and fill. THE avatar SHALL NOT mirror a glyph itself, and SHALL NOT mirror its picture or its initials.
AVT-16 WHERE the avatar is given members THE avatar SHALL be a group: it SHALL draw its members in one row that does not wrap, in the order they are given from the start edge, each as an avatar of the group's size and shape with that member's own picture, initials or glyph (AVT-2 to AVT-6), and SHALL ignore its own src, initials, icon slot and decorative. Each box after the first SHALL lie over the end of the one before it by the overlap of the group's size (comp.avatar.group.overlap.small for small, comp.avatar.group.overlap.medium for medium, comp.avatar.group.overlap.large for large) and be drawn above it, and every box SHALL be surrounded, outside its own edge and following its shape, by a gap comp.avatar.group.outline.width wide in comp.avatar.group.outline.color that takes no room in the layout. THE group SHALL be as wide as its boxes less their overlaps, and as high as one box.
AVT-17 WHILE the group has more members than max and max is 2 or more THE group SHALL draw the first max less one members and then, as its last box, an overflow box: a box of the group's size and shape filled with comp.avatar.container.color, placed and surrounded as a member is (AVT-16), holding on one line, in the label style of the group's size (AVT-5) and comp.avatar.label.color, a plus sign followed by the number of members not drawn. WHILE max is 0, or the group has no more members than max, THE group SHALL draw every member and no overflow box, unless total says more exist (AVT-18). THE overflow box SHALL take no input and SHALL NOT be a control: showing the members it counts is the product's, beside the group.
AVT-18 WHILE total is greater than the number of members the group is given THE group SHALL count as not drawn every member up to total, and SHALL draw the overflow box with that number after the members it draws: where the members given fit within max less one, or max is 0, all of them are drawn before it. THE group SHALL write the number in the current locale's digits with no grouping separator, SHALL draw 99 followed by a plus sign in place of a number above 99, at every size, so that the box never holds more than three characters (the exact number stays in overflowLabel, AVT-19), and SHALL lay the sign and the number out as one left-to-right run isolated from the text around it, so that the plus sign stays before the digits in a right-to-left layout.
AVT-19 THE group SHALL be exposed to assistive technology as one group named by its label, holding in order one image for each member it draws, each named by that member's label whatever decorative says, and then, where it draws an overflow box, one text: overflowLabel — from the instance's prop or, WHILE that is empty, from the product's words of the key avatarGroupOverflowLabel — with its place {count} filled by the number of members not drawn, in the current locale's digits with no grouping separator and never cut at 99 as the drawn text is (AVT-18); else the drawn text. Another text between braces, and a brace that opens or closes nothing, SHALL be read as written and reported in debug builds; a sentence without {count} SHALL be read as written and reported in debug builds, because it does not say how many. THE gaps SHALL be kept from assistive technology. IF the group's label is empty THE group SHALL expose its members without a group's name and in debug builds report that a group has no name; IF a member's label is empty THE group SHALL expose nothing for that member and in debug builds report it.
AVT-20 WHERE the layout direction is right-to-left THE group SHALL lay its row out from the right: the first member is at the right, each following box lies over the left end of the one before it and above it, and the overflow box is the leftmost; the order assistive technology reads SHALL stay the order given.
AVT-21 WHEN the group's members, max, total, size or shape change THE group SHALL draw and expose the new row at once, without a motion, and SHALL NOT announce the change by itself.
AVT-22 WHEN size or shape names a value that the active design system does not have THE avatar SHALL render with the default value's tokens, and in debug builds report the unknown value. IF max is 1, negative or not a whole number THE group SHALL draw as for 0 and in debug builds report it; IF total is not null and is less than the number of members given, negative or not a whole number THE group SHALL count the members given and in debug builds report it.
AVT-23 IF the avatar is a group and every member has been removed THE group SHALL draw nothing, take no space and expose nothing. IF max, total or overflowLabel is set on an avatar that has no members THE avatar SHALL ignore it and in debug builds report it.
AVT-24 WHERE the platform has ARIA attributes (the web), an avatar's host and a group's host carries its role (AVT-9, AVT-19) itself, so what the product writes on it is not moved, but for a name: WHILE label is not empty THE avatar SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that label is its whole name although the platform gives aria-labelledby the precedence, and WHEN label is emptied SHALL give them back as they were written; WHILE label is empty a name the product gives so — aria-label, or aria-labelledby naming an element — SHALL be its name and SHALL NOT be reported as having none in debug builds (AVT-9, AVT-19). WHILE an avatar's label is empty and decorative is false (or it is a member of a group) a name the product gives so SHALL make it one image named by that name, as AVT-9 says of its label: an image the product names is a named image. WHILE an avatar is decorative and not a member, or a group has no members (AVT-23), it exposes nothing, and THE avatar SHALL hold them as well, giving them back when it is exposed again. WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE avatar SHALL take it away.

各平台名称对照

对等并不意味着 API 完全相同。同一份契约,由各平台以自己的惯用方式表达。

规格 Web SwiftUI Jetpack Compose Flutter React Native
组件 tanrei-avatar TanreiAvatar TanreiAvatar TanreiAvatar Avatar
src · 属性 src url model image source
label · 属性 label name name name name
initials · 属性 initials initials initials initials initials
decorative · 属性 decorative isDecorative decorative decorative decorative
size · 属性 size size size size size
shape · 属性 shape shape shape shape shape
max · 属性 max max max max max
total · 属性 total total total total total
overflowLabel · 属性 overflowLabel overflowLabel overflowDescription overflowSemanticLabel overflowAccessibilityLabel
备注 Two elements: <tanrei-avatar src label initials size shape decorative> with the fallback glyph in its icon slot, and the group form as <tanrei-avatar-group label max total overflow-label size shape> whose light-DOM children are the <tanrei-avatar> members (the spec's group props are the group element's attributes; overflowLabel is reflected as overflow-label). The avatar's host is display: inline-block, flex: none, vertical-align: middle, with role="img" and aria-label while it is named and aria-hidden="true" while decorative, set through ElementInternals where axe can see it and as attributes otherwise; no tabindex, no listeners, and pointer-events left as they are, so a press over an avatar inside a link or a Button reaches that element (AVT-8). The picture is an <img alt="" decoding="async"> in the shadow root with object-fit: cover, kept hidden until its load (and its decode), then faded in while the fallback fades out — at once where the picture was complete as soon as its address was set, the browser's list of available images — and removed on error (AVT-4); loading, referrerpolicy and crossorigin are forwarded to it and mean nothing off the web. Initials are one dir="auto" run cut to two grapheme clusters with Intl.Segmenter (AVT-5). **Before the element is defined** the stylesheet of @tanrei/web gives tanrei-avatar:not(:defined) the box of its size and shape attributes in the container color and hides its children, so a page of avatars does not move when the script arrives; no picture, initials or name show until then, which is why a byline writes the name as text beside a decorative avatar. tanrei-avatar-group:not(:defined) is an inline flex row of those boxes. The group is role="group" with aria-label; it sets size, shape and the named state on its members, hides the members past the limit with hidden (they stay in the document), and draws the overflow box in its own shadow root as aria-hidden text beside a visually hidden run that carries overflow-label (AVT-19). The gap of AVT-16 is an outline (or a box-shadow spread) in --tanrei-comp-avatar-group-outline-color, never a border, so it takes no room; later members are above earlier ones by document order, which needs no z-index. Under forced-colors: active the box takes a CanvasText border and the <img> keeps forced-color-adjust: none (AVT-13). A badge on an avatar is <tanrei-badge label="3 unread"><tanrei-avatar …></tanrei-avatar></tanrei-badge>; a link is <tanrei-link href="…"><tanrei-avatar label="Ada Lovelace" …></tanrei-avatar></tanrei-link> or a plain anchor. TanreiAvatar(_ name: String, url: URL?, initials:, icon:, size:, shape:, isDecorative:), the fallback glyph given by name through icon:; the picture through AsyncImage, whose placeholder and failure phases both draw the fallback. The group form is TanreiAvatarGroup(_ name: String, max:, total:, overflowLabel:, size:, shape:) { TanreiAvatar(…) … }, which carries the spec's group props. Not a Button; allowsHitTesting(false) so a press reaches a Link, a Button or a row that holds it. One accessibility element with the image trait and the name as its label, or hidden while decorative; the group is accessibilityElement(children: .contain) with the group's label. TanreiAvatar(name, model, initials, icon, size, shape, decorative), the fallback glyph given by name through icon. The package keeps no image-loading dependency: model is handed to a painter the app provides through a composition local, and a painter that reports loading or failure draws the fallback (the same arrangement the chip's avatar needs; the platform's agent settles it). The group form is TanreiAvatarGroup(name, max, total, overflowDescription, size, shape) { TanreiAvatar(…) … }. No clickable and no focusable modifier; semantics are Role.Image with the name as contentDescription, cleared while decorative; the group is a semantics node with the group's name that contains its members. TanreiAvatar(name: …, image: ImageProvider?, initials:, icon:, size:, shape:, decorative:), the fallback glyph given by name through icon; the picture through Image(image:, frameBuilder:, errorBuilder:), both builders drawing the fallback. The group form is TanreiAvatarGroup(name: …, max:, total:, overflowSemanticLabel:, size:, shape:, children: [TanreiAvatar(…), …]). Wrapped in IgnorePointer, with no Focus. Semantics(image: true, label: name) over the drawn parts, which are excluded, or ExcludeSemantics while decorative; the group is Semantics(container: true, label: name). <Avatar name="Ada Lovelace" source={{ uri }} initials="AL" />; the fallback glyph is the icon prop (a glyph name). The picture is an Image whose onLoad shows it and whose onError keeps the fallback. The group form is <AvatarGroup name="Reviewers" max={4} total={…} overflowAccessibilityLabel="…"> with <Avatar> children. pointerEvents="none" and not focusable. One accessible element with accessibilityRole="image" and the name as accessibilityLabel, or accessible={false} with importantForAccessibility="no-hide-descendants" while decorative. Follows the app's direction where an ancestor's is not known.

令牌

令牌 引用 解析值(浅色)
--tanrei-comp-avatar-container-color sys.color.surface-container-highest #eeeeee
--tanrei-comp-avatar-container-shape-circle sys.shape.corner.full 9999px
--tanrei-comp-avatar-container-shape-square sys.shape.corner.small 6px
--tanrei-comp-avatar-container-size-large — 56px
--tanrei-comp-avatar-container-size-medium — 40px
--tanrei-comp-avatar-container-size-small — 24px
--tanrei-comp-avatar-group-outline-color sys.color.surface #ffffff
--tanrei-comp-avatar-group-outline-width sys.border.thick 2px
--tanrei-comp-avatar-group-overlap-large sys.space.space100 8px
--tanrei-comp-avatar-group-overlap-medium sys.space.space50 4px
--tanrei-comp-avatar-group-overlap-small sys.space.space25 2px
--tanrei-comp-avatar-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-avatar-icon-size-large sys.icon.large 32px
--tanrei-comp-avatar-icon-size-medium sys.icon.medium 24px
--tanrei-comp-avatar-icon-size-small sys.icon.extra-small 16px
--tanrei-comp-avatar-label-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-avatar-motion-picture-duration sys.motion.role.state.default 250ms
--tanrei-comp-avatar-motion-picture-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-avatar-label-typescale-large sys.typescale.heading-3 500 20px/1.4
--tanrei-comp-avatar-label-typescale-medium sys.typescale.label 500 14px/1.4286
--tanrei-comp-avatar-label-typescale-small sys.typescale.caption 500 11px/1.4545

测试样例

作为基准的渲染结果。所有平台都以相同的 ID 为每个样例截取快照,以便相互比较。

生成自 specs/avatar.spec.json, tokens/comp/avatar.tokens.json, design/tokens/

指南

何时使用

当一张小图片比单独的姓名更快地告诉用户某样东西属于谁、属于什么时,使用头像:署名行、评论、人员列表中的一行、个人资料的顶部。它是一张图片,仅此而已。它没有悬停,没有焦点,没有按下,也没有事件。

你需要 使用
人身上的一个圆点或一个计数(“3 条未读”) 围在头像外面的徽标。
通向个人资料的头像 里面放着头像的链接。
打开菜单的头像 里面放着头像的按钮。
可以被选中或移除的人 纸片。
在线状态(在线、离开) 姓名旁边的文字;需要标记的地方再加一个 Tag。

它绘制什么

头像绘制下面这些东西里它拥有的第一样:

  1. src 的图片,在它加载完成之后。
  2. 你给出的 initials。
  3. 它的 icon 插槽里的字形。
  4. 系统自己的字形:圆形用一个人形,方形用一个中性的标记。

方框从第一次绘制起就保持自己的尺寸。图片加载期间,在它的位置上绘制替代内容,图片到达后淡入,替代内容同时淡出。浏览器已经持有的图片会立即绘制。头像周围的东西都不会移动。无法加载的图片会留下替代内容:没有图片损坏的标记,头像也不会再次请求。

姓名缩写

头像不会根据姓名生成缩写。用哪些字符代表一个姓名,取决于它的文字系统,也取决于哪一部分写在前面,而你的产品已经知道这些。请在 initials 中给出:

姓名 initials
Ada Lovelace AL
山田 花子 山 或 山田
王小明 王
ليلى حسن لح
किरण राव किरा

头像最多绘制两个字符,按读者数字符的方式来数,所以带附加符号的字母或者连写的音节绝不会被切成两半。它按写下的样子绘制,不改变大小写。

几种文字系统的姓名缩写

尺寸和形状

size 边长 用于
small 24 一行文本的旁边:署名行、表格单元格、提及。
medium(默认) 40 列表中的一行、评论。
large 56 某个人自己的页面或卡片的顶部。
shape 用于
circle(默认) 一个人。
square 不是某一个人的东西:团队、项目、组织、机器人。

所有替代内容都使用同一种低调的填充。没有按人区分的颜色:不表达任何含义的颜色,系统里没有。

图片

  • 提供一张方形图片,边长至少是头像边长的两倍,这样它在高密度屏幕上仍然清晰。其他比例的图片会围绕中心裁剪。
  • loading="lazy" 会等到头像靠近窗口时才请求图片。在很长的列表里使用它。
  • referrerpolicy 和 crossorigin 会按你写的原样传给图片。头像两样都不替你选:把你页面的哪些信息告诉图片所在的主机,由你决定。

组

组把它的成员画成一行。每个成员只压住前一个成员一点点(按尺寸为 2、4 或 8),因此并排的两个字母缩写保持完整、不会被误读;每个成员周围都有一圈表面颜色的间隙。

把没有交给它的成员也数进去的组

  • max 是组最多绘制的方框数,溢出框也算在内。六名成员加上 max="4",是三名成员和“+3”。组绝不绘制“+1”:那等于花掉一个方框去藏起一张脸。
  • 交给组的成员比实际的少时,total 是真实的总数。三名成员、max="4" 和 total="240",是三名成员和“99+”:超过 99 时,任何尺寸的方框都写“99+”,所以方框里最多只有三个字符。确切的数字请写在 overflow-label 里,读屏读的是它。
  • 组把自己的 size 和 shape 交给每一个成员。
  • 放在页面表面以外的其他表面上时,把 --tanrei-comp-avatar-group-outline-color 设为那个表面的颜色。
  • 溢出框是文本,不是控件。用户需要看到还有谁的地方,在组的旁边放一个链接或按钮。

脚本到达之前

<tanrei-avatar> 在自己的 shadow root 里绘制,所以服务器渲染的页面在脚本运行之前,它的位置上什么都不显示。加载 @tanrei/web/avatar.css,每个头像就会保留一个与它的尺寸和形状相符的方框,页面也就不会发生位移。在那之前,图片、姓名缩写和名称都不显示。对于不运行脚本也必须能读的页面,请在装饰性的头像旁边用文本写出姓名。

带 max 的组在脚本数完成员之前,会显示你交给它的每一个成员。如果这绝不能让页面发生位移,就只把组要绘制的成员交给它,其余的用 total 表示。

推荐

  • 给每个单独出现的头像一个 label:完整的姓名。
  • 头像位于写着同一个姓名的文本旁边时,给它设置 decorative。
  • 给每个人都提供 initials,这样图片缺失或加载缓慢时,仍然看得出是谁。
  • 在整个产品里,同一类东西使用同一种形状。

避免

  • 不要在头像上放处理函数。把它放进链接或按钮,它们才有各种状态和焦点指示。
  • 不要在标签里写“……的照片”。标签就是姓名。
  • 不要用你自己的颜色、圆环或圆点来表示状态。计数用徽标,在线状态用文字说明。
  • 不要把头像用于装饰性的图片或标题里的标志(logo)。它代表的是某个人,或者用户以其身份行事的某样东西。

无障碍

角色
img
标注
An avatar that stands alone is an image named by label, the full name of the person or the thing, whatever it draws; the initials, the glyph and the picture's address are never read. An avatar beside the same name in visible text is decorative and hidden. A group is a group named by its label, holding one named image for each member it draws and, last, the overflow's text (overflowLabel, or the drawn count). Inside a link or a Button, the avatar's label is part of that element's name.
最小目标
即使外观尺寸更小,点击区域也满足最小目标尺寸。 minimum 32px · pointer 44px · spacing 8px · touch 48px

键盘操作

按键 动作

备注

  • Not interactive: the avatar takes no input and no focus (AVT-7), so there is no target to size and minimumTarget holds trivially. An avatar that is pressed is inside a link or a Button, and that element meets the minimum target by its own spec; a small (24) avatar alone in a link needs the link's target, not its own box, to be large enough.
  • Decorative or named is the product's decision and cannot be seen from the avatar: beside "Ada Lovelace" in text a named avatar would be read as "Ada Lovelace, image, Ada Lovelace". The rule the docs page gives: if deleting the avatar loses a name, it is named; otherwise it is decorative.
  • The name is the name, not a description of the picture: "Ada Lovelace", never "Photo of Ada Lovelace" and never the initials.
  • Contrast in the default system: the initials, the count and the glyph are on-surface-variant on surface-container-highest, a pair the token invariants hold to 4.5:1 for secondary content on every surface tone. The fill against the surface around it is not held to a ratio: the avatar is not a control, and what it says is its name.
  • A picture brings its own colors, which the avatar does not check. A picture with a pale edge on a pale surface loses its outline; the avatar draws no ring around a picture, so a product whose pictures are often pale chooses the square or gives the surface behind them a tone.
  • A badge on an avatar (AVT-12) says that something is waiting, in the badge's one color and with the badge's label in words. Presence (online, away, busy) is a status that a color alone would carry; say it in words beside the name, with a tag where it needs a mark.
  • Forced colors (AVT-13): every fallback gains an edge in the text color; pictures are left alone.
  • A group's overflow box is text, not a control. Where the people it counts matter (who else can see this), the product lists them: a link or a Button beside the group that opens the full list.

生成自 specs/avatar.spec.json, tokens/sys/measure.tokens.json

组件负责的部分

  • 单独使用时,它是一张由 label 命名的图像,无论它绘制的是图片、姓名缩写还是字形。姓名缩写、字形的名称和图片的地址绝不会被朗读。
  • 设置 decorative 后,它对辅助技术隐藏。
  • 在链接或按钮里面时,它的标签成为该元素的名称,按在头像上也会传到该元素。
  • 围在它外面的徽标,会把徽标的标签加在头像的名称之后。
  • 组是一个由它的 label 命名的组。它为自己绘制的每个成员各包含一张有名称的图像,按给定的顺序排列,然后是溢出框的文本。它没有绘制的成员不会暴露出来。
  • 它不接受任何输入,也不接受焦点,所以不在焦点顺序中增加停靠点。
  • 文本放大时,它像图标一样保持自己的方框大小。姓名缩写随文本变大,到该尺寸的字形框为止,在方框里保持完整。
  • 在强制颜色模式下,所有替代内容都会多出一道文本颜色的边线。图片保留自己的颜色。
  • 在从右到左的布局中,组从右侧开始。图片和姓名缩写绝不镜像,“+3”的加号仍然在数字之前。
  • 没有名称的头像、超过两个字符的姓名缩写、加载失败的图片,以及未知的尺寸或形状,都会在调试构建中报告。

需要你做的事

  • 为每个头像决定它是有名称的,还是装饰性的。规则是:如果删掉这个头像会丢掉一个姓名,它就是有名称的;否则就是装饰性的。
  • 用页面所用的语言编写一次 overflowLabel,在数字的位置写上占位符 {count}(“还有 {count} 人”)——写在组上,或用 setWords({ avatarGroupOverflowLabel }) 为整个产品设置。组会填入未画出的人数,即使画的是 99+,填入的也是实际人数。请写出对任何数字都正确的句子;如果语言需要按数字变换形式,就按数字替换。没有它时,“+3”会按画出来的样子朗读。
  • 给链接里的小头像留出足够的按压空间。头像宽 24;链接自己必须满足最小目标。
  • 图片带有它自己的颜色。图片的边缘常常偏浅的地方,给它们背后的表面加一层色调。