Skip to content
Brok UI

Loading…

No results

User Identity

Open source

A consistent user identity row with avatar fallback, display name, secondary identifier, and optional role and presence status in compact or full form.

Version
v1.1.2
Stability
stable
License
MIT
Related
Avatar
Status
Badge

Preview

Online Avery Stone Owner [email protected]
Mode
previews.components.user-identity.default.blade.php Blade
<x-ui.user-identity name="Avery Stone" secondary="avery@example.com" role="Owner" status="online" />
Compact Current
Full Current
Card Current

Installation

terminal
php artisan ui:add user-identity

Registry contract

php artisan ui:add user-identity writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.

  • blade resources/views/components/ui/user-identity.blade.php
Registry dependencies
avatar badge
Packages
composer: jml/brok:^0.2

Use with AI

A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.

user-identity.md
# Brok UI: User Identity (`user-identity`)

A consistent user identity row with avatar fallback, display name, secondary identifier, and optional role and presence status in compact or full form.

Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.

## Install

```bash
php artisan ui:add user-identity
```

## Usage

```blade
<x-ui.user-identity name="Avery Stone" secondary="[email protected]" role="Owner" status="online" />
```

## Props

- `name` (string, default `required`) — Visible display name.
- `secondary` (string|null, default `null`) — Email, handle, or another secondary identifier.
- `src` (url|null, default `null`) — Validated image URL.
- `fallback` (string|null, default `null`) — Explicit avatar fallback; initials are derived when absent.
- `role` (string|null, default `null`) — Optional role label.
- `status` (online|offline|busy|away|neutral|null, default `null`) — Optional visible presence state.
- `mode` (compact|full|card, default `full`) — compact: avatar and name on one line; full: name, role and a secondary line; card: a bordered card with a large avatar, the status in words and an actions slot.
- `href` (url|null, default `null`) — Optional profile link.

## Use when

- Use to summarize, sequence, or present data so users can scan it quickly.
- Show the same user identity contract in tables, lists, audit feeds, and menus.

## Avoid when

- Do not add display-only ornament when the user needs actionable structure or exact comparison instead.
- Use avatar when only an image or initials are needed.

## Anti-patterns

- Adding display ornament without informational value

## Rules

