Skip to content

Avatar

Display user avatars with support for images, initials, icons, status indicators, and various styling options. Built for Pulse Framework with full reactivity support.

Import

tsx
import { Avatar, Pulse } from '@odyssee/components';

Basic Usage

Code Éditable
Résultat

With Initials

Display user initials when no image is available.

Code Éditable
Résultat

Sizes

Five size options are available: xs, sm, md, lg, and xl.

Code Éditable
Résultat

Rounded Styles

Control the border radius with the rounded prop.

Code Éditable
Résultat

Colors for Initials

When using initials, you can customize the color scheme with color and colorVariant props.

Code Éditable
Résultat

Status Indicator

Add status indicators to show online/offline state.

Code Éditable
Résultat

Status Position

Control the position of the status indicator.

Code Éditable
Résultat

Icon Placeholder

Display a default icon when no image or initials are provided.

Code Éditable
Résultat

With Tooltip

Add tooltips to provide additional information.

tsx
const avatarWithTooltip = (
  <Avatar
    src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5"
    status="online"
    tooltip="Mark Wanner is online"
  />
);

Clickable Avatar

Make avatars clickable for navigation or actions.

tsx
const clickableAvatar = (
  <Avatar
    src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5"
    href="/profile/user-123"
  />
);

// Or with onClick
const onClickAvatar = (
  <Avatar
    src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5"
    onClick={() => console.log('Avatar clicked!')}
  />
);

Reactive Status

Control status dynamically with Pulse signals.

tsx
const userStatus = Pulse.signal<'online' | 'offline' | 'away' | 'busy'>('online');

// Simulate status changes
setInterval(() => {
  const statuses = ['online', 'offline', 'away', 'busy'] as const;
  const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
  userStatus(randomStatus);
}, 3000);

const reactiveAvatar = (
  <Avatar
    src="https://images.unsplash.com/photo-1568602471122-7832951cc4c5"
    status={userStatus}
  />
);

Complete Example

Here's a comprehensive example with multiple features:

tsx
import { Avatar, Badge, Pulse } from '@odyssee/components';

const UserProfile = () => {
  const user = Pulse.signal({
    name: 'Mark Wanner',
    avatar: 'https://images.unsplash.com/photo-1568602471122-7832951cc4c5',
    status: 'online' as const,
    role: 'Admin',
    initials: 'MW'
  });

  const handleAvatarClick = () => {
    console.log('Navigate to profile:', user().name);
  };

  return (
    <div class="flex items-center gap-4 p-6 bg-white rounded-lg shadow">
      {/* Avatar with status */}
      <Avatar
        src={user().avatar}
        alt={user().name}
        status={user().status}
        statusPosition="bottom"
        size="lg"
        onClick={handleAvatarClick}
        tooltip={`${user().name} is ${user().status}`}
      />

      {/* User info */}
      <div class="flex-1">
        <div class="flex items-center gap-2">
          <h3 class="text-lg font-semibold">{user().name}</h3>
          <Badge
            variant="soft"
            color="primary"
            size="sm"
          >
            {user().role}
          </Badge>
        </div>
        <p class="text-sm text-gray-500">
          Status: <span class="capitalize">{user().status}</span>
        </p>
      </div>
    </div>
  );
};

Props

PropTypeDefaultDescription
srcstring-Image URL
altstring"Avatar"Image alt text
namestring-User name (used to generate initials)
initialsstring-Display initials instead of image
variant"image" | "initials" | "icon"Auto-detectedAvatar display variant
size"xs" | "sm" | "md" | "lg" | "xl""md"Avatar size
roundedtrue | false | "full" | "lg""full"Border radius style
color"gray" | "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "white""gray"Color for initials variant
colorVariant"solid" | "soft" | "outline""solid"Color style for initials
status"none" | "online" | "offline" | "away" | "busy""none"Status indicator
statusPosition"top" | "bottom""bottom"Status indicator position
statusColorstring-Custom status indicator color
tooltipstring-Tooltip text on hover
hrefstring-Make avatar a link
onClick(event: Event) => void-Click event handler
classNamestring-Additional CSS classes
idstringAuto-generatedHTML id attribute

