Cover Carousel
封面卡片式水平輪播,捲動比例連續驅動指示器(scrub),並具備完整鍵盤導航與 ARIA。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
16
<CoverCarousel />
安裝
npx shadcn@latest add https://webberui.com/r/cover-carousel.json或在 components.json 設定 registries 後,改用 @webberui/cover-carousel 安裝。
安裝依賴後,從 registry JSON(/r/cover-carousel.json 的 files[0].content)複製 cover-carousel.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
以 CoverCarousel 包裹,內容放入若干 CoverCarouselItem,每張投影片的寬度由你在 className 上決定:
import {
CoverCarousel,
CoverCarouselItem,
} from "@/components/ui/cover-carousel";
<CoverCarousel ariaLabel="精選機型">
{items.map((item) => (
<CoverCarouselItem key={item.id} className="w-[240px]">
<Card {...item} />
</CoverCarouselItem>
))}
</CoverCarousel>;受控模式:傳入 index 與 onIndexChange 即可由外部驅動當前投影片。
const [index, setIndex] = React.useState(0);
<CoverCarousel index={index} onIndexChange={setIndex}>
{/* ... */}
</CoverCarousel>;Props
CoverCarousel
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 放入 CoverCarouselItem,每個為一張投影片 |
index | number | — | 受控模式的當前索引,變動時捲動至該張 |
defaultIndex | number | 0 | 非受控模式的初始索引 |
onIndexChange | (index: number) => void | — | 置中投影片改變時觸發 |
controls | boolean | true | 是否顯示左右箭頭按鈕 |
indicators | "dots" | "bar" | "none" | "dots" | 底部指示器樣式 |
loop | boolean | false | 到頭/到尾時是否環繞 |
snapAlign | "start" | "center" | "start" | 投影片的 scroll-snap 對齊點 |
gap | number | 16 | 投影片間距(px) |
ariaLabel | string | "輪播" | 輪播區域的無障礙標籤 |
className | string | — | 外層區域 |
viewportClassName | string | — | 水平捲動視窗 |
CoverCarouselItem
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 投影片內容 |
aria-label | string | 自動 | 覆寫此張的無障礙標籤,預設為「第 N 張,共 M 張」 |
className | string | — | 設定投影片寬度與外觀 |
細節
- 捲動 scrub:指示器(圓點藥丸或進度條)由捲動容器的水平捲動比例
scrollXProgress連續驅動,並以useSpring平滑,因此在兩張之間拖曳時藥丸會連續滑動,而非離散跳格。 - 對齊偵測:以
requestAnimationFrame節流捲動事件,量測最靠近視窗中線的投影片作為當前索引,同時更新到頭/到尾狀態以停用箭頭。 - 雙模式:不傳
index時為非受控(內部追蹤捲動位置);傳入index則為受控,外部變動會捲動至該張。
可及性
- 整體為
role="region"且aria-roledescription="輪播",每張投影片為role="group"並標記「第 N 張,共 M 張」。 - 捲動視窗可聚焦,聚焦後
←→(或↑↓)切換投影片,Home/End跳至首尾。 - 箭頭與圓點皆為原生按鈕,可鍵盤聚焦與觸發;圓點以
role="tab"搭配aria-selected標記當前張。 - 目前張次透過
aria-live="polite"的隱藏區域朗讀。 - 使用者開啟「減少動態效果」時,程式化捲動改為瞬間定位、指示器不套用彈簧平滑。