Zaidan

Command Palette

Search for a command to run...

GitHub

Avatar

An image element with a fallback for representing the user.

Installation

CLI

Manual

Copy and paste the following code into your project.

import * as ImagePrimitive from "@kobalte/core/image";
import type { PolymorphicProps } from "@kobalte/core/polymorphic";
import type { ComponentProps, ValidComponent } from "solid-js";
import { mergeProps, splitProps } from "solid-js";
import { cn } from "~/lib/utils";
type AvatarRootProps<T extends ValidComponent = "span"> = PolymorphicProps<
T,
ImagePrimitive.ImageRootProps<T>
> &
Pick<ComponentProps<T>, "class"> & {
size?: "sm" | "default" | "lg";
};
const Avatar = <T extends ValidComponent = "span">(props: AvatarRootProps<T>) => {
const mergedProps = mergeProps({ size: "default" }, props);
const [local, others] = splitProps(mergedProps as AvatarRootProps, ["class", "size"]);
return (
<ImagePrimitive.Root
class={cn(
"group/avatar relative z-avatar flex shrink-0 select-none after:absolute after:inset-0 after:border after:border-border after:mix-blend-darken dark:after:mix-blend-lighten",
local.class,
)}
data-size={local.size}
data-slot="avatar"
{...others}
/>
);
};
type AvatarImageProps<T extends ValidComponent = "img"> = PolymorphicProps<
T,
ImagePrimitive.ImageImgProps<T>
> &
Pick<ComponentProps<T>, "class">;
const AvatarImage = <T extends ValidComponent = "img">(props: AvatarImageProps<T>) => {
const [local, others] = splitProps(props as AvatarImageProps, ["class"]);
return (
<ImagePrimitive.Img
class={cn("z-avatar-image aspect-square size-full object-cover", local.class)}
data-slot="avatar-image"
{...others}
/>
);
};
type AvatarFallbackProps<T extends ValidComponent = "span"> = PolymorphicProps<
T,
ImagePrimitive.ImageFallbackProps<T>
> &
Pick<ComponentProps<T>, "class">;
const AvatarFallback = <T extends ValidComponent = "span">(props: AvatarFallbackProps<T>) => {
const [local, others] = splitProps(props as AvatarFallbackProps, ["class"]);
return (
<ImagePrimitive.Fallback
class={cn(
"z-avatar-fallback flex size-full items-center justify-center text-sm group-data-[size=sm]/avatar:text-xs",
local.class,
)}
data-slot="avatar-fallback"
{...others}
/>
);
};
type AvatarBadgeProps = ComponentProps<"span">;
function AvatarBadge(props: AvatarBadgeProps) {
const [local, others] = splitProps(props as AvatarBadgeProps, ["class"]);
return (
<span
data-slot="avatar-badge"
class={cn(
"absolute right-0 bottom-0 z-10 z-avatar-badge inline-flex select-none items-center justify-center rounded-full bg-blend-color ring-2",
"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",
local.class,
)}
{...others}
/>
);
}
type AvatarGroupProps = ComponentProps<"div">;
function AvatarGroup(props: AvatarGroupProps) {
const [local, others] = splitProps(props as AvatarGroupProps, ["class"]);
return (
<div
data-slot="avatar-group"
class={cn(
"group/avatar-group z-avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
local.class,
)}
{...others}
/>
);
}
type AvatarGroupCountProps = ComponentProps<"div">;
function AvatarGroupCount(props: AvatarGroupCountProps) {
const [local, others] = splitProps(props as AvatarGroupCountProps, ["class"]);
return (
<div
data-slot="avatar-group-count"
class={cn(
"relative z-avatar-group-count flex shrink-0 items-center justify-center ring-2 ring-background",
"",
local.class,
)}
{...others}
/>
);
}
export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };

Examples

Here are the source code of all the examples from the preview page:

Sizes