Accessibility

The Avatar component follows accessibility best practices:

  • ✅ Proper alt attributes for images
  • ✅ Semantic HTML structure
  • ✅ Keyboard navigation support for clickable avatars
  • ✅ ARIA labels for status indicators
  • ✅ Tooltips for additional context
  • ✅ Sufficient color contrast

ARIA Attributes

tsx
const accessibleAvatar = (
  <Avatar
    src="..."
    alt="John Doe profile picture"
    status="online"
    aria-label="John Doe, currently online"
  />
);

Best Practices

✅ Do

  • Always provide meaningful alt text for images
  • Use appropriate sizes for the context
  • Show status indicators for real-time communication apps
  • Use initials as fallback when images fail to load
  • Provide tooltips for additional context
tsx
// Good: Proper alt text and fallback
const goodAvatar = (
  <Avatar
    src="https://..."
    alt="John Doe"
    initials="JD"
    name="John Doe"
  />
);

❌ Don't

  • Don't use very large images (optimize for size)
  • Don't forget alt text
  • Don't use avatars for decorative purposes without proper ARIA
  • Don't make avatars too small to recognize
tsx
// Bad: No alt text, no fallback
const badAvatar = (
  <Avatar src="https://..." />
);

// Better: With proper attributes
const betterAvatar = (
  <Avatar
    src="https://..."
    alt="User profile picture"
    initials="JD"
  />
);

Use Cases

User Lists

tsx
const users = [
  { name: 'Alice Cooper', avatar: '...', status: 'online' },
  { name: 'Bob Smith', avatar: '...', status: 'away' },
  { name: 'Charlie Brown', initials: 'CB', status: 'offline' }
];

const userList = (
  <div class="space-y-3">
    {users.map(user => (
      <div class="flex items-center gap-3">
        <Avatar
          src={user.avatar}
          initials={user.initials}
          name={user.name}
          status={user.status}
          size="sm"
        />
        <span>{user.name}</span>
      </div>
    ))}
  </div>
);

Comment Section

tsx
const Comment = ({ author, text, timestamp }) => (
  <div class="flex gap-3">
    <Avatar
      src={author.avatar}
      alt={author.name}
      size="md"
    />
    <div class="flex-1">
      <div class="flex items-center gap-2">
        <span class="font-semibold">{author.name}</span>
        <span class="text-xs text-gray-500">{timestamp}</span>
      </div>
      <p class="mt-1 text-gray-700">{text}</p>
    </div>
  </div>
);

Team Members

tsx
const teamMembers = (
  <div class="flex -space-x-2">
    <Avatar
      src="..."
      size="md"
      tooltip="Alice Cooper"
    />
    <Avatar
      src="..."
      size="md"
      tooltip="Bob Smith"
    />
    <Avatar
      src="..."
      size="md"
      tooltip="Charlie Brown"
    />
    <Avatar
      initials="+5"
      color="gray"
      size="md"
      tooltip="5 more members"
    />
  </div>
);

Styling & Theming

All avatar styles use Tailwind CSS classes and support dark mode automatically.

Custom Styling

tsx
const customAvatar = (
  <Avatar
    src="..."
    className="ring-4 ring-blue-500 ring-offset-2"
  />
);

TypeScript

Full TypeScript support with complete type definitions:

tsx
import type { AvatarProps } from '@odyssee/components';

const props: AvatarProps = {
  src: 'https://...',
  alt: 'User Avatar',
  size: 'md',
  status: 'online',
  onClick: (e: Event) => {
    console.log('Clicked!');
  }
};

const avatar = <Avatar {...props} />;

Version: 1.0.0
Last Updated: January 2025

Released under the MIT License.