Avatar Stack
一排重疊的圓形頭像,hover/focus 時上浮放大、鄰居讓開並浮出名字 tooltip。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add avatar-stackAvatar Stack 是用 React、Motion(motion/react)與 Tailwind CSS 做的頭像堆疊(avatar group/疊放頭像)元件:頭像左壓右重疊排列,滑鼠移上或鍵盤聚焦時該頭像上浮放大、左右鄰居讓開,並浮出名字。超過 max 的人數會收成 +N 泡泡,沒有圖片時用名字產生固定的漸層底色與首字。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
avatars | AvatarStackItem[] | — | 頭像清單,依序由左至右堆疊(左壓右) |
max | number | 5 | 最多顯示幾個頭像,其餘彙整成 +N 泡泡 |
size | number | 40 | 頭像直徑(px) |
className | string | — | 外層容器自訂樣式 |
AvatarStackItem
| 欄位 | 型別 | 說明 |
|---|---|---|
src | string? | 頭像圖片網址;省略時顯示文字 fallback |
alt | string | 替代文字,同時作為 tooltip 顯示的名字 |
fallback | string? | 無圖片時顯示的字元;省略時自動取 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。也可以從安裝區塊的「手動」分頁複製原始碼。