WebberUI

Card Deck

可拖曳抽牌的堆疊卡組,四向甩牌、自動補位,支援無限循環或抽完見底兩種模式。

載入預覽⋯

Playground

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

3
96
500
<CardDeck />

安裝

npx shadcn@latest add https://webberui.com/r/card-deck.json

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

安裝依賴後,從 registry JSON(/r/card-deck.jsonfiles[0].content)複製 card-deck.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

使用

每個直接子節點就是一張卡片,第一項為初始最上層。容器需要有明確尺寸(卡片以絕對定位相互堆疊)。

import { CardDeck } from "@/components/ui/card-deck";

<div className="h-72 w-64">
  <CardDeck className="h-full w-full">
    <div className="flex h-full items-center justify-center">卡片一</div>
    <div className="flex h-full items-center justify-center">卡片二</div>
    <div className="flex h-full items-center justify-center">卡片三</div>
  </CardDeck>
</div>

程式化抽牌

透過 ref 取得 draw() / reset(),方向鍵盤與拖曳之外也能用按鈕觸發。

import { CardDeck, type CardDeckHandle } from "@/components/ui/card-deck";

const deckRef = React.useRef<CardDeckHandle>(null);

<CardDeck ref={deckRef}>{/* ... */}</CardDeck>
<button onClick={() => deckRef.current?.draw("left")}>抽牌</button>

抽完見底

設定 loop={false} 時,卡片會被逐張抽掉,抽完後顯示 emptyState

<CardDeck loop={false} emptyState={<p>沒有更多了</p>}>
  {/* ... */}
</CardDeck>

Props

Prop型別預設值說明
childrenReact.ReactNode每個直接子節點是一張卡片,第一項為初始最上層
indexnumber受控的最上層卡片索引
defaultIndexnumber0非受控模式的初始最上層索引
onIndexChange(index: number) => void最上層卡片變更時觸發
onDraw(index: number, direction: DrawDirection) => void抽掉一張卡時觸發,帶入被抽卡片索引與方向
loopbooleantruetrue 抽後循環回牌底;false 抽完顯示空狀態
visibleCountnumber3同時堆疊渲染的層數(含最上層)
drawThresholdnumber96觸發抽牌的拖曳位移閾值(px)
velocityThresholdnumber500觸發抽牌的拖曳甩動速度閾值(px/s)
emptyStateReact.ReactNodeloop={false} 抽完後顯示的內容
cardClassNamestring套用到每張卡片外觀表面的樣式
classNamestring套用到牌組容器

DrawDirection"up" | "down" | "left" | "right"

ref 會取得 CardDeckHandledraw(direction?) 抽掉最上層卡片(預設向上),reset() 回到第一張。

細節

  • 最上層卡片可自由拖曳(四個方向),位移或甩動速度超過閾值即朝該方向飛出,未達門檻則彈回原位。
  • 拖曳時卡片會依水平位移量輕微傾斜;後排卡片以索引雜湊出穩定的堆疊傾角,看起來像自然疊放的一落牌。
  • 抽牌後下一張自動 spring 補位到最前,牌組後方遞補新卡;loop 開啟時被抽的卡循環回牌底。
  • 受控(傳入 index + onIndexChange)與非受控(defaultIndex)雙模式;子節點數量變動時非受控索引會自動夾回合法範圍。

可及性

  • 最上層卡片可聚焦(tabIndex),方向鍵對應四向抽牌,Enter/Space 向上抽出。
  • 牌組容器帶 role="group"aria-roledescription,並以 aria-live 區域朗讀目前張數/剩餘張數。
  • 使用者系統開啟「減少動態效果」時,停用拖曳與飛出位移,抽牌改為淡出,避免大幅度動態。

On this page