Avatar
Zwarta wizualna tożsamość osoby lub organizacji — z obrazem, inicjałami zastępczymi i opcjonalnym statusem obecności.
import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarImage,
} from "@/components/ui/avatar"
import aurora from "@/examples/avatar/assets/aurora.svg"
import ember from "@/examples/avatar/assets/ember.svg"
import tide from "@/examples/avatar/assets/tide.svg"
export default function AvatarDemo() {
return (
<AvatarGroup>
<Avatar size="lg">
<AvatarImage src={aurora.src} alt="Maya Chen" />
<AvatarFallback>MC</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src={ember.src} alt="Jonah Okafor" />
<AvatarFallback>JO</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src={tide.src} alt="Lena Park" />
<AvatarFallback>LP</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarFallback>RS</AvatarFallback>
</Avatar>
<AvatarGroupCount>+8</AvatarGroupCount>
</AvatarGroup>
)
}Anatomia
- 1Element głównyKoło dla osób, zaokrąglony kwadrat dla organizacji. Pięć rozmiarów, od 20 do 56 px.
- 2OdznakaOpcjonalna kropka statusu z obwódką w kolorze strony, która oddziela ją od obrazu.
- 3Treść zastępczaInicjały na neutralnym wypełnieniu, widoczne podczas ładowania obrazu — albo zamiast niego, gdy go brak.
- 4GrupaNachodzące na siebie awatary, każdy z obwódką w kolorze strony.
- 5LicznikLiczba pozostałych osób, w rozmiarze dopasowanym do grupy.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/avatar.jsonUżycie
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"<Avatar>
<AvatarImage src="/avatars/maya.png" alt="Maya Chen" />
<AvatarFallback>MC</AvatarFallback>
</Avatar>Zawsze dodawaj AvatarFallback. Renderuje się podczas ładowania obrazu, a na stałe — gdy obrazu brak lub nie udało się go wczytać. Dzięki temu wolna sieć czy usunięty plik nigdy nie zostawią dziury w układzie.
Przykłady
Rozmiary
Pięć rozmiarów podąża za skalą kontrolek: xs 20, sm 24, default 32, lg 40 i xl 56 pikseli. Inicjały skalują się razem z awatarem, więc pozostają optycznie wyśrodkowane.
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import aurora from "@/examples/avatar/assets/aurora.svg"
const sizes = ["xs", "sm", "default", "lg", "xl"] as const
export default function AvatarSizes() {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex items-end gap-4">
{sizes.map((size) => (
<Avatar key={size} size={size}>
<AvatarImage src={aurora.src} alt="Maya Chen" />
<AvatarFallback>MC</AvatarFallback>
</Avatar>
))}
</div>
<div className="flex items-end gap-4">
{sizes.map((size) => (
<Avatar key={size} size={size}>
<AvatarFallback>MC</AvatarFallback>
</Avatar>
))}
</div>
</div>
)
}Treść zastępcza
Gdy nie ma obrazu, pokaż dwa inicjały wielkimi literami — imienia i nazwiska. Dla osób, o których nic nie wiesz, użyj neutralnej ikony i nadaj jej dostępną nazwę.
import { UserIcon } from "lucide-react"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import dusk from "@/examples/avatar/assets/dusk.svg"
export default function AvatarFallbackExample() {
return (
<div className="flex items-center gap-6">
<div className="flex flex-col items-center gap-2">
<Avatar size="lg">
<AvatarImage src={dusk.src} alt="Priya Raman" />
<AvatarFallback>PR</AvatarFallback>
</Avatar>
<span className="text-xs text-muted-foreground">Zdjęcie</span>
</div>
<div className="flex flex-col items-center gap-2">
<Avatar size="lg">
<AvatarFallback>PR</AvatarFallback>
</Avatar>
<span className="text-xs text-muted-foreground">Inicjały</span>
</div>
<div className="flex flex-col items-center gap-2">
<Avatar size="lg">
<AvatarFallback>
<UserIcon className="size-4" aria-hidden="true" />
<span className="sr-only">Nieznany użytkownik</span>
</AvatarFallback>
</Avatar>
<span className="text-xs text-muted-foreground">Anonim</span>
</div>
</div>
)
}delay={600} do AvatarFallback, żeby pokazywać je tylko wtedy, gdy ładowanie naprawdę się przeciąga.Kształt
Koła są dla osób, zaokrąglone kwadraty — dla tego, do czego osoby należą: przestrzeni roboczych, organizacji, aplikacji. Kształt niesie znaczenie, więc stosuj go konsekwentnie w całym produkcie.
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import aurora from "@/examples/avatar/assets/aurora.svg"
import moss from "@/examples/avatar/assets/moss.svg"
export default function AvatarShape() {
return (
<div className="grid justify-items-start gap-6 sm:grid-flow-col sm:gap-10">
<div className="flex items-center gap-3">
<Avatar size="lg">
<AvatarImage src={aurora.src} alt="Maya Chen" />
<AvatarFallback>MC</AvatarFallback>
</Avatar>
<div className="flex flex-col whitespace-nowrap">
<span className="text-sm font-medium">Maya Chen</span>
<span className="text-xs text-muted-foreground">Osoba · koło</span>
</div>
</div>
<div className="flex items-center gap-3">
<Avatar size="lg" shape="square">
<AvatarImage src={moss.src} alt="Northwind" />
<AvatarFallback>NW</AvatarFallback>
</Avatar>
<div className="flex flex-col whitespace-nowrap">
<span className="text-sm font-medium">Northwind</span>
<span className="text-xs text-muted-foreground">
Przestrzeń robocza · kwadrat
</span>
</div>
</div>
</div>
)
}Status
AvatarBadge znajduje się na prawej dolnej krawędzi i ma obwódkę w kolorze strony, więc jest czytelny na każdym tle. Domyślnie ma kolor sukcesu, oznaczający status online; dla innych stanów zmień kolor tokenem semantycznym i zawsze dodaj etykietę tekstową dla czytników ekranu.
import { CheckIcon } from "lucide-react"
import {
Avatar,
AvatarBadge,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
import aurora from "@/examples/avatar/assets/aurora.svg"
import ember from "@/examples/avatar/assets/ember.svg"
import tide from "@/examples/avatar/assets/tide.svg"
export default function AvatarWithBadge() {
return (
<div className="flex items-center gap-8">
<Avatar size="lg">
<AvatarImage src={aurora.src} alt="Maya Chen" />
<AvatarFallback>MC</AvatarFallback>
<AvatarBadge>
<span className="sr-only">Online</span>
</AvatarBadge>
</Avatar>
<Avatar size="lg">
<AvatarImage src={ember.src} alt="Jonah Okafor" />
<AvatarFallback>JO</AvatarFallback>
<AvatarBadge className="bg-warning-9">
<span className="sr-only">Zaraz wracam</span>
</AvatarBadge>
</Avatar>
<Avatar size="lg">
<AvatarImage src={tide.src} alt="Lena Park" />
<AvatarFallback>LP</AvatarFallback>
<AvatarBadge className="bg-gray-9">
<span className="sr-only">Offline</span>
</AvatarBadge>
</Avatar>
<Avatar size="xl">
<AvatarFallback>RS</AvatarFallback>
<AvatarBadge className="bg-brand text-brand-foreground">
<CheckIcon aria-hidden="true" />
<span className="sr-only">Konto zweryfikowane</span>
</AvatarBadge>
</Avatar>
</div>
)
}Grupa
Nakładaj awatary na siebie, aby pokazać, kto bierze udział, bez wymieniania wszystkich. Pokaż od trzech do pięciu, a resztę podsumuj za pomocą AvatarGroupCount. Każdy awatar dostaje obwódkę w kolorze strony, więc miejsca, w których się nakładają, pozostają wyraźne.
import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarImage,
} from "@/components/ui/avatar"
import aurora from "@/examples/avatar/assets/aurora.svg"
import dusk from "@/examples/avatar/assets/dusk.svg"
import ember from "@/examples/avatar/assets/ember.svg"
import tide from "@/examples/avatar/assets/tide.svg"
const people = [
{ name: "Maya Chen", initials: "MC", image: aurora.src },
{ name: "Jonah Okafor", initials: "JO", image: ember.src },
{ name: "Lena Park", initials: "LP", image: tide.src },
{ name: "Priya Raman", initials: "PR", image: dusk.src },
]
export default function AvatarGroupExample() {
return (
<div className="flex flex-col items-center gap-6">
{(["sm", "default", "lg"] as const).map((size) => (
<AvatarGroup
key={size}
aria-label="Członkowie projektu: Maya Chen, Jonah Okafor, Lena Park, Priya Raman i 12 innych osób"
>
{people.map((person) => (
<Avatar key={person.name} size={size}>
<AvatarImage src={person.image} alt={person.name} />
<AvatarFallback>{person.initials}</AvatarFallback>
</Avatar>
))}
<AvatarGroupCount>+12</AvatarGroupCount>
</AvatarGroup>
))}
</div>
)
}Z tekstem
Zwykle awatar występuje obok imienia i nazwiska. Skoro nazwa jest już widoczna, awatar pełni funkcję dekoracyjną: nadaj obrazowi pusty alt, żeby technologie wspomagające nie odczytywały nazwy dwa razy.
import {
Avatar,
AvatarBadge,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import aurora from "@/examples/avatar/assets/aurora.svg"
export default function AvatarWithText() {
return (
<div className="flex w-full max-w-sm items-center gap-3 rounded-xl border bg-card p-4 shadow-raised">
<Avatar size="lg">
<AvatarImage src={aurora.src} alt="" />
<AvatarFallback>MC</AvatarFallback>
<AvatarBadge>
<span className="sr-only">Online</span>
</AvatarBadge>
</Avatar>
<div className="flex min-w-0 flex-1 flex-col">
<span className="truncate text-sm font-medium">Maya Chen</span>
<span className="truncate text-body-xs text-muted-foreground">
maya@northwind.dev
</span>
</div>
<Badge variant="secondary">Właściciel</Badge>
</div>
)
}Wytyczne
Kiedy używać
- Aby pomóc rozpoznać, kto coś zrobił: autorów komentarzy, osoby przypisane, współpracowników, właścicieli kont.
- Aby oznaczyć przestrzeń roboczą, organizację lub połączoną aplikację w przełącznikach i na listach.
Kiedy nie używać
- Do grafik dekoracyjnych lub redakcyjnych — użyj zwykłego obrazu.
- Do obiektów, które nie są osobami ani organizacjami, na przykład plików czy integracji na liście — użyj komponentu Item z ikoną.
- Jako jedynego sposobu identyfikacji osoby w gęstej tabeli. Dodaj obok imię i nazwisko albo udostępnij je w podpowiedzi.
Spójna tożsamość
Inicjały
Obrazy
- Używaj kwadratowych obrazów źródłowych co najmniej dwa razy większych od wyświetlanego rozmiaru (112 px dla
xl), żeby awatary pozostały ostre na ekranach o dużej gęstości pikseli. - Kadruj wokół twarzy lub logo; awatar stosuje
object-coveri przycina obraz do swojego kształtu. - Nie dodawaj obramowań — każdy awatar ma już cienką wewnętrzną obwódkę, dzięki której jasne obrazy nie zlewają się z jasnymi powierzchniami.
Dostępność
- Nazwij obraz.
AvatarImagerenderuje<img>: ustaw waltnazwę osoby lub organizacji. Gdy nazwa jest widoczna obok awatara, ustawalt=""i dodajaria-hiddendoAvatar, żeby inicjały nie były odczytywane jako pojedyncze litery. - Status wymaga słów. Odznaka to tylko kolor i położenie. Umieść w niej etykietę ukrytą wizualnie (
<span className="sr-only">Online</span>), a obecność pokazuj tekstem wszędzie tam, gdzie ma to znaczenie. - Grupa wymaga podsumowania.
AvatarGroupma rolęgroup, więc jego etykieta jest odczytywana. Nadaj mu atrybutaria-label, który wymienia osoby lub podaje ich liczbę — „Członkowie projektu: Maya Chen, Jonah Okafor i 12 innych osób”. - Kontrast. Inicjały zastępcze (
gray-11nagray-3) osiągają 4,5:1 w obu trybach.
Dokumentacja API
Avatar
Komponent główny. Przyjmuje wszystkie propsy Avatar Root z Base UI.
AvatarImage
AvatarFallback
AvatarBadge
<span> umieszczony na krawędzi awatara. Domyślnie ma kolor sukcesu; zmień go tokenem tła, np. bg-warning-9. Od rozmiaru default wzwyż rozmiar ikon wewnątrz jest dobierany automatycznie; w rozmiarach xs i sm ikony są ukryte, bo kropka jest na nie za mała.
AvatarGroup
<div> z role="group", który nakłada awatary na siebie i otacza je obwódką w kolorze strony. Przyjmuje wszystkie propsy elementu div, w tym aria-label.
AvatarGroupCount
<div> z podsumowaniem „+N” na końcu grupy. Automatycznie przyjmuje rozmiar awatarów w grupie.