Skip to content

Avatar

A single component with one or two CSS variables and a theme() fallback. Use this shape when consumers should be able to override a specific value without touching anything else.

For most components, the Button recipe's pattern (color sets a fixed set of CSS variables, style consumes them) is a stronger starting point. For libraries that need wrapper-driven theming or automatic dark mode, see the Theming deep-dive.

Authoring

ts
// recipes/avatar.config.ts
import { defineComponent } from 'varia'

export default defineComponent('avatar', {
  base: 'inline-flex items-center justify-center rounded-full overflow-hidden bg-[var(--avatar-bg,theme(colors.gray.200))] text-[var(--avatar-fg,theme(colors.gray.700))] font-medium select-none',
  variants: {
    s: {
      sm: 'w-8 h-8 text-xs',
      md: 'w-10 h-10 text-sm',
      lg: 'w-14 h-14 text-base',
      xl: 'w-20 h-20 text-lg',
    },
    ring: 'ring-2 ring-[var(--avatar-ring,theme(colors.white))] ring-offset-2 ring-offset-[var(--avatar-ring-offset,theme(colors.gray.100))]',
  },
})

The pattern in detail:

text
bg-[var(--avatar-bg,theme(colors.gray.200))]
   └── arbitrary-value utility
       └── var() with fallback
           ├── --avatar-bg (consumer's override hook)
           └── theme(colors.gray.200) (your design-system default)

Live preview

JBVARPAC

Re-themed via CSS custom properties (warm peach):

JBVARP

Consumption (defaults)

html
<span class="avatar avatar-s-md">JB</span>
<span class="avatar avatar-s-lg avatar-ring">VA</span>

Re-theming without forking

The consumer scopes their override anywhere in CSS: globally, per-page, per-component.

css
/* App-wide brand override */
:root {
  --avatar-bg: oklch(0.7 0.15 60);   /* warm peach */
  --avatar-fg: oklch(0.2 0.05 60);   /* deep brown */
  --avatar-ring: oklch(0.95 0.02 60);
}

/* Or scoped to a component */
.team-card {
  --avatar-bg: oklch(0.55 0.2 250);
  --avatar-fg: white;
}

The consumer never touches the varia config. They never recompile. The override lives in their CSS where it belongs.

Generated class names

ClassPurpose
avatarBase styling, theming hooks
avatar-s-sm / -md / -lg / -xlSize scale
avatar-ringAdds offset ring around the image (also themable)

When to use this pattern

Whenever the consumer might want to override the value but probably won't. Drop a var(--token, theme(...)) in the expansion, ship the default, and surface the variable name in your docs.

Released under the MIT License.