UnflowUI
Components

UserTag

A chip that pairs an avatar (with optional status badge) and a name label — for representing a person or account inline.

Overview

UserTag combines Avatar and Tag into a single component: it renders an avatar (image, initials, or fallback icon, plus an optional status badge) next to a text label. Like Tag, it renders as a static <div> by default and becomes a <button> when an onClick prop is provided, and icon slots (startIcon, endIcon) can have their own independent onClick handlers via slotProps — enabling actions like "remove" without triggering the tag's own click.

Import

import { UserTag } from '@unflow.io/ui/components/UserTag';

Props

PropTypeDefaultDescription
labelstringText shown next to the avatar
srcstringAvatar image URL, forwarded to the internal Avatar
status'invisible' | 'away' | 'available' | 'unavailable'Status shown as a badge on the avatar
variant'white' | 'grey''white'Background color family
size'sm' | 'md' | 'lg''sm'Tag size (also controls the internal avatar size)
roundedbooleanfalseRenders a fully rounded (pill) shape instead of the default radius
startIconReactNodeIcon before the avatar
endIconReactNodeIcon after the label
onClick(e: MouseEvent<HTMLButtonElement>) => voidMakes the tag a button
disabledbooleanfalseSets aria-disabled="true" and makes the tag inert

Basic usage

Jane Doe

<UserTag label="Jane Doe" src="https://i.pravatar.cc/60" status="available" />

Statuses

The status prop is passed through to the internal Avatar and rendered as a badge over it.

Available

Away

Unavailable

No badge

<UserTag label="Available" src="https://i.pravatar.cc/60" status="available" />
<UserTag label="Away" src="https://i.pravatar.cc/60?img=2" status="away" />
<UserTag label="Unavailable" src="https://i.pravatar.cc/60?img=3" status="unavailable" />
<UserTag label="No badge" src="https://i.pravatar.cc/60?img=4" status="invisible" />

Sizes

Small

Medium

Large

<UserTag label="Small" src="https://i.pravatar.cc/60" status="available" size="sm" />
<UserTag label="Medium" src="https://i.pravatar.cc/60" status="available" size="md" />
<UserTag label="Large" src="https://i.pravatar.cc/60" status="available" size="lg" />

Interactive

Removable

When onClick is provided, the entire tag becomes a <button>:

<UserTag
  label="Clickable"
  src="https://i.pravatar.cc/60"
  status="available"
  onClick={() => console.log('user tag clicked')}
/>

Icon onClick handlers in slotProps stop propagation — they don't trigger the main tag handler, which makes them useful for "remove" actions:

<UserTag
  label="Removable"
  src="https://i.pravatar.cc/60"
  status="available"
  endIcon={<X />}
  slotProps={{ endIcon: { onClick: () => console.log('remove clicked') } }}
/>

Customization (slots & slotProps)

SlotTypeDescription
avatarReactNodeOverride the entire avatar element
Slot PropPropsDescription
labelBaseHTMLProps<HTMLParagraphElement>Override the text element
startIconBaseHTMLProps<HTMLDivElement | HTMLButtonElement>Override start icon wrapper
endIconBaseHTMLProps<HTMLDivElement | HTMLButtonElement>Override end icon wrapper
avatarOmit<IAvatar, 'src' | 'size' | 'status'>Props forwarded to the internal Avatar (e.g. name, alt, disableStatusBadge) — src, size and status are controlled by UserTag itself

Accessibility

  • Renders as a <div> by default; becomes a <button> when onClick is provided, enabling keyboard focus and Enter/Space activation.
  • disabled sets aria-disabled="true" and marks the tag inert, removing it from the accessibility tree and tab order while it stays visible.
  • Icon slots (startIcon/endIcon) with their own onClick in slotProps render as independently focusable buttons; their clicks stop propagation so they don't also trigger the tag's own onClick.
  • Provide meaningful label text — the status badge conveys state visually, but the label remains the primary accessible content.