Ir al contenido

Componentes · Ola 3 · Contenido

Avatar

Muestra a una persona con su foto o, si no hay foto, con sus iniciales. Es circular, una excepción a los 2 px de los controles: es la silueta de una persona, no un control. Varias personas juntas se superponen en un grupo.

import { Avatar, AvatarGroup } from '@archeblack/ui';

Ejemplos

Foto e iniciales

Con src, la foto; sin foto, o mientras carga, o si falla, las iniciales de name.

Svelte
<script lang="ts">
	import { Avatar } from '@archeblack/ui';
	import portrait from './portrait.svg';
</script>

<!-- Con foto; sin foto; y con una foto que no carga: las iniciales quedan en su lugar. -->
<div style="display: flex; align-items: center; gap: var(--arche-spacing-4)">
	<Avatar name="Lucía Ferrer" src={portrait} />
	<Avatar name="Jimmy Mora" />
	<Avatar name="Ada Lovelace" src="data:image/png;base64," />
</div>

Tallas

sm (24 px) con una sola inicial; md (32 px), lg (40 px) y xl (96 px, el retrato de un autor, con las iniciales en 28 px) con dos. El nombre accesible es el mismo en todas.

Svelte
<script lang="ts">
	import { Avatar } from '@archeblack/ui';
	import portrait from './portrait.svg';
</script>

<div style="display: grid; gap: var(--arche-spacing-4)">
	<div style="display: flex; flex-wrap: wrap; align-items: center; gap: var(--arche-spacing-4)">
		<Avatar name="Jimmy Mora" size="sm" />
		<Avatar name="Jimmy Mora" size="md" />
		<Avatar name="Jimmy Mora" size="lg" />
		<Avatar name="Jimmy Mora" size="xl" />
	</div>
	<div style="display: flex; flex-wrap: wrap; align-items: center; gap: var(--arche-spacing-4)">
		<Avatar name="Lucía Ferrer" src={portrait} size="sm" />
		<Avatar name="Lucía Ferrer" src={portrait} size="md" />
		<Avatar name="Lucía Ferrer" src={portrait} size="lg" />
		<Avatar name="Lucía Ferrer" src={portrait} size="xl" />
	</div>
</div>

Junto al nombre

El nombre ya está escrito: alt="" deja al avatar como decorativo.

Grace Hopper

Revisora · hace 6 minutos

Svelte
<script lang="ts">
	import { Avatar } from '@archeblack/ui';
</script>

<!-- El nombre ya está escrito al lado: alt="" deja al avatar como decorativo. -->
<div style="display: flex; align-items: center; gap: var(--arche-spacing-3)">
	<Avatar name="Grace Hopper" alt="" />
	<div>
		<p style="margin: 0; color: var(--arche-color-text-strong)">Grace Hopper</p>
		<p
			style="margin: 0; font-size: var(--arche-font-size-xs); color: var(--arche-color-text-muted)"
		>
			Revisora · hace 6 minutos
		</p>
	</div>
</div>

Grupo

AvatarGroup superpone los avatares con un anillo del color del fondo y cuenta el resto.

+3
+3
+3
Svelte
<script lang="ts">
	import { AvatarGroup } from '@archeblack/ui';
	import portrait from './portrait.svg';

	const team = [
		{ name: 'Jimmy Mora' },
		{ name: 'Lucía Ferrer', src: portrait },
		{ name: 'Ada Lovelace' },
		{ name: 'Grace Hopper' },
		{ name: 'Alan Turing' },
		{ name: 'Katherine Johnson' },
		{ name: 'Barbara Liskov' }
	];
</script>

<!-- Siete personas: se ven cuatro y el resto se cuenta en «+3». -->
<div style="display: grid; justify-items: center; gap: var(--arche-spacing-6)">
	<AvatarGroup aria-label="Equipo del proyecto" items={team} max={4} size="sm" />
	<AvatarGroup aria-label="Equipo del proyecto" items={team} max={4} />
	<AvatarGroup aria-label="Equipo del proyecto" items={team} max={4} size="lg" />
</div>

Grupo sobre una tarjeta

surface pone el anillo del color de la capa; total cuenta a los que no llegaron en items.

Revisión

12 personas revisan

+9
Svelte
<script lang="ts">
	import { AvatarGroup, Card } from '@archeblack/ui';

	const reviewers = [{ name: 'Jimmy Mora' }, { name: 'Ada Lovelace' }, { name: 'Grace Hopper' }];
</script>

