Class: Primer::OpenProject::AvatarWithFallback

Inherits:
Beta::Avatar show all
Defined in:
app/components/primer/open_project/avatar_with_fallback.rb

Overview

OpenProject-specific Avatar component that extends Primer::Beta::Avatar to support fallback rendering with initials when no image source is provided.

Uses a “fallback first” pattern for flicker-free loading:

  1. Always renders fallback SVG as initial <img> src (visible immediately)

  2. Client-side JS test-loads the real URL in background

  3. On success, swaps to real image; on failure, fallback stays visible

This approach is inspired by OpenProject’s Angular PrincipalRendererService.

Constant Summary collapse

FONT_STACK =

See Also:

  • https://primer.style/foundations/typography/ - https://github.com/primer/css/blob/main/src/support/variables/typography.scss
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'"

Constants inherited from Beta::Avatar

Beta::Avatar::DEFAULT_SHAPE, Beta::Avatar::DEFAULT_SIZE, Beta::Avatar::SHAPE_OPTIONS, Beta::Avatar::SIZE_OPTIONS, Beta::Avatar::SMALL_THRESHOLD

Constants inherited from Component

Component::INVALID_ARIA_LABEL_TAGS

Constants included from Status::Dsl

Status::Dsl::STATUSES

Constants included from ViewHelper

ViewHelper::HELPERS

Constants included from TestSelectorHelper

TestSelectorHelper::TEST_SELECTOR_TAG

Constants included from FetchOrFallbackHelper

FetchOrFallbackHelper::InvalidValueError

Constants included from AttributesHelper

AttributesHelper::PLURAL_ARIA_ATTRIBUTES, AttributesHelper::PLURAL_DATA_ATTRIBUTES

Instance Method Summary collapse

Methods inherited from Component

deprecated?, generate_id

Methods included from JoinStyleArgumentsHelper

#join_style_arguments

Methods included from TestSelectorHelper

#add_test_selector

Methods included from FetchOrFallbackHelper

#fetch_or_fallback, #fetch_or_fallback_boolean, #silence_deprecations?

Methods included from ClassNameHelper

#class_names

Methods included from AttributesHelper

#aria, #data, #extract_data, #merge_aria, #merge_data, #merge_prefixed_attribute_hashes

Methods included from ExperimentalSlotHelpers

included

Methods included from ExperimentalRenderHelpers

included

Constructor Details

#initialize(src: nil, alt: nil, size: DEFAULT_SIZE, shape: DEFAULT_SHAPE, href: nil, unique_id: nil, **system_arguments) ⇒ AvatarWithFallback

Returns a new instance of AvatarWithFallback.

Parameters:

  • src (String) (defaults to: nil)

    The source URL of the avatar image. When provided, JavaScript will test-load it in the background and swap to it on success. When nil or blank, only the fallback SVG is displayed.

  • alt (String) (defaults to: nil)

    Alt text for the avatar. Used for accessibility and to generate initials for the fallback SVG.

  • size (Integer) (defaults to: DEFAULT_SIZE)

    <%= one_of(Primer::Beta::Avatar::SIZE_OPTIONS) %>

  • shape (Symbol) (defaults to: DEFAULT_SHAPE)

    Shape of the avatar. <%= one_of(Primer::Beta::Avatar::SHAPE_OPTIONS) %>

  • href (String) (defaults to: nil)

    The URL to link to. If used, component will be wrapped by an ‘<a>` tag.

  • unique_id (String, Integer) (defaults to: nil)

    Unique identifier for generating consistent avatar colors across renders.

  • system_arguments (Hash)

    <%= link_to_system_arguments_docs %>



29
30
31
32
33
34
35
36
37
38
# File 'app/components/primer/open_project/avatar_with_fallback.rb', line 29

def initialize(src: nil, alt: nil, size: DEFAULT_SIZE, shape: DEFAULT_SHAPE, href: nil, unique_id: nil, **system_arguments)
  require_src_or_alt_arguments(src, alt)

  @unique_id = unique_id
  @avatar_src = src.presence
  @fallback_svg = generate_fallback_svg(alt, size)

  # Always render fallback first - JS will swap to real image on successful load
  super(src: @fallback_svg, alt: alt, size: size, shape: shape, href: href, **system_arguments)
end

Instance Method Details

#callObject



40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/components/primer/open_project/avatar_with_fallback.rb', line 40

def call
  render(
    Primer::BaseComponent.new(
      tag: :"avatar-fallback",
      data: {
        unique_id: @unique_id,
        alt_text: @system_arguments[:alt],
        avatar_src: @avatar_src
      }
    )
  ) { super }
end