Avatar
Stableuser thumbnail
AS
MK
RJ
AS
MK
RJ
+5
Usage example #
Copy this ERB into a Rails view after installing the component. The snippet below is the same code used by the live preview above.
app/views/.../avatar_example.html.erb
<div class="flex items-center gap-4">
<%= render Senren::AvatarComponent.new(initials: "AS", size: :sm) %>
<%= render Senren::AvatarComponent.new(initials: "MK", size: :md) %>
<%= render Senren::AvatarComponent.new(initials: "RJ", size: :lg) %>
</div>
<div class="mt-6 flex items-center -space-x-2">
<%= render Senren::AvatarComponent.new(initials: "AS", size: :md) %>
<%= render Senren::AvatarComponent.new(initials: "MK", size: :md) %>
<%= render Senren::AvatarComponent.new(initials: "RJ", size: :md) %>
<%= render Senren::AvatarComponent.new(initials: "+5", size: :md) %>
</div>
Install this component #
Copy the official component into your app
Use this when you want the Senren-maintained implementation copied into app/components/senren.
Terminal
bin/rails senren:add avatar
Create a custom component with the same conventions
Use this when you need an app-specific static component that follows Senren's ViewComponent structure.
Terminal
bin/rails generate senren:component avatar --no-client
At a glance #
Category
Data
Class name
Senren::AvatarComponent
Stimulus
—
Variants
sm, md, lg
Depends on
—
Pairs with
card, team_member_list, dropdown_menu
Source #
app/components/senren/avatar_component.html.erb
<%= tag.span(**root_attrs("relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-[hsl(var(--senren-muted))] text-[hsl(var(--senren-foreground))] font-semibold shadow-sm ring-1 ring-[hsl(var(--senren-border))]", role: "img", "aria-label": alt.presence || fallback)) do %>
<% if src.present? %>
<%= image_tag src, alt: alt.to_s, class: "h-full w-full object-cover" %>
<% else %>
<svg aria-hidden="true" viewBox="0 0 64 64" preserveAspectRatio="none" class="absolute inset-0 h-full w-full">
<rect width="64" height="64" fill="#2b9bd7" />
<circle cx="42" cy="15" r="8" fill="#fffbea" />
<path d="M0 27 C10 20 16 22 24 17 C31 13 37 23 45 18 C54 12 58 22 64 20 L64 64 L0 64 Z" fill="#f6a4c8" />
<path d="M0 36 C10 29 19 35 29 29 C39 23 48 33 64 27 L64 64 L0 64 Z" fill="#86c84a" />
<path d="M5 46 C17 39 34 40 59 43 C50 53 23 57 5 46 Z" fill="#bdeef4" />
<path d="M0 50 C10 44 18 48 25 43 C28 51 42 48 46 55 C56 48 60 53 64 50 L64 64 L0 64 Z" fill="#7fc547" />
<path d="M2 54 C11 49 18 51 25 47 C28 55 16 60 5 61 Z" fill="#b59ce9" opacity=".9" />
<path d="M44 49 C52 45 59 47 64 44 L64 64 L45 64 C41 58 40 53 44 49 Z" fill="#16a060" opacity=".9" />
<g fill="#107e76" opacity=".45">
<circle cx="8" cy="12" r=".8" />
<circle cx="17" cy="25" r=".6" />
<circle cx="28" cy="9" r=".7" />
<circle cx="36" cy="32" r=".6" />
<circle cx="51" cy="25" r=".7" />
<circle cx="57" cy="38" r=".6" />
</g>
</svg>
<% if fallback.present? %>
<span class="relative z-10 rounded-full bg-[hsl(var(--senren-background)/0.72)] px-1.5 leading-none text-[hsl(var(--senren-foreground))] shadow-sm"><%= fallback %></span>
<% end %>
<% end %>
<% end %>
app/components/senren/avatar_component.rb
# frozen_string_literal: true
module Senren
class AvatarComponent < BaseComponent
VARIANTS = { default: '' }.freeze
SIZES = {
sm: 'h-8 w-8 text-xs',
md: 'h-10 w-10 text-sm',
lg: 'h-14 w-14 text-base'
}.freeze
def initialize(src: nil, alt: nil, fallback: nil, initials: nil, size: :md, class_name: nil, **html)
super(variant: :default, size: size, class_name: class_name, **html)
@src = src
@alt = alt
@fallback = fallback.presence || initials.presence || initials_from_alt
end
attr_reader :src, :alt, :fallback
private
def initials_from_alt
return '' if alt.blank?
alt.split.map(&:first).first(2).join.upcase
end
end
end
AI agent rules #
Use for
- +user thumbnail
- +team list
- +comments
Avoid
- -decorative-only without alt
Accessibility #
- alt text required; fallback to initials with role=img and aria-label.