頁面區塊 Sections
名片捲帶
名片式的評價卡排成橫向捲帶,可拖曳或捲動吸附,越靠近中央的卡片越大越清楚,兩側逐漸縮小變淡並微微傾斜朝向中央。
把客戶評價做成一張張橫式名片,排在一條全幅的橫向捲帶上。每張卡左上是姓名縮寫漸層頭像、姓名與職稱 · 公司,右上是公司字標,中段是最多三行的引言,底部以細分隔線隔出產業、方案等標籤。捲帶用原生捲動加 scroll-snap 吸附:觸控與觸控板直接滑,滑鼠可按住拖曳並帶慣性,標題列右側的箭頭一次切換一張。卡片依自己與捲帶中心的距離即時縮放、變淡並以 rotateY 微傾,中央那張最大最清楚。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add business-card-reelPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
320
8
500
編輯中的呼叫預設屬性
<BusinessCardReel/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/business-card-reel.json或在 components.json 設定 registries 後,改用 @webberui/business-card-reel 安裝。
使用
import { BusinessCardReel } from "@/components/ui/business-card-reel";
<BusinessCardReel
eyebrow="客戶評價"
title="團隊導入後的第一個月"
testimonials={[
{
quote: "以前每週要花半天整理門市排班,現在店長十分鐘就能排完。",
name: "林予安",
role: "營運經理",
company: "青嶼咖啡",
companyMark: "Qingyu",
highlight: "十分鐘就能排完",
tags: ["餐飲", "團隊方案"],
},
// ...
]}
cardWidth={320}
tilt={8}
onChange={(index) => console.log(`置中第 ${index + 1} 張`)}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
testimonials | BusinessCardReelItem[] | — | 評價資料陣列 |
eyebrow | string | — | 標題上方的小標籤 |
title | string | "客戶怎麼說" | 區塊主標題,同時是 section 的 aria-labelledby 來源 |
subtitle | string | — | 主標題下方的說明文字 |
value | number | — | 受控模式:目前置中的卡片索引;變更時捲帶會捲到該卡 |
defaultValue | number | 0 | 非受控模式:初始置中的卡片索引(掛載後直接定位,不播動畫) |
onChange | (index: number) => void | — | 捲動吸附完成、置中卡片改變時回呼 |
cardWidth | number | 320 | 卡片寬度(px);高度依 1.75:1 推算,內容多時自動長高 |
tilt | number | 8 | 兩側卡片的最大 rotateY 傾斜角度(deg),0 為不傾斜 |
showTags | boolean | true | 是否顯示卡片底部的標籤 chips |
duration | number | — | 進場動畫時長(ms);未提供時讀 --wb-business-card-reel-duration(預設 500ms) |
reelLabel | string | "客戶評價捲帶,可用左右方向鍵切換" | 捲帶區域的 aria-label |
prevLabel | string | "上一則評價" | 上一則按鈕的 aria-label |
nextLabel | string | "下一則評價" | 下一則按鈕的 aria-label |
className | string | — | 併入最外層 section |
BusinessCardReelItem
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
quote | string | — | 引言內文,卡片上最多顯示三行 |
name | string | — | 評價者姓名;頭像縮寫中文取末兩字、拉丁取首尾單字首字母 |
role | string | — | 職稱 |
company | string | — | 公司名稱 |
companyMark | string | — | 右上角的公司字標文字;未提供時改用 company |
tags | string[] | — | 卡片底部的標籤 chips(例如產業、使用方案) |
highlight | string | — | quote 中要以強調色標記的片段(需完全相同,只標第一次出現) |
avatarHue | number | — | 頭像漸層色相(0–360);未提供時依索引以黃金角度 137.508° 推算 |
avatarSrc | string | — | 頭像圖片網址;提供時取代縮寫漸層方塊 |
rating | number | — | 本元件不顯示,保留與其他 testimonial 元件共用資料 |
metric | { value: string; label: string } | — | 本元件不顯示,保留與其他 testimonial 元件共用資料 |
細節
- 距離映射:每張卡以自己中心與捲帶中心的距離比例 d(0–1)計算
scale1 → 0.88、opacity1 → 0.5、rotateY0 → ±tilt,由useScroll({ container })的捲動位置驅動,不重新 render。 - 左右留白為「半個捲帶寬 − 半張卡」,第一張與最後一張也能吸附到正中央。
- 滑鼠拖曳時暫時關閉
scroll-snap,放手後依速度做慣性減速,停下時再交還給吸附並捲到最近一張;拖曳結束不會誤觸卡片內的點擊。觸控與觸控板維持原生捲動。 onChange只在捲動停止、吸附完成後才觸發,smooth 捲動途中經過的卡片不會回報,受控模式不會被中間索引打斷。- 強調色只走
--wb-business-card-reel-accent(預設亮色#0d9488、暗色#2dd4bf),用於小標籤、引言標記與焦點框;進場時長走--wb-business-card-reel-duration。
可及性
- 根元素為
section,以aria-labelledby指向主標題;每則評價是figure,引言在blockquote,姓名與職稱在figcaption - 捲帶為
role="region"、帶aria-label且tabIndex=0,聚焦後可用 ← / → 切換一張、Home / End 跳到頭尾 - 箭頭按鈕為
type="button",帶aria-label與指向捲帶的aria-controls,到頭尾時停用 - 吸附完成後以
aria-live="polite"朗讀「第幾則,共幾則」與姓名 - 使用者系統開啟「減少動態效果」時,不做距離縮放、變淡與傾斜,箭頭改為瞬間定位、拖曳不帶慣性,進場改為 150ms 淡入;
scroll-snap吸附保留