Shion Hoshimi
Translated 128 light novels
<script setup lang="ts">
import { Avatar, Card, Inline, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Card class="w-full max-w-sm">
<Inline gap="sm">
<Avatar size="lg" src="/avatars/selfie.webp" name="Shion Hoshimi" />
<Stack gap="none">
<Text class="font-medium">Shion Hoshimi</Text>
<Text tone="muted" size="sm">Translated 128 light novels</Text>
</Stack>
</Inline>
</Card>
</template>
Usage
import { Avatar } from '@hina-ui/vue'
src is the picture and name is the person behind it. The picture shows once it loads; failing that, the initials of the name; failing that, a generic icon.
<script setup lang="ts">
import { Avatar, Inline } from '@hina-ui/vue'
</script>
<template>
<Inline>
<Avatar src="/avatars/paper.webp" alt="Shion Hoshimi" />
<Avatar name="Shion Hoshimi" />
<Avatar />
</Inline>
</template>
Examples
Sizes
The three steps are 24, 32 and 40 pixels. An avatar is always round; there is no square or rounded-corner option.
<script setup lang="ts">
import { Avatar, Inline } from '@hina-ui/vue'
</script>
<template>
<Inline align="center">
<Avatar size="sm" src="/avatars/peek.webp" alt="Shion Hoshimi" />
<Avatar size="md" src="/avatars/peek.webp" alt="Shion Hoshimi" />
<Avatar size="lg" src="/avatars/peek.webp" alt="Shion Hoshimi" />
</Inline>
</template>
Fallbacks
Initials follow the writing system: a Chinese, Japanese or Korean name gives its first character, a Western one the initials of its first two parts. A picture that fails to load falls back the same way, and the broken image never shows.
Two initials
One character for CJK
An icon without a name
The image failed to load
<script setup lang="ts">
import { Avatar, Inline, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Inline align="start" class="gap-8">
<Stack gap="xs" align="center">
<Avatar name="Shion Hoshimi" />
<Text tone="muted" size="sm">Two initials</Text>
</Stack>
<Stack gap="xs" align="center">
<Avatar name="星见书音" />
<Text tone="muted" size="sm">One character for CJK</Text>
</Stack>
<Stack gap="xs" align="center">
<Avatar />
<Text tone="muted" size="sm">An icon without a name</Text>
</Stack>
<Stack gap="xs" align="center">
<Avatar src="/missing.png" name="Shion Hoshimi" />
<Text tone="muted" size="sm">The image failed to load</Text>
</Stack>
</Inline>
</template>
Groups
AvatarGroup stacks several avatars together. max caps how many are shown and folds the rest into a +N. A size on the group sets the size for all of them, and an avatar with its own size keeps it.
All of them
Three at most, the rest folded into a count
<script setup lang="ts">
import { Avatar, AvatarGroup, Stack, Text } from '@hina-ui/vue'
const members = [
{ src: '/avatars/paper.webp', name: 'Shion Hoshimi' },
{ src: '/avatars/peek.webp', name: 'Peek' },
{ src: '/avatars/glass.webp', name: 'Glass' },
{ src: '/avatars/huh.webp', name: 'Huh' },
{ src: '/avatars/run.webp', name: 'Run' },
{ src: '/avatars/sleep.webp', name: 'Sleep' },
]
</script>
<template>
<Stack>
<Stack gap="xs">
<Text tone="muted" size="sm">All of them</Text>
<AvatarGroup>
<Avatar v-for="m in members.slice(0, 4)" :key="m.name" :src="m.src" :alt="m.name" />
</AvatarGroup>
</Stack>
<Stack gap="xs">
<Text tone="muted" size="sm">Three at most, the rest folded into a count</Text>
<AvatarGroup :max="3" size="lg">
<Avatar v-for="m in members" :key="m.name" :src="m.src" :alt="m.name" />
</AvatarGroup>
</Stack>
</Stack>
</template>
Overlap spacing and separator rings apply directly to the group’s outer child elements. A custom avatar wrapped in a trigger does not need to forward group layout classes to its inner avatar. The wrapper’s rounding and decoration remain under the custom component’s control.
Custom children can import useAvatarGroup from the package root to read the group size reactively. It returns null outside a group. For example, preserve an individual avatar’s size override in a custom component:
import { computed } from 'vue'
import { useAvatarGroup, type AvatarVariants } from '@hina-ui/vue'
const props = defineProps<{ size?: AvatarVariants['size'] }>()
const group = useAvatarGroup()
const size = computed(() => props.size ?? group?.value.size ?? 'md')
max counts entries supplied by the default slot, including a v-for directly in that slot. Multiple avatars rendered inside a custom component are not counted separately; supply one avatar per slot entry when an accurate +N is required.
Custom content
The default slot replaces the built-in fallback with an icon or a short piece of text.
<script setup lang="ts">
import { Bot } from '@lucide/vue'
import { Avatar, Inline } from '@hina-ui/vue'
</script>
<template>
<Inline>
<Avatar>
<Bot />
</Avatar>
<Avatar>★</Avatar>
</Inline>
</template>
Behaviour
- The avatar is rendered by Image, so its address goes through
provideImageResolvertoo and a skeleton holds the circle while it loads. - The picture fills the circle with
object-fit: cover, so an image of a different aspect ratio is not stretched. - The fallback shows when there is no
srcor the picture fails; a failed picture is removed. - Image’s other props can be written straight on Avatar —
fallback,lazy,eagerand the rest are passed through.
Accessibility
- With a picture,
altis its alternative text; withoutaltit falls back toname. - The initials and the icon are decorative: a screen reader reads the name in the surrounding text rather than announcing the avatar twice.
API
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | The picture |
alt | string | — | Alternative text; falls back to name |
name | string | — | The name the initials come from |
size | 'sm' | 'md' | 'lg' | 'md' | Size |
class | string | — | Classes appended to the root |
| Slot | Description |
|---|---|
default | Replaces the built-in fallback |
AvatarGroup
| Prop | Type | Default | Description |
|---|---|---|---|
max | number | — | How many to show; the rest fold into a count |
size | 'sm' | 'md' | 'lg' | — | Size for the group; an avatar may override it |
class | string | — | Classes appended to the container |
| Slot | Description |
|---|---|
default | The avatars |
useAvatarGroup
useAvatarGroup() returns ComputedRef<AvatarGroupContext> | null. AvatarGroupContext is also exported from the package root.
| Field | Type | Description |
|---|---|---|
size | AvatarVariants['size'] | The nearest group’s size, or undefined if the group leaves it unset |