<!-- Dentro de una Card el fondo es surface: el anillo de cada avatar toma ese color. -->
<Card style="width: 100%; max-width: 24rem">
	{#snippet header()}
		<h4 id="reviewers-title">Revisión</h4>
	{/snippet}
	<div
		style="display: flex; align-items: center; justify-content: space-between; gap: var(--arche-spacing-3)"
	>
		<p style="margin: 0; color: var(--arche-color-text-muted)">12 personas revisan</p>
		<AvatarGroup
			aria-labelledby="reviewers-title"
			items={reviewers}
			total={12}
			surface="surface"
			moreLabel={(count) => `y ${count} personas más`}
		/>
	</div>
</Card>

Props

Avatar

Props de Avatar
PropDescripción
name string La persona o la entidad. Da las iniciales (la primera letra de la primera y de la última palabra) y el nombre accesible.
src? string La foto. Mientras carga, o si falla, se ven las iniciales. Sin src, solo las iniciales.
alt? string Nombre accesible en lugar de name, como el alt de una imagen. Con alt="" el avatar es decorativo: úsalo cuando el nombre ya está escrito al lado.
initials? string Iniciales en lugar de las que salen de name («PL» para «Equipo de plataforma»). En sm se ve solo la primera.
size? 'sm' | 'md' | 'lg' | 'xl' Por defecto 'md'24, 32, 40 o 96 px de diámetro. sm muestra una sola inicial (la primera); md, lg y xl, dos. xl es el retrato de un autor en su cabecera: con él, Masthead pone el avatar al lado del texto.
class? ClassValue Clases del producto; se suman a arche-avatar.
...rest HTMLAttributes<HTMLSpanElement> Van a la raíz (<span>): id, title, style y data-*.

AvatarGroup

Props de AvatarGroup
PropDescripción
items { name, src?, alt?, initials? }[] Las personas, en orden: las primeras max se ven y las demás se cuentan en «+N».
aria-label? string Nombre del grupo («Equipo del proyecto»); si un texto de la página ya lo nombra, aria-labelledby con su id. Hace falta uno de los dos: TypeScript rechaza un grupo sin nombre.
max? number Por defecto 4Cuántos avatares se ven como mucho antes del contador.
total? number El total de personas, si items trae solo algunas. Por defecto, la cantidad de items.
size? 'sm' | 'md' | 'lg' Por defecto 'md'Talla de todos los avatares y del contador. En sm, cada avatar muestra una sola inicial. Sin xl: un retrato no se agrupa.
surface? 'bg' | 'surface' | 'surface-raised' | 'surface-overlay' Por defecto 'bg'El fondo sobre el que está el grupo. El anillo de 2 px que separa cada avatar del siguiente es de ese color.
moreLabel? (count: number) => string Por defecto (n) => `${n} más`Nombre accesible del contador. En pantalla se ve «+3».
class? ClassValue Clases del producto; se suman a arche-avatar-group.
...rest HTMLAttributes<HTMLDivElement> Van a la raíz (role="group"): id, style y data-*.

Accesibilidad

  • El avatar es una imagen con nombre (role="img" y aria-label con name, o con alt), haya foto o no. La foto (alt="") y las iniciales están ocultas para el lector: el nombre no depende de si la foto cargó.
  • Si el nombre ya está escrito al lado (una fila con el avatar y «Grace Hopper»), pasa alt="": el avatar queda decorativo y el nombre no se lee dos veces.
  • AvatarGroup es un role="group" con nombre obligatorio. Cada avatar se lee con su nombre y el contador, como una imagen: «3 más», o el texto de moreLabel.
  • Las iniciales van en text-strong sobre surface-overlay, en AA. El borde del círculo es border: decorativo, el avatar no es un control.
  • En colores forzados, el fondo y los anillos del grupo desaparecen y el borde pasa a CanvasText: cada círculo sigue separado del siguiente.
  • El avatar no es interactivo. Para abrir un perfil, envuélvelo en un link con el nombre como texto (y el avatar con alt=""), o usa un Button con su propia etiqueta.

Qué evitar

  • Un avatar como única forma de saber quién es alguien, sin nombre en ningún lado. El nombre al lado, o al menos en name, que el lector de pantalla dice.
  • Avatares cuadrados o con otro radio para distinguir tipos de cuenta. El círculo siempre. Para una organización o un equipo, las iniciales del nombre o initials; el tipo, en texto o con un Badge.
  • Un grupo con decenas de avatares visibles. max (4 por defecto) y el total en el contador.
  • El anillo del grupo con el color equivocado (un grupo sobre una Card con el anillo del fondo de la página). surface con la capa donde está el grupo.