Avatar

A versatile avatar component for displaying user profile images, initials, or placeholder icons with status indicators and social media platform sizes.

Key Features

  • Image Display with automatic fallback to initials or icon
  • Social Media Sizes - Instagram, X, LinkedIn, Discord, GitHub, etc.
  • Status Indicators - Online, offline, busy, away, streaming
  • Multiple Shapes - Circle, rounded, square
  • Ring Styles - Instagram story ring, semantic colors
  • Clickable - Link to user profiles
  • Avatar Groups - Overlapping stacks for team displays
  • Accessibility - Proper ARIA roles and alt text support
  • JavaScript API - Programmatic control with data-action attributes

Basic Usage

The avatar component supports images, initials derived from names, or a default user icon fallback.


<%= rui_avatar(src: user.avatar_url, alt: user.name) %>

<%= rui_avatar(name: "John Doe") %>

<%= rui_avatar(initials: "JD", size: :lg) %>
User photo JD JD

Left to right: Image, Name initials, Custom initials, Fallback icon

Content Types

Avatar automatically falls back through: Image → Initials → Icon

Photo

Image

rui_avatar(src: url)
SM

Initials

rui_avatar(name: "Sarah Miller")

Fallback Icon

rui_avatar

Sizes

Standard UI sizes from extra small (24px) to extra large (192px).

XS

xs

SM

sm

MD

md

LG

lg

XL

xl

X2

xl2

X3

xl3

<%= rui_avatar(name: "JD", size: :xs) %>   
<%= rui_avatar(name: "JD", size: :sm) %>   
<%= rui_avatar(name: "JD", size: :md) %>   
<%= rui_avatar(name: "JD", size: :lg) %>   
<%= rui_avatar(name: "JD", size: :xl) %>   
<%= rui_avatar(name: "JD", size: :xl2) %>  
<%= rui_avatar(name: "JD", size: :xl3) %>  

Social Media Platform Sizes

Use semantic size names that match exactly what you're building. "Make the right thing the obvious thing."

Why Platform Sizes?

Instead of guessing pixel sizes, use platform-specific names like :ig_profile or :x_tweet. Your code becomes self-documenting!

Instagram

IG

ig_comment

IG

ig_post

IG

ig_story

IG

ig_profile

<%= rui_avatar(src: url, size: :ig_story, ring: :ig_story) %>  
<%= rui_avatar(src: url, size: :ig_profile) %>                 
<%= rui_avatar(src: url, size: :ig_post) %>                    
<%= rui_avatar(src: url, size: :ig_comment) %>                 

X (Twitter)

X

x_reply

X

x_tweet

X

x_profile

Discord

DC

discord_avatar

DC

discord_server

DC

discord_profile

GitHub

GH

github_contrib

GH

github_avatar

GH

github_profile


:linkedin_profile, :linkedin_post, :linkedin_comment
:fb_profile, :fb_post, :fb_story
:slack_avatar, :slack_profile
:twitch_avatar, :twitch_channel
:whatsapp_chat, :whatsapp_profile
:tiktok_profile, :tiktok_comment

Shapes

Three shape options for different visual styles.

JD

Circle (Default)

shape: :circle
JD

Rounded

shape: :rounded
JD

Square

shape: :square

Ring Styles

Add emphasis with ring/border styles. Great for story indicators or status emphasis.

JD

none

JD

white

JD

gray

JD

primary

JD

success

JD

warning

JD

danger

JD

ig_story

JD

ig_live

<%= rui_avatar(src: url, ring: :primary) %>  
<%= rui_avatar(src: url, ring: :success) %>  
<%= rui_avatar(src: url, ring: :ig_story) %> 
<%= rui_avatar(src: url, ring: :ig_live) %>  

Status Indicators

Show user availability with status dots that automatically scale with avatar size.

JD

online

JD

offline

JD

busy

JD

away

JD

dnd

JD

streaming

JD

idle

<%= rui_avatar(src: url, status: :online) %>    
<%= rui_avatar(src: url, status: :offline) %>   
<%= rui_avatar(src: url, status: :busy) %>      
<%= rui_avatar(src: url, status: :away) %>      
<%= rui_avatar(src: url, status: :dnd) %>       
<%= rui_avatar(src: url, status: :streaming) %> 

Tip: Status dots have hover titles. Try hovering over them to see the status name!

Clickable Avatars

Make avatars link to user profiles with hover effects.

JD SM Hover to see effect, click to follow link

<%= rui_avatar(src: user.avatar_url, url: user_path(user)) %>

<%= rui_avatar(name: "John Doe", url: "/users/1") %>

Avatar Groups

Create overlapping avatar stacks for team displays and contributor lists.

