Klarhimmel UI

Avatar

Stable

A person or team as a photo, or as initials on a colour picked from the name.

npx shadcn add @klarhimmel/avatar

When to use

  • Use for

    Next to a name in lists, comments, headers and assignee pickers.

  • Not for

    Logos and product images. Use Media.

  • Pairs with

    Badge, Card, a name in text.

Preview

Photo, photo, a photo that failed to load (initials), and a square for a team.

avatar.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Avatar } from '@/components/klarhimmel/ui/avatar';

export default function Example() {
  return (
    <Theme theme="brand">
      <Avatar name="Maja Lindqvist" src="/people/maja.jpg" />
    </Theme>
  );
}

Install

Import

import { Avatar } from '@/components/klarhimmel/ui/avatar';
Lands in
components/klarhimmel/ui/avatar.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
Render in
Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.

Examples

  • Sizes

    MLMLMLMLE
    import { Avatar } from '@/components/klarhimmel/ui/avatar';
    
    export default function AvatarSizes() {
      return (
        <div className="flex flex-wrap items-center gap-4">
          <Avatar name="Maja Lindqvist" size="xs" />
          <Avatar name="Maja Lindqvist" size="sm" />
          <Avatar name="Maja Lindqvist" />
          <Avatar name="Maja Lindqvist" size="lg" />
          <Avatar name="Exempelhotellet" size="lg" square />
        </div>
      );
    }
  • Fallback

    • Maja Lindqvist
    • Nils Berg
    • Ada Ek
    • Oskar Holm
    • Sofia Nord
    GWNo photo, or one that fails to load, shows initials.
    MLNBAEOH
    import { Avatar } from '@/components/klarhimmel/ui/avatar';
    
    const people = ['Maja Lindqvist', 'Nils Berg', 'Ada Ek', 'Oskar Holm', 'Sofia Nord'];
    
    export default function AvatarFallback() {
      return (
        <div className="flex flex-col gap-4">
          <ul className="flex flex-wrap gap-4">
            {people.map((name) => (
              <li key={name} className="flex items-center gap-2 text-kh-small">
                <Avatar name={name} decorative />
                {name}
              </li>
            ))}
          </ul>
          <div className="flex items-center gap-3 text-kh-small text-kh-muted">
            <Avatar name="Guest without a photo" />
            No photo, or one that fails to load, shows initials.
          </div>
          <div className="flex -space-x-2">
            {people.slice(0, 4).map((name) => (
              <Avatar key={name} name={name} size="sm" className="ring-2 ring-kh-canvas" />
            ))}
          </div>
        </div>
      );
    }

API reference

PropTypeDefaultDescription
namestring-Required. The accessible name and the source of the initials and colour.
size'xs' | 'sm' | 'md' | 'lg''md'24, 32, 40 and 56 px.
squarebooleanfalseA rounded square, for teams and organisations.
src / srcSetstring-A photo. Falls back to initials if it fails to load.
decorativebooleanfalseHide it from assistive tech.
classNamestring-Extra classes, merged after the component's own.

Accessibility

KeyDoes
TabSkips it: an avatar is not interactive
Screen readerReads the name. With decorative set, it reads nothing

Not interactive. Wrap it in a link or button yourself if it should be.

Accessibility