Avatar Group
Pile d'avatars superposes pour les participants, les personnes assignees et les contextes collaboratifs. Installez Avatar Group depuis le registre VLLNT UI avec la CLI shadcn.
Pile d'avatars superposes pour les participants, les personnes assignees et les contextes collaboratifs. Fait partie de la famille data dans VLLNT UI, il est publie comme entree de registre lisible par machine — copiez la source directement dans votre application avec la CLI shadcn et possedez-la, sans dependance d'execution a une bibliotheque de composants.
Apercu
Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.
Installation
Ajoutez Avatar Group a votre projet avec la CLI shadcn. La source arrive dans votre code, prete a etre adaptee :
pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/avatar-group.jsonSource
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
import { Avatar, AvatarFallback, AvatarImage } from "../avatar/avatar";
const avatarGroupVariants = cva("flex items-center", {
defaultVariants: {
size: "md",
},
variants: {
size: {
lg: "-space-x-4",
md: "-space-x-3",
sm: "-space-x-2.5",
},
},
});
const avatarItemVariants = cva(
"ring-2 ring-background border border-border bg-muted text-muted-foreground",
{
defaultVariants: {
size: "md",
},
variants: {
size: {
lg: "size-12 text-sm",
md: "size-10 text-xs",
sm: "size-8 text-[11px]",
},
},
},
);
const overflowBadgeVariants = cva(
"inline-flex shrink-0 items-center justify-center rounded-full border border-border bg-muted font-medium text-muted-foreground ring-2 ring-background",
{
defaultVariants: {
size: "md",
},
variants: {
size: {
lg: "h-12 min-w-12 px-3 text-sm",
md: "h-10 min-w-10 px-2.5 text-xs",
sm: "h-8 min-w-8 px-2 text-[11px]",
},
},
},
);
export type AvatarGroupItem = {
alt: string;
fallback: string;
src?: string;
};
export type AvatarGroupProps = React.HTMLAttributes<HTMLDivElement> &
VariantProps<typeof avatarGroupVariants> & {
items: AvatarGroupItem[];
max?: number;
overflowLabel?: (hiddenCount: number) => string;
};
const AvatarGroup = ({
className,
items,
max,
overflowLabel,
ref: reference,
size,
...props
}: AvatarGroupProps & { ref?: React.Ref<HTMLDivElement> }) => {
const visibleItems = max === undefined ? items : items.slice(0, max);
const hiddenCount = max === undefined ? 0 : Math.max(items.length - max, 0);
return (
<div
className={cn(avatarGroupVariants({ size }), className)}
ref={reference}
{...props}
>
{visibleItems.map((item, index) => (
<Avatar
className={avatarItemVariants({ size })}
key={item.src ?? item.alt}
style={{ zIndex: visibleItems.length - index }}
>
{item.src ? <AvatarImage alt={item.alt} src={item.src} /> : null}
<AvatarFallback>{item.fallback}</AvatarFallback>
</Avatar>
))}
{hiddenCount > 0 ? (
<span className={overflowBadgeVariants({ size })}>
{overflowLabel ? overflowLabel(hiddenCount) : `+${hiddenCount}`}
</span>
) : null}
</div>
);
};
AvatarGroup.displayName = "AvatarGroup";
export { AvatarGroup, avatarGroupVariants, avatarItemVariants };
Stories
Explorez chaque variante et etat dans le Storybook interactif :
Apercu
Basculez entre clair et sombre pour inspecter l'apercu Storybook integre.