page AvatarGroupcomponent { seo { title = "AvatarGroup component" description = "Theme-aware, responsive avatar group component." } view {
W WRNexusJS
base component

AvatarGroup

Theme-aware, responsive avatar group component.

@wrnexus/ui 0.5.012 props0 slots1 events

Usage

Components are auto-discovered. Use the component directly in any .wrn view:

<AvatarGroup
  items="[]"
  size="md"
  color="primary"
  variant="solid"
  shape="circle"
/>

Legacy mount name: data-component="AvatarGroup".

Props and attributes

PropTypeRequirementDefault
itemsstringOptional[]
sizestringOptional"md"
colorstringOptional"primary"
variantstringOptional"solid"
shapestringOptional"circle"
layoutstringOptional"stack"
maxVisiblenumberOptional4
columnsnumberOptional3
borderColorstringOptional""
showTooltipsbooleanOptionaltrue
overflowLabelstringOptional"Show remaining members"
classstringOptional""

Slots

This component does not declare a slot.

Events

  • overflow

Source contract

Installed source: components/AvatarGroup.wrn

component AvatarGroup {
  props {
    items = []
    size = "md"
    color = "primary"
    variant = "solid"
    shape = "circle"
    layout = "stack"
    maxVisible = 4
    columns = 3
    borderColor = ""
    showTooltips = true
    overflowLabel = "Show remaining members"
    class = ""

    @event overflow = function
  }

  state overflowOpen = false

  functions {
    function visibleMembers() {
      return items.slice(0, Number(maxVisible))
    }

    function hiddenMembers() {
      return items.slice(Number(maxVisible))
    }

    function toggleOverflow(sourceEvent, root, customEvent) {
      overflowOpen = !overflowOpen
      root = sourceEvent.currentTarget.closest("[data-wrn-avatar-group]")

      customEvent = document.createEvent("CustomEvent")
      customEvent.initCustomEvent("overflow", true, false, {
        component: "AvatarGroup",
        open: overflowOpen,
        hiddenCount: hiddenMembers().length
      })
      root.dispatchEvent(customEvent)
    }
  }

  view {
        <div
      {...attrs}
      class="wire-next wire-next--avatar-group {class}"
      data-wrn-avatar-group
      data-layout="{layout}"
      data-shape="{shape}"
      data-size="{size}"
      style="--wire-avatar-group-columns:{columns}; --wire-avatar-group-ring:{borderColor || 'var(--wire-color-bg)'}"
      role="group"
      aria-label="Avatar group"
    >
        <div class="wire-next__avatar-group-members">
        {#each visibleMembers() as item}
          <span
            class="wire-next__avatar-group-member"
            data-size="{item.size || size}"
            data-shape="{item.shape || shape}"
            data-color="{item.color || color}"
            data-variant="{item.variant || variant}"
            tabindex="{showTooltips && (item.tooltip || item.name) ? '0' : '-1'}"
            aria-label="{item.name || item.alt || item.initials || 'Group member'}"
          >
        <span class="wire-next__avatar-group-avatar">
              {#if item.src}
                <img src="{item.src}" alt="{item.alt || item.name || ''}" loading="lazy" />
              {:else if item.initials}
                <span aria-hidden="true">{item.initials}</span>
              {:else}
                <span class="icon-[lucide--user-round]" aria-hidden="true">
        </span>
              {/if}
            </span>

            {#if showTooltips && (item.tooltip || item.name)}
              <span class="wire-next__avatar-group-tooltip" role="tooltip">
                {item.tooltip || item.name}
              </span>
            {/if}
          </span>
        {/each}

        {#if hiddenMembers().length > 0}
          <span class="wire-next__avatar-group-overflow">
        <button
              type="button"
              class="wire-next__avatar-group-overflow-button"
              aria-label="{overflowLabel}"
              aria-expanded="{overflowOpen ? 'true' : 'false'}"
              @click="toggleOverflow(event)"
            >
              +{hiddenMembers().length}
            </button>
        <span
              class="wire-next__avatar-group-menu"
              role="menu"
              data-show="overflowOpen"
              aria-hidden="{overflowOpen ? 'false' : 'true'}"
            >
              {#each hiddenMembers() as item}
                <span class="wire-next__avatar-group-menu-item" role="menuitem">
        <span class="wire-next__avatar-group-menu-avatar">
                    {#if item.src}
                      <img src="{item.src}" alt="" loading="lazy" />
                    {:else}
                      <span>{item.initials || '?'}</span>
                    {/if}
                  </span>
        <span>{item.name || item.alt || item.initials || 'Team member'}</span>
        </span>
              {/each}
            </span>
        </span>
        {/if}
      </div>
        </div>
    }
}
} }