Saltar al contenido

Avatar

Una imagen de usuario con las iniciales como alternativa para los menús de perfil, los hilos de comentarios y las listas de equipos, con ese estilo neobrutalista de bordes gruesos.

import {
  Avatar,
  AvatarBadge,

El avatar muestra la imagen de un usuario y la sustituye por AvatarFallback —iniciales o un icono— mientras la imagen carga o cuando falla, sin provocar saltos de diseño. Está construido sobre el componente Base UI Avatar y sigue la receta neobrutalista: un borde grueso de 2px e iniciales en negrita con la tipografía de encabezados.

Úsalo cuando:

  • Menús de perfil — el avatar de la cabecera que abre las acciones de la cuenta; mira el ejemplo de Dropdown.
  • Hilos de comentarios y feeds de actividad — una cara junto a cada línea de autor, con iniciales que cubren las fotos rotas o ausentes.
  • Listas de equipos y miembros — superpón colaboradores con AvatarGroup y resume el excedente con AvatarGroupCount.

Instalación

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

Instala las siguientes dependencias:

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

Copia y pega el siguiente código en tu proyecto.

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,
}

Actualiza las rutas de importación para que coincidan con la estructura de tu proyecto.

Uso

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

Composición

Usa la siguiente composición para construir un Avatar:

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

Usa la siguiente composición para construir un AvatarGroup:

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

Ejemplos

Básico

Un componente de avatar básico con una imagen y un sustituto.

NB
import {
  Avatar,
  AvatarFallback,

Badge

Usa el componente AvatarBadge para añadir un badge al avatar. El badge se coloca en la parte inferior derecha del avatar.

import {
  Avatar,
  AvatarBadge,

Usa la prop className para aplicar estilos personalizados al badge, como colores, tamaños, 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 con icono

También puedes usar un icono dentro de <AvatarBadge>.

import { PlusIcon } from "lucide-react"

import {

Grupo de avatares

Usa el componente AvatarGroup para mostrar un grupo de avatares.

import {
  Avatar,
  AvatarFallback,

Contador del grupo de avatares

Usa <AvatarGroupCount> para añadir un contador al grupo.

import {
  Avatar,
  AvatarFallback,

Grupo de avatares con icono

También puedes usar un icono dentro de <AvatarGroupCount>.

import { PlusIcon } from "lucide-react"

import {

Tamaños

Usa la prop size para cambiar el tamaño del avatar.

import {
  Avatar,
  AvatarFallback,

Menú desplegable

Puedes usar el componente Avatar como disparador de un menú desplegable.

"use client"

import {

RTL

Para activar la compatibilidad con RTL en Neobrutalism, consulta la guía de configuración de RTL.

"use client"

import * as React from "react"

Accesibilidad

Un avatar es una imagen, así que se aplican las reglas de las imágenes: dale a AvatarImage un alt con el nombre de la persona cuando el avatar sea lo único que la identifica, y alt="" cuando haya un nombre visible justo al lado; de lo contrario, los lectores de pantalla anuncian el nombre dos veces. Las iniciales de AvatarFallback son texto normal y se leen en voz alta, así que procura que signifiquen algo. Cuando el avatar abre un menú (mira Dropdown), coloca el nombre accesible en el botón disparador, no en la imagen.

Referencia de API

Avatar

El componente Avatar es el componente raíz que envuelve la imagen y el sustituto del avatar.

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

AvatarImage

El componente AvatarImage muestra la imagen del avatar. Acepta todas las props de Base UI Avatar Image.

PropTypeDefault
srcstring-
altstring-
classNamestring-

AvatarFallback

El componente AvatarFallback muestra un sustituto cuando la imagen no se carga. Acepta todas las props de Base UI Avatar Fallback.

PropTypeDefault
classNamestring-

AvatarBadge

El componente AvatarBadge muestra un indicador (badge) sobre el avatar, normalmente colocado en la parte inferior derecha.

PropTypeDefault
classNamestring-

AvatarGroup

El componente AvatarGroup muestra un grupo de avatares que se superponen.

PropTypeDefault
classNamestring-

AvatarGroupCount

El componente AvatarGroupCount muestra un contador en un grupo de avatares, que normalmente indica el número de avatares adicionales.

PropTypeDefault
classNamestring-

Para más información sobre las props de Base UI Avatar, consulta la documentación de Base UI.