Avatar
Image with an initials fallback. Sizes sm, default, lg; badge, group and count.
import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage,} from "@/components/ui/avatar";
export default function Demo() { return ( <div className="flex flex-wrap items-center gap-8"> <div className="flex items-center gap-3"> <Avatar size="sm"> <AvatarFallback>DL</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar size="lg"> <AvatarFallback>SC</AvatarFallback> </Avatar> </div> <Avatar size="lg"> <AvatarFallback>JB</AvatarFallback> <AvatarBadge /> </Avatar> <AvatarGroup> <Avatar> <AvatarFallback>NG</AvatarFallback> </Avatar> <Avatar> <AvatarFallback>ER</AvatarFallback> </Avatar> <Avatar> <AvatarFallback>SC</AvatarFallback> </Avatar> <AvatarGroupCount>+9</AvatarGroupCount> </AvatarGroup> </div> );}<script setup lang="ts">import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage,} from "@/components/ui/avatar";</script>
<template> <div class="flex flex-wrap items-center gap-8"> <div class="flex items-center gap-3"> <Avatar size="sm"> <AvatarFallback>DL</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar size="lg"> <AvatarFallback>SC</AvatarFallback> </Avatar> </div> <Avatar size="lg"> <AvatarFallback>JB</AvatarFallback> <AvatarBadge /> </Avatar> <AvatarGroup> <Avatar><AvatarFallback>NG</AvatarFallback></Avatar> <Avatar><AvatarFallback>ER</AvatarFallback></Avatar> <Avatar><AvatarFallback>SC</AvatarFallback></Avatar> <AvatarGroupCount>+9</AvatarGroupCount> </AvatarGroup> </div></template><script lang="ts"> import * as Avatar from "$lib/components/ui/avatar";</script>
<div class="flex flex-wrap items-center gap-8"> <div class="flex items-center gap-3"> <Avatar.Root size="sm"> <Avatar.Fallback>DL</Avatar.Fallback> </Avatar.Root> <Avatar.Root> <Avatar.Image src="https://github.com/shadcn.png" alt="shadcn" /> <Avatar.Fallback>CN</Avatar.Fallback> </Avatar.Root> <Avatar.Root size="lg"> <Avatar.Fallback>SC</Avatar.Fallback> </Avatar.Root> </div> <Avatar.Root size="lg"> <Avatar.Fallback>JB</Avatar.Fallback> <Avatar.Badge /> </Avatar.Root> <Avatar.Group> <Avatar.Root><Avatar.Fallback>NG</Avatar.Fallback></Avatar.Root> <Avatar.Root><Avatar.Fallback>ER</Avatar.Fallback></Avatar.Root> <Avatar.Root><Avatar.Fallback>SC</Avatar.Fallback></Avatar.Root> <Avatar.GroupCount>+9</Avatar.GroupCount> </Avatar.Group></div>Installation
Section titled “Installation”npx shadcn@latest add @edmi-ui/avatarpnpm dlx shadcn@latest add @edmi-ui/avataryarn dlx shadcn@latest add @edmi-ui/avatarbunx shadcn@latest add @edmi-ui/avatarPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install @base-ui/reactTerminal window pnpm add @base-ui/reactTerminal window yarn add @base-ui/reactTerminal window bun add @base-ui/reactCopy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-vue@latest add @edmi-ui/avatarpnpm dlx shadcn-vue@latest add @edmi-ui/avataryarn dlx shadcn-vue@latest add @edmi-ui/avatarbunx shadcn-vue@latest add @edmi-ui/avatarPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install reka-ui @vueuse/coreTerminal window pnpm add reka-ui @vueuse/coreTerminal window yarn add reka-ui @vueuse/coreTerminal window bun add reka-ui @vueuse/coreCopy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/avatar.jsonpnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/avatar.jsonyarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/avatar.jsonbunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/avatar.jsonPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Copy the code from Component source into your project and update the import paths to match your aliases.
import { Avatar, AvatarBadge, AvatarFallback, AvatarImage,} from "@/components/ui/avatar";
<div className="flex flex-wrap items-center gap-8"> <div className="flex items-center gap-3"> <Avatar size="sm"> <AvatarFallback>DL</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar size="lg"> <AvatarFallback>SC</AvatarFallback> </Avatar> </div> <Avatar size="lg"> <AvatarFallback>JB</AvatarFallback> <AvatarBadge /> </Avatar> {/* … */}</div><script setup lang="ts">import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage,} from "@/components/ui/avatar";</script>
<template> <div class="flex flex-wrap items-center gap-8"> <div class="flex items-center gap-3"> <Avatar size="sm"> <AvatarFallback>DL</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar size="lg"> <AvatarFallback>SC</AvatarFallback> </Avatar> </div> <Avatar size="lg"> <AvatarFallback>JB</AvatarFallback> <AvatarBadge /> </Avatar> <AvatarGroup> <Avatar><AvatarFallback>NG</AvatarFallback></Avatar> <Avatar><AvatarFallback>ER</AvatarFallback></Avatar> <Avatar><AvatarFallback>SC</AvatarFallback></Avatar> <AvatarGroupCount>+9</AvatarGroupCount> </AvatarGroup> </div></template><script lang="ts"> import * as Avatar from "$lib/components/ui/avatar";</script>
<div class="flex flex-wrap items-center gap-8"> <div class="flex items-center gap-3"> <Avatar.Root size="sm"> <Avatar.Fallback>DL</Avatar.Fallback> </Avatar.Root> <Avatar.Root> <Avatar.Image src="https://github.com/shadcn.png" alt="shadcn" /> <Avatar.Fallback>CN</Avatar.Fallback> </Avatar.Root> <Avatar.Root size="lg"> <Avatar.Fallback>SC</Avatar.Fallback> </Avatar.Root> </div> <Avatar.Root size="lg"> <Avatar.Fallback>JB</Avatar.Fallback> <Avatar.Badge /> </Avatar.Root> <Avatar.Group> <Avatar.Root><Avatar.Fallback>NG</Avatar.Fallback></Avatar.Root> <Avatar.Root><Avatar.Fallback>ER</Avatar.Fallback></Avatar.Root> <Avatar.Root><Avatar.Fallback>SC</Avatar.Fallback></Avatar.Root> <Avatar.GroupCount>+9</Avatar.GroupCount> </Avatar.Group></div>Component source
Section titled “Component source”import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";import { cn } from "cn";import type * as React from "react";
function Avatar({ className, size = "default", ...props}: AvatarPrimitive.Root.Props & { 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 select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border data-[size=lg]:size-10 data-[size=sm]:size-6", className, )} {...props} /> );}
function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) { return ( <AvatarPrimitive.Image data-slot="avatar-image" className={cn( "aspect-square size-full rounded-full object-cover", className, )} {...props} /> );}
// Initials are mono (DESIGN §1 type): every short code, number and address uses JetBrains Mono.function AvatarFallback({ className, ...props}: AvatarPrimitive.Fallback.Props) { return ( <AvatarPrimitive.Fallback data-slot="avatar-fallback" className={cn( "flex size-full items-center justify-center rounded-full bg-muted font-mono text-[13px] font-medium text-muted-foreground group-data-[size=sm]/avatar:text-[10px] group-data-[size=lg]/avatar:text-sm", className, )} {...props} /> );}
function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) { return ( <span data-slot="avatar-badge" className={cn( "absolute -right-px -bottom-px z-10 inline-flex items-center justify-center rounded-full bg-brand text-brand-foreground 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-[11px] 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.5 *: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 border border-border bg-muted font-mono text-xs 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, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage,};<script setup lang="ts">import type { AvatarRootProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { AvatarRoot } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = withDefaults(defineProps<AvatarRootProps & { class?: HTMLAttributes['class'] size?: 'default' | 'sm' | 'lg'}>(), { size: 'default',})
const delegatedProps = reactiveOmit(props, 'class', 'size')</script>
<template> <AvatarRoot data-slot="avatar" :data-size="size" v-bind="delegatedProps" :class="cn('group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border data-[size=lg]:size-10 data-[size=sm]:size-6', props.class)" > <slot /> </AvatarRoot></template><script setup lang="ts">import type { HTMLAttributes } from 'vue'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class']}>()</script>
<template> <span data-slot="avatar-badge" :class="cn('absolute -right-px -bottom-px z-10 inline-flex items-center justify-center rounded-full bg-brand text-brand-foreground 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-[11px] group-data-[size=default]/avatar:[&>svg]:size-2 group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2', props.class)" > <slot /> </span></template><script setup lang="ts">import type { AvatarFallbackProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { AvatarFallback } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<AvatarFallbackProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')</script>
<template> <!-- Initials are mono (DESIGN §1 type): every short code, number and address uses JetBrains Mono. --> <AvatarFallback data-slot="avatar-fallback" v-bind="delegatedProps" :class="cn('flex size-full items-center justify-center rounded-full bg-muted font-mono text-[13px] font-medium text-muted-foreground group-data-[size=sm]/avatar:text-[10px] group-data-[size=lg]/avatar:text-sm', props.class)" > <slot /> </AvatarFallback></template><script setup lang="ts">import type { HTMLAttributes } from 'vue'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class']}>()</script>
<template> <div data-slot="avatar-group" :class="cn('group/avatar-group flex -space-x-2.5 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background', props.class)" > <slot /> </div></template><script setup lang="ts">import type { HTMLAttributes } from 'vue'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class']}>()</script>
<template> <div data-slot="avatar-group-count" :class="cn('relative flex size-8 shrink-0 items-center justify-center rounded-full border border-border bg-muted font-mono text-xs 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', props.class)" > <slot /> </div></template><script setup lang="ts">import type { AvatarImageProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { AvatarImage } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<AvatarImageProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')</script>
<template> <AvatarImage data-slot="avatar-image" v-bind="delegatedProps" :class="cn('aspect-square size-full rounded-full object-cover', props.class)" > <slot /> </AvatarImage></template>export { default as Avatar } from "./Avatar.vue";export { default as AvatarBadge } from "./AvatarBadge.vue";export { default as AvatarFallback } from "./AvatarFallback.vue";export { default as AvatarGroup } from "./AvatarGroup.vue";export { default as AvatarGroupCount } from "./AvatarGroupCount.vue";export { default as AvatarImage } from "./AvatarImage.vue";<script lang="ts"> import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLAttributes } from "svelte/elements";
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();</script>
<span bind:this={ref} data-slot="avatar-badge" class={cn( "absolute -right-px -bottom-px z-10 inline-flex items-center justify-center rounded-full bg-brand text-brand-foreground 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-[11px] group-data-[size=default]/avatar:[&>svg]:size-2 group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className )} {...restProps}> {@render children?.()}</span><script lang="ts"> import { Avatar as AvatarPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), class: className, ...restProps }: AvatarPrimitive.FallbackProps = $props();</script>
<!-- Initials are mono (DESIGN §1 type): every short code, number and address uses JetBrains Mono. --><AvatarPrimitive.Fallback bind:ref data-slot="avatar-fallback" class={cn( "flex size-full items-center justify-center rounded-full bg-muted font-mono text-[13px] font-medium text-muted-foreground group-data-[size=sm]/avatar:text-[10px] group-data-[size=lg]/avatar:text-sm", className )} {...restProps}/><script lang="ts"> import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLAttributes } from "svelte/elements";
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();</script>
<div bind:this={ref} data-slot="avatar-group-count" class={cn( "relative flex size-8 shrink-0 items-center justify-center rounded-full border border-border bg-muted font-mono text-xs 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 )} {...restProps}> {@render children?.()}</div><script lang="ts"> import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLAttributes } from "svelte/elements";
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();</script>
<div bind:this={ref} data-slot="avatar-group" class={cn( "group/avatar-group flex -space-x-2.5 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background", className )} {...restProps}> {@render children?.()}</div><script lang="ts"> import { Avatar as AvatarPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), class: className, ...restProps }: AvatarPrimitive.ImageProps = $props();</script>
<AvatarPrimitive.Image bind:ref data-slot="avatar-image" class={cn("aspect-square size-full rounded-full object-cover", className)} {...restProps}/><script lang="ts"> import { Avatar as AvatarPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), loadingStatus = $bindable("loading"), size = "default", class: className, ...restProps }: AvatarPrimitive.RootProps & { size?: "default" | "sm" | "lg"; } = $props();</script>
<AvatarPrimitive.Root bind:ref bind:loadingStatus data-slot="avatar" data-size={size} class={cn( "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border data-[size=lg]:size-10 data-[size=sm]:size-6", className )} {...restProps}/>import Root from "./avatar.svelte";import Badge from "./avatar-badge.svelte";import Fallback from "./avatar-fallback.svelte";import Group from "./avatar-group.svelte";import GroupCount from "./avatar-group-count.svelte";import Image from "./avatar-image.svelte";
export { Badge, Badge as AvatarBadge, Fallback, Fallback as AvatarFallback, Group, Group as AvatarGroup, GroupCount, GroupCount as AvatarGroupCount, Image, Image as AvatarImage, Root, // Root as Avatar,};| Prop | Type | Default |
|---|---|---|
size |
sm | default | lg |
default |
Parts: Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup, AvatarGroupCount.
✦ Edmi additions
Section titled “✦ Edmi additions”- Initials render in JetBrains Mono; the badge uses
--brandwith a background ring.