Stacked Avatars with White Borders

AB CD EF GH

With Count Badge

GH EF CD
+99

With Real Avatar Images

Avatar 1 Avatar 2 Avatar 3 Avatar 4

Reverse Stacked with Real Images

Avatar 4 Avatar 3 Avatar 2 Avatar 1
<!-- Stacked avatars with initials -->
<div class="flex -space-x-4 rtl:space-x-reverse">
  <%= rui_avatar(name: "John Doe", size: :md, ring: :white) %>
  <%= rui_avatar(name: "Jane Smith", size: :md, ring: :white) %>
  <%= rui_avatar(name: "Mike Brown", size: :md, ring: :white) %>
  <%= rui_avatar(name: "Sarah Lee", size: :md, ring: :white) %>
</div>

<!-- With real avatar images -->
<div class="flex -space-x-4 rtl:space-x-reverse">
  <%= rui_avatar(src: user1.avatar_url, alt: user1.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user2.avatar_url, alt: user2.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user3.avatar_url, alt: user3.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user4.avatar_url, alt: user4.name, size: :md, ring: :white) %>
</div>

<!-- Reverse stacked with real images -->
<div class="flex -space-x-4 rtl:space-x-reverse">
  <%= rui_avatar(src: user4.avatar_url, alt: user4.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user3.avatar_url, alt: user3.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user2.avatar_url, alt: user2.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user1.avatar_url, alt: user1.name, size: :md, ring: :white) %>
</div>

<!-- With count badge (z-10 makes badge appear on top) -->
<div class="flex -space-x-4 rtl:space-x-reverse">
  <%= rui_avatar(src: user1.avatar_url, alt: user1.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user2.avatar_url, alt: user2.name, size: :md, ring: :white) %>
  <%= rui_avatar(src: user3.avatar_url, alt: user3.name, size: :md, ring: :white) %>
  <div class="relative z-10 flex items-center justify-center w-10 h-10 text-xs font-medium text-white bg-gray-800 dark:bg-gray-900 border-2 border-white dark:border-gray-900 rounded-full flex-shrink-0">
    +99
  </div>
</div>

Proper Group Container Classes

  • flex - Creates flexbox container
  • -space-x-4 - Creates negative spacing (16px overlap) for stacking
  • rtl:space-x-reverse - RTL support for right-to-left languages
  • ring: :white - Add white borders for visual separation
  • z-10 - (For badges) Ensures count badge appears on top of avatars

Real-World Examples

User Profile Header

Jane Smith

Jane Smith

@janesmith
Verified
<div class="flex items-center gap-4">
  <%= rui_avatar(
    src: @user.avatar_url,
    alt: @user.name,
    size: :xl4,
    ring: @user.verified? ? :success : :none,
    status: @user.online_status
  ) %>
  <div>
    <%= rui_text(@user.name, size: :xl, weight: :bold) %>
    <%= rui_link("@#{@user.username}", href: user_path(@user), variant: :muted, size: :sm, underline: :none) %>
    <%= rui_badge(text: "Verified", color: :success, size: :xs) if @user.verified? %>
  </div>
</div>

Comment Thread

AR
Alex Rivera

This looks amazing! Great work on the design.

Reply Like

2 hours ago

SL
Sam Lee

Thanks Alex!

<div class="flex gap-3">
  <%= rui_avatar(name: comment.user.name, size: :sm, url: user_path(comment.user)) %>
  <div class="bg-white dark:bg-zinc-800 rounded-lg p-3 flex-1">
    <%= rui_link(comment.user.name, href: user_path(comment.user), size: :sm, weight: :semibold, underline: :none) %>
    <%= rui_text(comment.body, size: :sm, color: :muted) %>
    <div class="mt-2 flex items-center gap-3">
      <%= rui_link("Reply", href: "#", size: :xs, variant: :muted, underline: :hover) %>
      <%= rui_link("Like", href: "#", size: :xs, variant: :muted, underline: :hover) %>
      <%= rui_text(time_ago_in_words(comment.created_at) + " ago", size: :xs, color: :muted) %>
    </div>
  </div>
</div>

Chat Interface

TA

Hey! Are you joining the meeting?

2:34 PM

ME

Yes, joining in 5 minutes!

2:35 PM

<div class="flex items-start gap-2">
  <%= rui_avatar(name: message.sender.name, size: :discord_avatar, status: message.sender.status) %>
  <div class="bg-indigo-100 dark:bg-indigo-900 rounded-lg p-3 max-w-md">
    <%= rui_text(message.body, size: :sm) %>
    <%= rui_text(message.sent_at.strftime("%l:%M %p"), size: :xs, color: :muted, class: "mt-1") %>
  </div>
