Aller au contenu

Avatar

Une image d'utilisateur avec, à défaut, ses initiales, pour les menus de profil, les fils de commentaires et les listes d'équipes — avec un effet « néobrutaliste » à bordures épaisses.

import {
  Avatar,
  AvatarBadge,

L’avatar affiche l’image d’un utilisateur et lui substitue AvatarFallback — initiales ou icône — pendant le chargement de l’image ou en cas d’échec, sans décalage de mise en page. Construit sur le composant Base UI Avatar et habillé du style néobrutaliste : une bordure épaisse de 2px et des initiales grasses en police de titrage.

À privilégier pour :

  • Menus de profil — l’avatar d’en-tête qui ouvre les actions du compte ; voir l’exemple Dropdown.
  • Fils de commentaires et flux d’activité — un visage à côté de chaque ligne d’auteur, les initiales prenant le relais des photos cassées ou manquantes.
  • Listes d’équipe et de membres — superposez les collaborateurs avec AvatarGroup et plafonnez le débordement avec AvatarGroupCount.

Installation

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/avatar.json
npx shadcn@latest add https://neobrutalism.com/r/base/avatar.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/avatar.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/avatar.json

Installez les dépendances suivantes :

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Copiez et collez le code suivant dans votre projet.

components/ui/avatar.tsx
"use client"

import * as React from "react"
import { Avatar as AvatarPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function Avatar({
  className,
  size = "default",
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Root> & {
  size?: "default" | "sm" | "lg"
}) {
  return (
    <AvatarPrimitive.Root
      data-slot="avatar"
      data-size={size}
      className={cn(
        "group/avatar relative flex size-8 shrink-0 rounded-full border-2 select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
        className
      )}
      {...props}
    />
  )
}

function AvatarImage({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
  return (
    <AvatarPrimitive.Image
      data-slot="avatar-image"
      className={cn(
        "aspect-square size-full rounded-full object-cover",
        className
      )}
      {...props}
    />
  )
}

function AvatarFallback({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
  return (
    <AvatarPrimitive.Fallback
      data-slot="avatar-fallback"
      className={cn(
        "flex size-full items-center justify-center rounded-full bg-muted font-head text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
        className
      )}
      {...props}
    />
  )
}

function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="avatar-badge"
      className={cn(
        "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
        "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
        "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
        "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
        className
      )}
      {...props}
    />
  )
}

function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="avatar-group"
      className={cn(
        "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
        className
      )}
      {...props}
    />
  )
}

function AvatarGroupCount({
  className,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="avatar-group-count"
      className={cn(
        "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
        className
      )}
      {...props}
    />
  )
}

export {
  Avatar,
  AvatarImage,
  AvatarFallback,
  AvatarGroup,
  AvatarGroupCount,
  AvatarBadge,
}

Adaptez les chemins d’import à la structure de votre projet.

Utilisation

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
<Avatar>
  <AvatarImage src="https://github.com/shadcn.png" />
  <AvatarFallback>CN</AvatarFallback>
</Avatar>

Composition

Utilisez la composition suivante pour construire un Avatar :

Avatar
├── AvatarImage
├── AvatarFallback
└── AvatarBadge

Utilisez la composition suivante pour construire un AvatarGroup :

AvatarGroup
├── Avatar
│   ├── AvatarImage
│   ├── AvatarFallback
│   └── AvatarBadge
├── Avatar
│   ├── AvatarImage
│   ├── AvatarFallback
│   └── AvatarBadge
└── AvatarGroupCount

Exemples

Simple

Un composant avatar simple avec une image et un substitut.

NB
import {
  Avatar,
  AvatarFallback,

Badge

Utilisez le composant AvatarBadge pour ajouter un badge à l’avatar. Le badge est placé en bas à droite de l’avatar.

import {
  Avatar,
  AvatarBadge,

Utilisez la prop className pour appliquer des styles personnalisés au badge : couleurs, tailles, etc.

<Avatar>
  <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
  <AvatarFallback>CN</AvatarFallback>
  <AvatarBadge className="bg-green-600 dark:bg-green-800" />
</Avatar>

Badge avec icône

Vous pouvez aussi utiliser une icône à l’intérieur de <AvatarBadge>.

import { PlusIcon } from "lucide-react"

import {

Groupe d’avatars

Utilisez le composant AvatarGroup pour afficher un groupe d’avatars.

import {
  Avatar,
  AvatarFallback,

Compteur du groupe d’avatars

Utilisez <AvatarGroupCount> pour ajouter un compteur au groupe.

import {
  Avatar,
  AvatarFallback,

Groupe d’avatars avec icône

Vous pouvez aussi utiliser une icône à l’intérieur de <AvatarGroupCount>.

import { PlusIcon } from "lucide-react"

import {

Tailles

Utilisez la prop size pour changer la taille de l’avatar.

import {
  Avatar,
  AvatarFallback,

Vous pouvez utiliser le composant Avatar comme déclencheur d’un menu déroulant.

"use client"

import {

RTL

Pour activer le RTL dans Neobrutalism, consultez le guide de configuration RTL.

"use client"

import * as React from "react"

Accessibilité

Un avatar est une image, les règles des images s’appliquent donc : donnez à AvatarImage un alt nommant la personne quand l’avatar est le seul élément qui l’identifie, et alt="" quand un nom visible figure juste à côté — faute de quoi les lecteurs d’écran annoncent le nom deux fois. Les initiales d’AvatarFallback sont du texte brut et sont lues à voix haute : veillez à ce qu’elles restent parlantes. Quand l’avatar ouvre un menu (voir Dropdown), placez le nom accessible sur le bouton déclencheur, pas sur l’image.

Référence API

Avatar

Le composant Avatar est le composant racine qui enveloppe l’image et le substitut de l’avatar.

PropTypeDefault
size"default" | "sm" | "lg""default"
classNamestring-

AvatarImage

Le composant AvatarImage affiche l’image de l’avatar. Il accepte toutes les props de Base UI Avatar Image.

PropTypeDefault
srcstring-
altstring-
classNamestring-

AvatarFallback

Le composant AvatarFallback affiche un substitut lorsque l’image ne se charge pas. Il accepte toutes les props de Base UI Avatar Fallback.

PropTypeDefault
classNamestring-

AvatarBadge

Le composant AvatarBadge affiche un indicateur (badge) sur l’avatar, généralement placé en bas à droite.

PropTypeDefault
classNamestring-

AvatarGroup

Le composant AvatarGroup affiche un groupe d’avatars qui se chevauchent.

PropTypeDefault
classNamestring-

AvatarGroupCount

Le composant AvatarGroupCount affiche un compteur dans un groupe d’avatars, indiquant généralement le nombre d’avatars supplémentaires.

PropTypeDefault
classNamestring-

Pour en savoir plus sur les props de Base UI Avatar, consultez la documentation Base UI.