import {
Avatar,
AvatarFallback,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarSizes() {
return (
<Example title="Sizes">
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</div>
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar>
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</div>
</Example>
);
}

Badge

import {
Avatar,
AvatarBadge,
AvatarFallback,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarWithBadge() {
return (
<Example title="Badge">
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarImage src="https://github.com/jorgezreik.png" alt="@jorgezreik" />
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/jorgezreik.png" alt="@jorgezreik" />
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/jorgezreik.png" alt="@jorgezreik" />
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
</div>
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
<Avatar>
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
<Avatar size="lg">
<AvatarFallback>JZ</AvatarFallback>
<AvatarBadge />
</Avatar>
</div>
</Example>
);
}

Badge with Icon

import { Check, Plus } from "lucide-solid";
import {
Avatar,
AvatarBadge,
AvatarFallback,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarWithBadgeIcon() {
return (
<Example title="Badge with Icon">
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarImage src="https://github.com/pranathip.png" alt="@pranathip" />
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Plus />
</AvatarBadge>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/pranathip.png" alt="@pranathip" />
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Plus />
</AvatarBadge>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/pranathip.png" alt="@pranathip" />
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Plus />
</AvatarBadge>
</Avatar>
</div>
<div class="flex flex-wrap items-center gap-2">
<Avatar size="sm">
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Check />
</AvatarBadge>
</Avatar>
<Avatar>
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Check />
</AvatarBadge>
</Avatar>
<Avatar size="lg">
<AvatarFallback>PP</AvatarFallback>
<AvatarBadge>
<Check />
</AvatarBadge>
</Avatar>
</div>
</Example>
);
}

Group

import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarGroupExample() {
return (
<Example title="Group">
<AvatarGroup>
<Avatar size="sm">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
</AvatarGroup>
<AvatarGroup>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
</AvatarGroup>
<AvatarGroup>
<Avatar size="lg">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
</AvatarGroup>
</Example>
);
}

Group with Count

import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarGroupWithCount() {
return (
<Example title="Group with Count">
<AvatarGroup>
<Avatar size="sm">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>+3</AvatarGroupCount>
</AvatarGroup>
<AvatarGroup>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>+3</AvatarGroupCount>
</AvatarGroup>
<AvatarGroup>
<Avatar size="lg">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>+3</AvatarGroupCount>
</AvatarGroup>
</Example>
);
}

Group with Icon Count

import { Plus } from "lucide-solid";
import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarImage,
} from "~/components/ui/avatar";
function AvatarGroupWithIconCount() {
return (
<Example title="Group with Icon Count">
<AvatarGroup>
<Avatar size="sm">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="sm">
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>
<Plus />
</AvatarGroupCount>
</AvatarGroup>
<AvatarGroup>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar>
<AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>
<Plus />
</AvatarGroupCount>
</AvatarGroup>
<AvatarGroup>
<Avatar size="lg">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" class="grayscale" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" class="grayscale" />
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage
src="https://github.com/evilrabbit.png"
alt="@evilrabbit"
class="grayscale"
/>
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>
<Plus />
</AvatarGroupCount>
</AvatarGroup>
</Example>
);
}

In Empty

import { Plus } from "lucide-solid";
import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarImage,
} from "~/components/ui/avatar";
import { Button } from "~/components/ui/button";
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "~/components/ui/empty";
function AvatarInEmpty() {
return (
<Example title="In Empty">
<Empty class="w-full flex-none border">
<EmptyHeader>
<EmptyMedia>
<AvatarGroup>
<Avatar size="lg">
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" class="grayscale" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage
src="https://github.com/maxleiter.png"
alt="@maxleiter"
class="grayscale"
/>
<AvatarFallback>LR</AvatarFallback>
</Avatar>
<Avatar size="lg">
<AvatarImage
src="https://github.com/evilrabbit.png"
alt="@evilrabbit"
class="grayscale"
/>
<AvatarFallback>ER</AvatarFallback>
</Avatar>
<AvatarGroupCount>
<Plus />
</AvatarGroupCount>
</AvatarGroup>
</EmptyMedia>
<EmptyTitle>No Team Members</EmptyTitle>
<EmptyDescription>Invite your team to collaborate on this project.</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button>
<Plus />
Invite Members
</Button>
</EmptyContent>
</Empty>
</Example>
);
}