頁面區塊 Sections

名片捲帶

名片式的評價卡排成橫向捲帶,可拖曳或捲動吸附,越靠近中央的卡片越大越清楚,兩側逐漸縮小變淡並微微傾斜朝向中央。

把客戶評價做成一張張橫式名片,排在一條全幅的橫向捲帶上。每張卡左上是姓名縮寫漸層頭像、姓名與職稱 · 公司,右上是公司字標,中段是最多三行的引言,底部以細分隔線隔出產業、方案等標籤。捲帶用原生捲動加 scroll-snap 吸附:觸控與觸控板直接滑,滑鼠可按住拖曳並帶慣性,標題列右側的箭頭一次切換一張。卡片依自己與捲帶中心的距離即時縮放、變淡並以 rotateY 微傾,中央那張最大最清楚。

把這個效果裝進你的專案

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

npx webberui@latest add business-card-reel

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

Playground

即時調整 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型別預設值說明
testimonialsBusinessCardReelItem[]—評價資料陣列
eyebrowstring—標題上方的小標籤
titlestring"客戶怎麼說"區塊主標題,同時是 section 的 aria-labelledby 來源
subtitlestring—主標題下方的說明文字
valuenumber—受控模式:目前置中的卡片索引;變更時捲帶會捲到該卡
defaultValuenumber0非受控模式:初始置中的卡片索引(掛載後直接定位,不播動畫)
onChange(index: number) => void—捲動吸附完成、置中卡片改變時回呼
cardWidthnumber320卡片寬度(px);高度依 1.75:1 推算,內容多時自動長高
tiltnumber8兩側卡片的最大 rotateY 傾斜角度(deg),0 為不傾斜
showTagsbooleantrue是否顯示卡片底部的標籤 chips
durationnumber—進場動畫時長(ms);未提供時讀 --wb-business-card-reel-duration(預設 500ms)
reelLabelstring"客戶評價捲帶,可用左右方向鍵切換"捲帶區域的 aria-label
prevLabelstring"上一則評價"上一則按鈕的 aria-label
nextLabelstring"下一則評價"下一則按鈕的 aria-label
classNamestring—併入最外層 section

BusinessCardReelItem

欄位型別預設值說明
quotestring—引言內文,卡片上最多顯示三行
namestring—評價者姓名;頭像縮寫中文取末兩字、拉丁取首尾單字首字母
rolestring—職稱
companystring—公司名稱
companyMarkstring—右上角的公司字標文字;未提供時改用 company
tagsstring[]—卡片底部的標籤 chips(例如產業、使用方案)
highlightstring—quote 中要以強調色標記的片段(需完全相同,只標第一次出現)
avatarHuenumber—頭像漸層色相(0–360);未提供時依索引以黃金角度 137.508° 推算
avatarSrcstring—頭像圖片網址;提供時取代縮寫漸層方塊
ratingnumber—本元件不顯示,保留與其他 testimonial 元件共用資料
metric{ value: string; label: string }—本元件不顯示,保留與其他 testimonial 元件共用資料

細節

  • 距離映射:每張卡以自己中心與捲帶中心的距離比例 d(0–1)計算 scale 1 → 0.88、opacity 1 → 0.5、rotateY 0 → ±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 吸附保留