</div>

Instagram Stories Style

A

Your Story

C LIVE
D

viewed

<div class="flex gap-4">
  <% @stories.each do |story| %>
    <div class="text-center">
      <%= rui_avatar(
        name: story.user.name,
        size: :ig_story,
        ring: story.live? ? :ig_live : (story.viewed? ? :gray : :ig_story),
        url: story_path(story)
      ) %>
      <% if story.live? %>
        <%= rui_badge(text: "LIVE", color: :danger, size: :xs, class: "mt-1") %>
      <% else %>
        <%= rui_link(story.user.username, href: user_path(story.user), size: :xs, underline: :none, class: "mt-1") %>
      <% end %>
    </div>
  <% end %>
</div>

Team Members Card

Project Team

View all
SC
Sarah Chen

Lead Designer

Admin
MJ
Mike Johnson

Developer

Member
EW
Emma Wilson

Product Manager

Member
<div class="flex items-center justify-between">
  <div class="flex items-center gap-3">
    <%= rui_avatar(name: member.name, size: :sm, status: member.status) %>
    <div>
      <%= rui_link(member.name, href: user_path(member), size: :sm, weight: :medium, underline: :none) %>
      <%= rui_text(member.role, size: :xs, color: :muted) %>
    </div>
  </div>
  <%= rui_badge(text: member.access_level, color: member.admin? ? :primary : :secondary, size: :xs) %>
</div>

Accessibility

The Avatar component follows WAI-ARIA best practices for images and interactive elements.

ARIA Attributes

  • Uses role="img" for avatar containers
  • Automatic aria-label generated from name or alt text
  • Status indicators use aria-hidden="true" with status in aria-label

Keyboard Navigation

  • Clickable avatars are focusable via Tab
  • Enter activates linked avatars
  • Visible focus ring indicates active element

Semantic HTML

  • Uses <img> with proper alt attribute when image is provided
  • Initials fallback uses <span> with aria-hidden (name in aria-label)
  • Clickable avatars wrapped in semantic <a> element

Screen Reader Support

  • Announces user name from name or alt attribute
  • Status is included in announcement (e.g., "John Doe, online")
  • Avatar groups announce count and context

API Reference

rui_avatar

Display user profile images, initials, or placeholder icons with status indicators

Parameter Type Default Description

Content

Image and fallback content options

Parameter Type Default Description
src String Image source URL (XSS-protected)
alt String name or 'Avatar' Alt text for accessibility
name String Full name (auto-generates up to 2-letter initials)
initials String Custom initials (overrides name-derived)

Appearance

Visual styling options

Parameter Type Default Description
size Symbol :md Standard sizes or platform presets
:xs :sm :md :lg :xl :xl2 :xl3 :xl4 :xl5 :xl6
shape Symbol :circle Avatar shape
:circle :rounded :square
ring Symbol :none Ring/border style around avatar
:none :white :gray :black :primary :success :warning :danger :ig_story :ig_live

Status

Online/presence indicator options

Parameter Type Default Description
status Symbol Status indicator dot
:online :offline :busy :away :dnd :streaming :idle :invisible

Behavior

Interaction and grouping options

Parameter Type Default Description
url String Makes avatar clickable with this URL
group_position Integer Position in avatar group (1, 2, 3, etc.) - controls overlap and z-index stacking

Platform Size Presets

Social media platform-specific sizes that match each platform's design system

Parameter Type Default Description
:ig_* Symbol Instagram sizes: :ig_story, :ig_profile, :ig_post, :ig_comment
:x_* Symbol X (Twitter) sizes: :x_profile, :x_tweet, :x_reply
:linkedin_* Symbol LinkedIn sizes: :linkedin_profile, :linkedin_post, :linkedin_comment, :linkedin_message
:fb_* Symbol Facebook sizes: :fb_profile, :fb_post, :fb_comment, :fb_story
:discord_* Symbol Discord sizes: :discord_avatar, :discord_profile, :discord_server
:slack_* Symbol Slack sizes: :slack_avatar, :slack_profile, :slack_sidebar
:github_* Symbol GitHub sizes: :github_avatar, :github_profile, :github_contrib
:yt_* Symbol YouTube sizes: :yt_channel, :yt_comment, :yt_thumbnail
:tiktok_* Symbol TikTok sizes: :tiktok_profile, :tiktok_comment, :tiktok_for_you
:twitch_* Symbol Twitch sizes: :twitch_avatar, :twitch_channel, :twitch_thumbnail
:whatsapp_* Symbol WhatsApp sizes: :whatsapp_chat, :whatsapp_profile, :whatsapp_group

Related Components