- Use the `<brok:user-identity>` tag (or `<x-ui.user-identity>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.

## Links

- Docs: https://brokui.dev/docs/components/user-identity
- Registry JSON (files, props, contract): https://brokui.dev/r/open/user-identity.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

Examples

long-content.blade.php Blade
<div class="max-w-xs">
    <x-ui.user-identity name="{{ __('A deliberately long translated display name for overflow testing') }}" secondary="a-very-long-secondary-identifier@example.test" role="{{ __('Organization administrator') }}" status="online" />
</div>
modes.blade.php Blade
{{-- compact for a table cell or a mention, full for a list row, card for a profile header. --}}
<div class="flex w-full max-w-md flex-col items-start gap-6">
    <x-ui.user-identity name="Morgan Lee" mode="compact" status="away" />
    <x-ui.user-identity name="Morgan Lee" secondary="morgan@example.com" role="Editor" status="away" href="#" />
    <x-ui.user-identity name="Morgan Lee" secondary="morgan@example.com" role="Editor" status="away" mode="card" class="w-full">
        <x-slot:actions>
            <x-ui.button variant="outline" size="sm">{{ __('Message') }}</x-ui.button>
            <x-ui.button variant="outline" size="sm" icon-label="{{ __('More') }}">
                <svg viewBox="0 0 24 24" fill="currentColor" class="size-4"><circle cx="5" cy="12" r="1.75" /><circle cx="12" cy="12" r="1.75" /><circle cx="19" cy="12" r="1.75" /></svg>
            </x-ui.button>
        </x-slot:actions>
    </x-ui.user-identity>
</div>
states.blade.php Blade
{{-- Every presence state, and a long RTL name that truncates. --}}
<div class="flex w-full max-w-md flex-col items-start gap-4">
    <div class="flex flex-wrap gap-6">
        <x-ui.user-identity name="Ava Chen" mode="compact" status="online" />
        <x-ui.user-identity name="Ben Ortiz" mode="compact" status="busy" />
        <x-ui.user-identity name="Cleo Park" mode="compact" status="away" />
        <x-ui.user-identity name="Dev Rao" mode="compact" status="offline" />
    </div>
    <div dir="rtl" class="w-full">
        <x-ui.user-identity name="اسم طويل جداً لاختبار التخطيط والاقتطاع" secondary="identity@example.com" role="Administrator" status="busy" class="max-w-xs" />
    </div>
</div>

API

manifest knowledge + registry-derived coverage

Props

Props accepted by this component: name, type, default value and description.
Prop Type Default Description
name string required Visible display name.
secondary string | null null Email, handle, or another secondary identifier.
src url | null null Validated image URL.
fallback string | null null Explicit avatar fallback; initials are derived when absent.
role string | null null Optional role label.
status online | offline | busy | away | neutral | null null Optional visible presence state.
mode compact | full | card full compact: avatar and name on one line; full: name, role and a secondary line; card: a bordered card with a large avatar, the status in words and an actions slot.
href url | null null Optional profile link.

Slots

Default Blade slot only.

Data slots

Stable hooks for CSS overrides and browser tests.

user-identity user-identity-status

Behavior

  • Derives a two-letter fallback when explicit initials are absent.
  • Declares registry capability flags: a11y, authoredStateFixtures, responsive, rtl, darkMode, localized.

Guidance

Scannable data display

Present data for rapid scanning.

Use when

  • Use to summarize, sequence, or present data so users can scan it quickly.
  • Show the same user identity contract in tables, lists, audit feeds, and menus.

Avoid when

  • Do not add display-only ornament when the user needs actionable structure or exact comparison instead.
  • Use avatar when only an image or initials are needed.

Use instead

  • Table for exact comparison
  • Plain text for a single value

Anti-patterns

  • Adding display ornament without informational value
Anatomy
user-identity
Theming hooks
Composes semantic avatar, badge, and status tokens.

Accessibility

WCAG 2.2 AA Keyboard focus-visible RTL-ready Localized labels Dark mode
Keyboard
No component-owned keyboard interaction; native element behavior applies.
Focus
none
  • Role and status use visible text, not color alone.
  • Image and fallback labels use the display name.
  • Semantic HTML and a stable data-slot attribute for styling and scripting hooks.
  • Focus-visible rings use the ring token, so keyboard focus is always visible.
  • Disabled and invalid states are conveyed to assistive tech, not by color alone.
  • Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
  • Labels go through __() and layout uses logical properties (ms-*, text-start), so it mirrors under dir="rtl" — flip the preview to RTL to confirm.
  • Dark mode uses the same semantic tokens under the dark class; high contrast follows forced-color system tokens.

Livewire

Safe

Livewire can update this component through forwarded wire:* attributes.

Source

The exact, editable file ui:add writes into your app. Previews render this same code; there are no preview-only components.

resources/views/components/ui/user-identity.blade.php Blade
@props([
    'name',
    'secondary' => null,
    'src' => null,
    'fallback' => null,
    'role' => null,
    // online | busy | away | offline | neutral — drawn as a dot on the avatar's
    // edge (named for assistive tech), never as a second text tag in the row.
    'status' => null,
    // compact: avatar sm + name on one line. full: avatar md, name + role, a
    // secondary line. card: a bordered card with avatar lg and room for actions.
    'mode' => 'full',
    'href' => null,
])

@php
    $mode = in_array($mode, ['compact', 'full', 'card'], true) ? $mode : 'full';
    $tag = filled($href) ? 'a' : ($mode === 'card' ? 'div' : 'span');
    $status = in_array($status, ['online', 'busy', 'away', 'offline', 'neutral'], true) ? $status : null;
    $initials = $fallback ?? collect(preg_split('/\s+/', trim((string) $name)) ?: [])
        ->filter()
        ->take(2)
        ->map(fn ($part) => mb_strtoupper(mb_substr($part, 0, 1)))
        ->implode('');
    $avatarSize = ['compact' => 'sm', 'full' => 'md', 'card' => 'lg'][$mode];
    // The presence dot sits on the avatar's bottom-end edge, ringed by the surface.
    $dotSize = ['compact' => 'size-2', 'full' => 'size-3', 'card' => 'size-3'][$mode];
    $dotColour = [
        'online' => 'bg-success',
        'busy' => 'bg-destructive',
        'away' => 'bg-warning',
        'offline' => 'border-2 border-muted-foreground/60 bg-background',
        'neutral' => 'bg-muted-foreground/60',
    ];
    $statusLabels = ['online' => __('Online'), 'busy' => __('Busy'), 'away' => __('Away'), 'offline' => __('Offline'), 'neutral' => __('Unknown')];
    $rootClasses = match ($mode) {
        'card' => 'flex min-w-0 items-center gap-4 rounded-lg border border-border bg-card p-6 text-start text-card-foreground',
        default => 'inline-flex min-w-0 items-center gap-3 text-start text-foreground',
    };
    if ($tag === 'a') {
        $rootClasses .= ' rounded-md transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-[length:var(--ring-width)] focus-visible:ring-ring focus-visible:ring-offset-[length:var(--ring-offset-width)] focus-visible:ring-offset-background motion-reduce:transition-none';
        $rootClasses .= $mode === 'card' ? ' hover:bg-muted/40' : '';
    }
@endphp

<{{ $tag }}
    data-slot="user-identity"
    data-mode="{{ $mode }}"
    @if ($status) data-status="{{ $status }}" @endif
    @if ($tag === 'a') href="{{ $href }}" @endif
    {{ $attributes->merge(['class' => $rootClasses]) }}
>
    <span class="relative inline-flex shrink-0">
        <x-ui.avatar :src="$src" :alt="$src ? (string) $name : ''" :fallback="$initials" :size="$avatarSize" />
        @if ($status)
            <span data-slot="user-identity-status" class="absolute bottom-0 end-0 rounded-full ring-2 ring-background {{ $dotSize }} {{ $dotColour[$status] }}" title="{{ $statusLabels[$status] }}" aria-hidden="true"></span>
            <span class="sr-only">{{ $statusLabels[$status] }}</span>
        @endif
    </span>

    <span class="min-w-0 flex-1">
        <span class="flex min-w-0 items-center gap-2">
            <span class="truncate {{ $mode === 'card' ? 'text-base font-semibold' : 'text-sm font-medium' }}">{{ $name }}</span>
            @if (filled($role))
                <x-ui.badge variant="outline" size="sm" class="shrink-0">{{ $role }}</x-ui.badge>
            @endif
        </span>
        @if ($mode !== 'compact' && filled($secondary))
            <span class="block truncate text-sm text-muted-foreground">{{ $secondary }}</span>
        @endif
        @if ($mode === 'card' && $status)
            <span class="mt-1 block text-xs text-muted-foreground">{{ $statusLabels[$status] }}</span>
        @endif
    </span>

    @isset($actions)
        <span class="flex shrink-0 items-center gap-2">{{ $actions }}</span>
    @endisset
</{{ $tag }}>

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.1.2
Status
Stable
License
open
Accessibility reviewed
No review date recorded
Last breaking change
No date recorded
Deprecation
Not deprecated
Contract
v6
Foundation
≥ 1.0.0