Avatar
Image and fallback initials primitive for identity surfaces such as profiles and assignees.
Name, fallback, and sizes
The name supplies the accessible identity and fallback supplies visible initials when no image is available. md stands alone, sm sits in a row of people, and xs names someone inline in small text.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar/ui-avatar.html"
>
<ui-avatar
name="Maya Chen"
> </ui-avatar>
<ui-avatar
name="Maya Chen"
size="sm"
> </ui-avatar>
<ui-avatar
name="Maya Chen"
size="xs"
> </ui-avatar><script setup>
import { UiAvatar } from "@threadlabs/looma";
</script>
<template>
<UiAvatar
name="Maya Chen"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="sm"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="xs"
> </UiAvatar>
</template>import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <>
<UiAvatar
name="Maya Chen"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="sm"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="xs"
> </UiAvatar>
</>;
}/** @jsxImportSource preact */
import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <>
<UiAvatar
name="Maya Chen"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="sm"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="xs"
> </UiAvatar>
</>;
}<script>
import { UiAvatar } from "@threadlabs/looma";
</script>
<UiAvatar
name="Maya Chen"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="sm"
> </UiAvatar>
<UiAvatar
name="Maya Chen"
size="xs"
> </UiAvatar>import { Component } from "@angular/core";
import { UiAvatar } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiAvatar],
template: `
<span
ui-avatar
[name]="'Maya Chen'"
> </span>
<span
ui-avatar
[name]="'Maya Chen'"
[size]="'sm'"
> </span>
<span
ui-avatar
[name]="'Maya Chen'"
[size]="'xs'"
> </span>
`,
})
export default class Example {}Image
Place an ordinary image inside Avatar; its own alt text supplies the accessible name and the fallback remains available if loading fails.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar/ui-avatar.html"
>
<ui-avatar
name="Maya Chen"
fallback="MC"
> <img
src="/_looma/portrait.svg"
alt="Maya Chen"
> </ui-avatar><script setup>
import { UiAvatar } from "@threadlabs/looma";
</script>
<template>
<UiAvatar
name="Maya Chen"
fallback="MC"
> <img
src="/_looma/portrait.svg"
alt="Maya Chen"
> </UiAvatar>
</template>import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <UiAvatar
name="Maya Chen"
fallback="MC"
>{" "}<img
src="/_looma/portrait.svg"
alt="Maya Chen"
/>{" "}</UiAvatar>;
}/** @jsxImportSource preact */
import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <UiAvatar
name="Maya Chen"
fallback="MC"
>{" "}<img
src="/_looma/portrait.svg"
alt="Maya Chen"
/>{" "}</UiAvatar>;
}<script>
import { UiAvatar } from "@threadlabs/looma";
</script>
<UiAvatar
name="Maya Chen"
fallback="MC"
> <img
src="/_looma/portrait.svg"
alt="Maya Chen"
> </UiAvatar>import { Component } from "@angular/core";
import { UiAvatar } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiAvatar],
template: `
<span
ui-avatar
[name]="'Maya Chen'"
[fallback]="'MC'"
> <img
src="/_looma/portrait.svg"
alt="Maya Chen"
> </span>
`,
})
export default class Example {}fallback="UX"
Fallback overrides the initials derived from name without requiring internal hooks or extra markup.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar/ui-avatar.html"
>
<ui-avatar
name="Maya Chen"
fallback="UX"
> </ui-avatar><script setup>
import { UiAvatar } from "@threadlabs/looma";
</script>
<template>
<UiAvatar
name="Maya Chen"
fallback="UX"
> </UiAvatar>
</template>import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <UiAvatar
name="Maya Chen"
fallback="UX"
> </UiAvatar>;
}/** @jsxImportSource preact */
import { UiAvatar } from "@threadlabs/looma";
export default function Example() {
return <UiAvatar
name="Maya Chen"
fallback="UX"
> </UiAvatar>;
}<script>
import { UiAvatar } from "@threadlabs/looma";
</script>
<UiAvatar
name="Maya Chen"
fallback="UX"
> </UiAvatar>import { Component } from "@angular/core";
import { UiAvatar } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiAvatar],
template: `
<span
ui-avatar
[name]="'Maya Chen'"
[fallback]="'UX'"
> </span>
`,
})
export default class Example {}Active
A small group, as in a page header. A ring marks someone active now, such as editing the same page. The ring is not announced, so alt says what it means.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar-group/ui-avatar-group.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar/ui-avatar.html"
>
<ui-avatar-group
label="On this page"
size="sm"
>
<ui-avatar
size="sm"
name="Ada Lovelace"
alt="Ada Lovelace, editing"
active
></ui-avatar>
<ui-avatar
size="sm"
name="Grace Hopper"
></ui-avatar>
</ui-avatar-group><script setup>
import { UiAvatar, UiAvatarGroup } from "@threadlabs/looma";
</script>
<template>
<UiAvatarGroup
label="On this page"
size="sm"
>
<UiAvatar
size="sm"
name="Ada Lovelace"
alt="Ada Lovelace, editing"
:active="true"
/>
<UiAvatar
size="sm"
name="Grace Hopper"
/>
</UiAvatarGroup>
</template>import { UiAvatar, UiAvatarGroup } from "@threadlabs/looma";
export default function Example() {
return <UiAvatarGroup
label="On this page"
size="sm"
>
<UiAvatar
size="sm"
name="Ada Lovelace"
alt="Ada Lovelace, editing"
active
/>
<UiAvatar
size="sm"
name="Grace Hopper"
/>
</UiAvatarGroup>;
}/** @jsxImportSource preact */
import { UiAvatar, UiAvatarGroup } from "@threadlabs/looma";
export default function Example() {
return <UiAvatarGroup
label="On this page"
size="sm"
>
<UiAvatar
size="sm"
name="Ada Lovelace"
alt="Ada Lovelace, editing"
active
/>
<UiAvatar
size="sm"
name="Grace Hopper"
/>
</UiAvatarGroup>;
}<script>
import { UiAvatar, UiAvatarGroup } from "@threadlabs/looma";
</script>
<UiAvatarGroup
label="On this page"
size="sm"
>
<UiAvatar
size="sm"
name="Ada Lovelace"
alt="Ada Lovelace, editing"
active
/>
<UiAvatar
size="sm"
name="Grace Hopper"
/>
</UiAvatarGroup>import { Component } from "@angular/core";
import { UiAvatar, UiAvatarGroup } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiAvatarGroup, UiAvatar],
template: `
<div
ui-avatar-group
[label]="'On this page'"
[size]="'sm'"
>
<span
ui-avatar
[size]="'sm'"
[name]="'Ada Lovelace'"
[alt]="'Ada Lovelace, editing'"
[active]="true"
></span>
<span
ui-avatar
[size]="'sm'"
[name]="'Grace Hopper'"
></span>
</div>
`,
})
export default class Example {}Shape and decoration
A square avatar follows the theme radius. An unnamed avatar shows a person glyph; decorative avatars are hidden from assistive technology.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-avatar/ui-avatar.html"
>
<ui-cluster
gap="s"
>
<ui-avatar></ui-avatar>
<ui-avatar
name="Ada Lovelace"
shape="square"
></ui-avatar>
<ui-avatar
name="Ada Lovelace"
decorative
></ui-avatar>
</ui-cluster><script setup>
import { UiAvatar, UiCluster } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
>
<UiAvatar />
<UiAvatar
name="Ada Lovelace"
shape="square"
/>
<UiAvatar
name="Ada Lovelace"
:decorative="true"
/>
</UiCluster>
</template>import { UiAvatar, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiAvatar />
<UiAvatar
name="Ada Lovelace"
shape="square"
/>
<UiAvatar
name="Ada Lovelace"
decorative
/>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiAvatar, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiAvatar />
<UiAvatar
name="Ada Lovelace"
shape="square"
/>
<UiAvatar
name="Ada Lovelace"
decorative
/>
</UiCluster>;
}<script>
import { UiAvatar, UiCluster } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
>
<UiAvatar />
<UiAvatar
name="Ada Lovelace"
shape="square"
/>
<UiAvatar
name="Ada Lovelace"
decorative
/>
</UiCluster>import { Component } from "@angular/core";
import { UiAvatar, UiCluster } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiAvatar],
template: `
<div
ui-cluster
[gap]="'s'"
>
<span
ui-avatar
></span>
<span
ui-avatar
[name]="'Ada Lovelace'"
[shape]="'square'"
></span>
<span
ui-avatar
[name]="'Ada Lovelace'"
[decorative]="true"
></span>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: span
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
active | Marks the person as active now, such as editing the same page: a fine accent ring around the avatar. The ring is not announced, so say what it means in alt ("Ada Lovelace, editing"). | active | boolean | false | — |
alt | The avatar's accessible name, announced for it as an image. When empty, name is used, then "Avatar". Initials come from name first, so alt supplies them only when name is empty. An authored img carries its own alt instead. | alt | string | | — |
decorative | Hides the avatar from assistive technology when adjacent text already identifies the person. | decorative | boolean | false | — |
fallback | Text shown instead of the initials derived from name or alt, whenever there is no image. It is uppercased; keep it to a couple of characters, because the circle clips anything wider. | fallback | string | | — |
name | The person's name. The initials are drawn from it: the first letters of the first two words, or the first two letters of a single word. It is also the accessible name when alt is empty. | name | string | | — |
shape | Circle by default, with a shallow shadow; square uses the theme's medium radius. | shape | keyword | circle | circle, square |
size | md is 2.5rem, for a person on their own (a profile, a comment); sm is 1.75rem with smaller initials, for a row of people in a toolbar or header; xs is 1.25rem with small initials, for a person named inline in a line of small text. | size | keyword | md | xs, sm, md |
src | The image to show, cropped to fill the circle. Until it loads, or if it fails, the avatar shows initials instead. An img element authored inside the avatar takes precedence over src. | src | string | — | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
active | boolean | false | — |
alt | string | | — |
decorative | boolean | false | — |
fallback | string | | — |
name | string | | — |
shape | "circle" | "square" | circle | circle, square |
size | "xs" | "sm" | "md" | md | xs, sm, md |
src | string | — | — |
Events
No events.
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--ui-avatar-active-ring | — | var(--ui-accent-solid) |
--ui-avatar-border | — | color-mix(in srgb, var(--ui-accent-solid) 35%, var(--ui-surface-default)) | var(--ui-border-strong) |
--ui-avatar-radius | — | var(--ui-radius-round) | var(--ui-radius-md) |
--ui-avatar-surface | — | var(--ui-accent-soft) |
--ui-avatar-text | — | var(--ui-accent-subtle-text, var(--ui-accent-solid)) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-accent-soft | — |
--ui-accent-solid | — |
--ui-accent-subtle-text | var(--ui-accent-solid) |
--ui-border-strong | — |
--ui-border-width | — |
--ui-font-size-md | — |
--ui-font-size-sm | — |
--ui-font-size-xs | — |
--ui-radius-md | — |
--ui-radius-round | — |
--ui-shadow-sm | — |
--ui-surface-default | — |