資料展示

Avatar Stack

一排重疊的圓形頭像,hover/focus 時上浮放大、鄰居讓開並浮出名字 tooltip。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add avatar-stack

還沒有專案,或安裝遇到問題?看快速開始 →

Avatar Stack 是用 React、Motion(motion/react)與 Tailwind CSS 做的頭像堆疊(avatar group/疊放頭像)元件:頭像左壓右重疊排列,滑鼠移上或鍵盤聚焦時該頭像上浮放大、左右鄰居讓開,並浮出名字。超過 max 的人數會收成 +N 泡泡,沒有圖片時用名字產生固定的漸層底色與首字。

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

5
40
編輯中的呼叫預設屬性
<AvatarStack/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

適用情境

  • 協作工具顯示「目前正在檢視這份文件的人」
  • 專案卡片或任務列上列出負責成員
  • 活動或課程頁面呈現「已有 N 人報名」並露出部分頭像
  • 首頁 hero 區的社群證明,搭配「超過一萬名團隊使用」之類的文案
  • 不適合:要完整展示成員姓名、職稱與照片時,改用 Team Grid Section

安裝

npx webberui@latest add https://webberui.com/r/avatar-stack.json

或在 components.json 設定 registries 後,改用 @webberui/avatar-stack 安裝。

使用

import { AvatarStack } from "@/components/ui/avatar-stack";

<AvatarStack
  avatars={[
    { src: "/team/ada.jpg", alt: "Ada Lovelace" },
    { alt: "Alan Turing" },
    { alt: "Grace Hopper", fallback: "GH" },
  ]}
  max={5}
  size={40}
/>;

範例

中文姓名的文字頭像

沒有 src 時會取 alt 的第一個字元當頭像文字,中文名字就會顯示姓氏。底色由名字計算,同一個人每次顏色都一樣。

import { AvatarStack } from "@/components/ui/avatar-stack";

<AvatarStack
  avatars={[
    { alt: "王小明" },
    { alt: "林怡君" },
    { alt: "陳志豪" },
    { alt: "張雅婷" },
  ]}
  size={36}
/>;

文件卡片上的共同編輯者

縮小 size、把 max 設小一點,適合放在卡片角落;其餘人數會顯示為 +N。

<div className="flex items-center justify-between rounded-xl border p-4">
  <div>
    <p className="text-sm font-medium">2026 Q4 產品規劃</p>
    <p className="text-xs text-neutral-500">10 分鐘前更新</p>
  </div>
  <AvatarStack avatars={editors} max={3} size={28} />
</div>

從 API 轉換資料

把後端的使用者資料轉成 AvatarStackItem,型別可以直接 import。

import { AvatarStack, type AvatarStackItem } from "@/components/ui/avatar-stack";

type Member = { id: string; name: string; avatarUrl: string | null };

function MemberAvatars({ members }: { members: Member[] }) {
  const avatars: AvatarStackItem[] = members.map((m) => ({
    src: m.avatarUrl ?? undefined,
    alt: m.name,
  }));
  return <AvatarStack avatars={avatars} max={4} />;
}

Props

Prop型別預設值說明
avatarsAvatarStackItem[]—頭像清單,依序由左至右堆疊(左壓右)
maxnumber5最多顯示幾個頭像,其餘彙整成 +N 泡泡
sizenumber40頭像直徑(px)
classNamestring—外層容器自訂樣式

AvatarStackItem

欄位型別說明
srcstring?頭像圖片網址;省略時顯示文字 fallback
altstring替代文字,同時作為 tooltip 顯示的名字
fallbackstring?無圖片時顯示的字元;省略時自動取 alt 首字

細節

  • 頭像以負 margin 重疊,左側壓在右側之上(z-index 由左至右遞減)。
  • hover 或鍵盤 focus 任一頭像時,該頭像上浮放大並取得最高層級,左右鄰居往兩側讓開,同時於上方浮出名字 tooltip。
  • 無圖片時以名字產生穩定漸層底色並顯示首字,同一名字每次結果都相同。
  • 超過 max 的頭像數量會彙整成 +N 泡泡,接在可見頭像之後。

可及性

  • 每個頭像為 button 並帶 aria-label(名字),可用鍵盤 Tab 聚焦,focus 時與 hover 一樣顯示 tooltip。
  • tooltip 為純視覺(aria-hidden),名字已透過 aria-label 提供給輔助科技,避免重複朗讀。
  • +N 泡泡帶 role="img" 與 aria-label(如「還有 2 位成員」)。
  • 使用者系統開啟「減少動態效果」時,停用上浮、放大與位移,tooltip 仍會顯示。

常見問題

可以在 Next.js App Router 使用嗎?

可以。檔案開頭已有 "use client",在 Server Component 頁面裡照常 import,資料可以在伺服器端取得後當 props 傳入。

fallback 傳兩個字母,為什麼只顯示一個?

文字頭像只顯示一個字元:取 fallback(沒有就取 alt)的第一個字並轉成大寫。需要顯示兩個字母的縮寫時,請提供頭像圖片。

頭像圖片用的是 next/image 嗎?

不是,元件使用一般的 <img>,以 object-cover 填滿圓形。圖片由你的網址決定,若要最佳化尺寸,可以先把網址指向已縮圖的版本。

鍵盤和螢幕閱讀器怎麼操作?

每個頭像都是帶 aria-label 的 button,可以用 Tab 聚焦,聚焦時和 hover 一樣顯示名字;+N 泡泡會朗讀「還有 N 位成員」。系統開啟「減少動態效果」時,上浮與位移會停用。

需要哪些依賴?

motion、clsx 與 tailwind-merge。也可以從安裝區塊的「手動」分頁複製原始碼。