icon

Morainev0.5.0

Avatar
elementsavatar

Avatar

Circular user or entity avatar with fallback initials and an optional indicator.

Import#

import { Avatar } from 'moraine'

Slot Structure#

Avatar renders a single image/fallback frame. Use AvatarGroup for grouped avatars with an overflow counter.

Single avatar#

root
├── image
├── fallback
│ └── fallbackIcon (Icon, optional)
└── badge (optional)

Examples#

Single Avatar#

Fallback first, then image crossfades in after preload.

function SingleAvatar() {
const IMAGE_A = createSvgDataUrl('A', '#3f3f46')
const IMAGE_B = createSvgDataUrl('B', '#18181b')
const [source, setSource] = createSignal(IMAGE_A)
function createSvgDataUrl(label: string, backgroundColor: string): string {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" fill="${backgroundColor}"/><text x="32" y="38" text-anchor="middle" fill="white" font-family="sans-serif" font-size="24">${label}</text></svg>`
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`
}
return (
<div class="flex gap-4 items-center">
<Avatar
src={source()}
alt="Moraine"
classes={{
root: 'ring-ring',
}}
/>
<Button
variant="outline"
onClick={() => {
setSource((current) => (current === IMAGE_A ? IMAGE_B : IMAGE_A))
}}
>
Swap Source
</Button>
</div>
)
}

Sizes#

Scale single avatars from xs to xl.

function Sizes() {
const SIZES: AvatarSize[] = ['xs', 'sm', 'md', 'lg', 'xl']
return (
<div class="flex flex-wrap gap-4 items-end">
<For each={SIZES}>
{(size) => (
<div class="flex flex-col gap-2 items-center">
<Avatar size={size} text="MR" />
<span class="text-xs text-muted-foreground font-mono">{size}</span>
</div>
)}
</For>
</div>
)
}

Fallback Modes#

Text, initials-from-alt and fallback icon.

function FallbackModes() {
return (
<div class="flex flex-wrap gap-3 items-center">
<Avatar text="MR" />
<Avatar alt="Moraine Team" />
<Avatar fallback="i-lucide-user" />
</div>
)
}

Badge Positions#

Top/bottom + left/right corner badge.

function BadgePositions() {
return (
<div class="flex flex-wrap gap-3 items-center">
<Avatar text="A" badge="i-lucide-check" badgePosition="top-left" />
<Avatar text="B" badge="i-lucide-check" badgePosition="top-right" />
<Avatar text="C" badge="i-lucide-check" badgePosition="bottom-left" />
<Avatar text="D" badge="i-lucide-check" badgePosition="bottom-right" />
</div>
)
}

API Reference#

Attributes#

Slotroot0 attributes
Avatar frame that controls size, shape, image, fallback, and badge placement.
No attribute metadata for this slot.

Props#

PropTypeDefaultDescription
altstring | undefined
Accessible alt text for the avatar.
badgeIconT.Name
Icon name for the badge.
badgePosition"top-left" | "top-right" | "bottom-left" | "bottom-right" | undefinedbottom-right
Position of the badge.
classClassValue
Class applied to the component root or trigger element.
classesAvatarT.Classes | undefined
fallbackIconT.Name
Icon name to show as fallback.
onStatusChange((status: AvatarStatus) => void) | undefined
Callback when the loading status of the avatar changes.
refJSX.HTMLElementTags["span"] extends { ref?: infer Ref; } ? Ref : never | undefined
size"xs" | "sm" | "md" | "lg" | "xl" | undefined
srcstring | undefined
Source URL for the avatar image.
styleJSX.CSSProperties | undefined
stylesAvatarT.Styles | undefined
textstring | undefined
Initial text to show if image fails or is missing.
transition"none" | "fast" | "normal" | "slow" | undefined

Items#

PropTypeDefaultDescription
altstring | undefined
Accessible alt text for the avatar.
badgeIconT.Name
Icon name for the badge.
badgePositionNonNullable<"top-left" | "top-right" | "bottom-left" | "bottom-right" | undefined> | undefinedbottom-right
Position of the badge.
fallbackIconT.Name
Icon name to show as fallback.
onStatusChange((status: AvatarStatus) => void) | undefined
Callback when the loading status of the avatar changes.
srcstring | undefined
Source URL for the avatar image.
textstring | undefined
Initial text to show if image fails or is missing.