Receipt Cart
熱感應收據隱喻的購物車:品項逐行打印進場、鋸齒紙緣延伸、紙尾小計與免運進度滾動更新、移除時該行被劃線撕出。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
60
5
0.05
<ReceiptCart />
安裝
npx shadcn@latest add https://webberui.com/r/receipt-cart.json或在 components.json 設定 registries 後,改用 @webberui/receipt-cart 安裝。
安裝依賴後,從 registry JSON(/r/receipt-cart.json 的 files[0].content)複製 receipt-cart.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
以資料驅動,傳入品項陣列即可。支援受控(items + onItemsChange)與非受控(defaultItems)雙模式:
import { ReceiptCart } from "@/components/ui/receipt-cart";
<ReceiptCart
defaultItems={[
{ id: "a", name: "手沖濾掛咖啡", price: 12.5, quantity: 2 },
{ id: "b", name: "陶瓷馬克杯", price: 18, note: "霧面炭黑" },
]}
currency="$"
freeShippingThreshold={75}
shippingFee={5}
taxRate={0.08}
onRemove={(removed) => console.log("撕除", removed.name)}
/>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
items | ReceiptCartItem[] | — | 受控模式:由外部提供的品項陣列 |
defaultItems | ReceiptCartItem[] | [] | 非受控模式:初始品項陣列 |
onItemsChange | (items) => void | — | 品項變動後回傳完整陣列 |
onRemove | (removed, remaining) => void | — | 某列被撕除後觸發 |
currency | string | "$" | 幣別前綴符號 |
freeShippingThreshold | number | — | 免運門檻;提供後於紙尾顯示進度條 |
shippingFee | number | 0 | 未達門檻時的運費 |
taxRate | number | — | 稅率(0–1),提供後加計稅額 |
storeName | string | "WEBBER MART" | 收據抬頭店名 |
subtitle | string | "CUSTOMER RECEIPT" | 抬頭副標 |
meta | ReactNode | — | 抬頭下方的日期/交易資訊列 |
orderNumber | string | — | 條碼下方單號文字 |
removable | boolean | true | 是否顯示每列移除按鈕 |
printStagger | number | 0.12 | 逐行打印進場的每列間隔(秒) |
ReceiptCartItem:{ id, name, price, quantity?, note? }。
細節
- 品項如出單機般逐行打印進場:整列淡入下移,內容以
clip-path由上而下顯影,printStagger控制節奏 - 鋸齒紙緣以 SVG
pattern平鋪三角齒,填色跟隨紙張底色,因此紙張隨品項增加自然向下延伸 - 紙尾小計、稅金、運費與免運進度以 spring 平滑滾動更新;達門檻時運費列切換為「免運 FREE」並填滿進度條
- 移除品項時該列先被橫向劃線,劃線完成後才真正撕出(列高收合、向右滑移淡出),其餘列平滑遞補
可及性
- 收據容器帶
role="region"與aria-label,免運進度條為role="progressbar"並提供aria-valuenow/min/max - 每個移除按鈕帶對應品項名稱的
aria-label,可鍵盤聚焦操作,focus-visible有清楚焦點環 - 使用者系統開啟「減少動態效果」時,停用打印與滾動動畫,移除時略過劃線直接撕除,金額直接顯示最終值