Przejdź do treści

Avatar

Zwarta wizualna tożsamość osoby lub organizacji — z obrazem, inicjałami zastępczymi i opcjonalnym statusem obecności.

Kod źródłowyBase UIRejestr
MCJOLPRS
+8
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

AL
GHKJMH
+4
  1. 1Element głównyKoło dla osób, zaokrąglony kwadrat dla organizacji. Pięć rozmiarów, od 20 do 56 px.
  2. 2OdznakaOpcjonalna kropka statusu z obwódką w kolorze strony, która oddziela ją od obrazu.
  3. 3Treść zastępczaInicjały na neutralnym wypełnieniu, widoczne podczas ładowania obrazu — albo zamiast niego, gdy go brak.
  4. 4GrupaNachodzące na siebie awatary, każdy z obwódką w kolorze strony.
  5. 5LicznikLiczba pozostałych osób, w rozmiarze dopasowanym do grupy.

Instalacja

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/avatar.json

Uż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.

MCMCMCMCMC
MCMCMCMCMC
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>
  )
}
RozmiarZastosowanie
xs, smWzmianki w tekście, gęste tabele, nałożone na siebie awatary przypisanych osób.
defaultListy, komentarze, menu, wiersze tabel.
lgKarty, przełączniki kont, listy członków z dwoma wierszami tekstu.
xlNagłówki profili i strony ustawień — jeden na widok.

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ę.

PRZdjęcie
PRInicjały
Nieznany użytkownikAnonim
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>
  )
}
Opóźnianie treści zastępczej
Przy szybkim łączu inicjały mogą mignąć na jedną klatkę, zanim pojawi się obraz. Przekaż 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.

MC
Maya ChenOsoba · koło
NW
NorthwindPrzestrzeń robocza · kwadrat
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.

MCOnlineJOZaraz wracamLPOfflineRSKonto zweryfikowane
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.

MCJOLPPR
+12
MCJOLPPR
+12
MCJOLPPR
+12
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.

MCOnline
Maya Chenmaya@northwind.dev
Właściciel
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ść

MCJONW
DobrzeKoła dla osób, kwadraty dla przestrzeni roboczych — kształt mówi, na co patrzysz.
MCJOLP
ŹleMieszanie kształtów przy tym samym rodzaju obiektów sprawia, że osoby wyglądają jak organizacje.

Inicjały

AK
DobrzeDwie wielkie litery: pierwsza litera imienia i pierwsza litera nazwiska.
aik
ŹleTrzy znaki lub więcej, małe litery albo emoji — w małych rozmiarach się nie mieszczą i wyglądają jak szum.

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-cover i 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. AvatarImage renderuje <img>: ustaw w alt nazwę osoby lub organizacji. Gdy nazwa jest widoczna obok awatara, ustaw alt="" i dodaj aria-hidden do Avatar, ż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. AvatarGroup ma rolę group, więc jego etykieta jest odczytywana. Nadaj mu atrybut aria-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-11 na gray-3) osiągają 4,5:1 w obu trybach.

Dokumentacja API

Avatar

Komponent główny. Przyjmuje wszystkie propsy Avatar Root z Base UI.

PropTypDomyślnie
size

20, 24, 32, 40 lub 56 pikseli. Tekst zastępczy i odznaka skalują się razem z awatarem.

"xs" | "sm" | "default" | "lg" | "xl""default"
shape

Koło dla osób, zaokrąglony kwadrat dla organizacji i aplikacji.

"circle" | "square""circle"
render

Zastępuje renderowany element span.

ReactElement | (props, state) => ReactElementBrak wartości domyślnej

AvatarImage

PropTypDomyślnie
src

Adres URL obrazu. Obraz jest wczytywany, zanim się pojawi; do tego czasu renderuje się treść zastępcza.

stringBrak wartości domyślnej
alt

Ustawiaj go zawsze: nazwa osoby lub organizacji albo pusty ciąg znaków, gdy nazwa jest widoczna obok.

stringBrak wartości domyślnej
onLoadingStatusChange

Wywoływana przy każdej zmianie stanu ładowania obrazu.

(status: "idle" | "loading" | "loaded" | "error") => voidBrak wartości domyślnej
keepMounted

Pozostawia element img zamontowany i wczytuje go na miejscu — potrzebne przy leniwym ładowaniu i komponentach optymalizujących obrazy.

booleanfalse

AvatarFallback

PropTypDomyślnie
delay

Liczba milisekund oczekiwania przed pokazaniem treści zastępczej — zapobiega mignięciu przy szybkim łączu.

number0
children

Dwuliterowe inicjały lub ikona.

ReactNodeBrak wartości domyślnej

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.