WebberUI

直播購物疊層(React)

直播賣場 UI 疊層的 React 元件:固定比例舞台上疊 LIVE 徽章與觀看人數滾動、愛心噴發、彈幕留言流、「+1」喊單自動偵測與浮出計數、置頂商品卡與庫存倒數,可放 children 當真正的影片。

這是 WebberUI Pro 元件

上線活動期間免費:註冊或登入後,在上方預覽區按「複製安裝指令」就能直接安裝,不需付費、不用綁信用卡。下方那條指令未登入時會回 401。

怎麼安裝 Pro 元件 →查看方案 →

台灣社群直播、電商直播的「喊單」文化:主播介紹商品,觀眾在留言區打「+1」就代表下單。這個元件把整套直播賣場的 UI 疊層封裝成一個固定比例的舞台(直式 9:16 或橫式 16:9)——底層是漸層+緩慢漂移的光暈當作影片占位(也可放 children 當真正的 video),上面疊:左上 LIVE 徽章與逐位滾動的觀看人數、右側愛心按鈕與上飄粒子、左下留言流(新訊息從底部滑入、舊的上移淡出、帳號以色塊首字當頭像)、+1 自動偵測(符合規則的留言高亮,商品卡上方浮出「+1」字樣,訂單數與庫存即時更新)、置頂商品卡與「+1 喊單」按鈕。留言串支援受控/非受控,也可以開 simulate 讓元件自己模擬留言與觀看人數變動;所有帳號、留言與商品皆為虛構示範資料。

載入預覽⋯
npx shadcn@latest add "https://webberui.com/r/live-shopping-overlay.json?t=<安裝 token>"

Playground

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

5
<LiveShoppingOverlay />

安裝

npx shadcn@latest add "https://webberui.com/r/live-shopping-overlay.json?t=<安裝 token>"

或在 components.json 設定 registries 後,改用 @webberui/live-shopping-overlay 安裝。

使用

import {
  LiveShoppingOverlay,
  isPlusOne,
} from "@/components/ui/live-shopping-overlay";

// 示範模式:留言流與觀看人數由元件內部模擬(商品與帳號皆為虛構)
<LiveShoppingOverlay
  simulate
  product={{ name: "陶瓷手沖濾杯組", price: 680, stock: 12 }}
  onPlusOne={(msg) => console.log("喊單", msg.user, msg.text)}
  onHeart={(count) => console.log("愛心", count)}
/>

// 正式接後端:留言受控、觀看人數由 API 提供,舞台底層放真正的 video
<LiveShoppingOverlay
  layout="landscape"
  messages={messages}
  onMessagesChange={setMessages}
  viewers={viewers}
  product={product}
  onPlusOne={(msg) => createOrder(msg)}
>
  <video src={streamUrl} autoPlay muted playsInline />
</LiveShoppingOverlay>

// 喊單判定函式可單獨使用(例如在後端或表單層過濾留言)
isPlusOne("+1 黑色"); // true
isPlusOne("我要 1 個"); // true
isPlusOne("有優惠碼嗎"); // false

Props

Prop型別預設值說明
messagesLiveMessage[]受控留言串(由舊到新);提供時內部狀態與 simulate 失效,新增留言請透過 onMessagesChange 回寫
defaultMessagesLiveMessage[][]非受控模式的初始留言
onMessagesChange(messages: LiveMessage[]) => void留言串變動時回呼(按「+1 喊單」或模擬新增留言);受控模式下由此更新 messages
simulatebooleanfalse非受控時由元件內部以計時器模擬留言流(含隨機 +1);示範用,正式接後端時請關閉
productLiveProduct內建虛構商品(NT$680、庫存 20)置頂商品(名稱、售價、起始庫存)
viewersnumber受控觀看人數;未提供時由內部模擬每隔數秒微幅浮動
defaultViewersnumber1280內部模擬觀看人數的起始值(viewers 未提供時才有效)
showViewersbooleantrue是否顯示右上角觀看人數
titlestring"週三晚上開賣"直播間標題,顯示於 LIVE 徽章右側
selfNamestring"我"按「+1 喊單」時送出留言所用的帳號名稱
onPlusOne(message: LiveMessage) => void每偵測到一則新的 +1 留言時回呼一次(含自己按下的喊單)
onHeart(count: number) => void點擊愛心時回呼,帶入累計次數
layout"portrait" | "landscape""portrait"舞台比例:直式 9:16(手機直播)或橫式 16:9
maxMessagesnumber5留言流最多同時顯示的則數,超過的舊留言上移淡出
childrenReact.ReactNode放在舞台底層的節點(例如真正的 video),會被拉伸填滿並置於疊層之下
classNamestring透傳到最外層舞台容器

LiveMessage

欄位型別預設值說明
idstring唯一識別碼;元件以此判斷「新訊息」,同一個 id 不會重複觸發 +1
userstring發言帳號名稱(頭像取首字,並依名稱雜湊上色)
textstring留言內容;符合 +1 規則時自動高亮並計入喊單
tsnumber送出時間(毫秒時間戳),選填、僅供呼叫端排序或顯示

LiveProduct

欄位型別預設值說明
namestring商品名稱
pricenumber售價(新台幣)
stocknumber起始庫存;每一筆 +1 扣一件,扣到 0 顯示完售並停用喊單按鈕

另外具名匯出 isPlusOne(text)LiveShoppingLayout 型別,方便在後端或表單層重複使用同一套喊單判定規則。

細節

  • +1 判定規則(isPlusOne):留言 trim 後符合 /(^|\s)\+?1(\s|$)/(獨立的「1」或「+1」,例如「1」「我要 1 個」),或內文任何位置含「+1」/全形「+1」(例如「+1黑色」「幫我留一個+1」)
  • 訂單數與庫存:每一則「新的」+1 留言扣一件庫存並觸發 onPlusOne;元件以 id 記錄已處理的留言,同一個 id 不會重複計數。初始留言(defaultMessages 或首次傳入的 messages)中的 +1 直接算進起始訂單數,但不觸發回呼與浮出動畫,SSR 與客戶端輸出一致
  • 受控/非受控:提供 messages 即為受控,元件不再自己新增留言(simulate 失效),按「+1 喊單」會以 onMessagesChange([...messages, 新留言]) 回寫,由你決定是否送到後端。非受控時內部保留的則數比 maxMessages 多一些,動態調大上限還有舊留言可補
  • 模擬留言流:以 setTimeout 鏈而非固定 setInterval 排程,每則間隔帶確定性抖動,讀起來像真人留言而非節拍器;約三成五機率喊單,完售後只出一般聊天;分頁切到背景時不塞留言,避免回來瞬間一大串動畫同時播放;卸載時清理計時器
  • 觀看人數:viewers 受控或以 defaultViewers 起始由內部每 3 秒微幅浮動(約 ±3%),數字逐位滾動;千分位格式自行實作,不走 toLocaleString,避免伺服器與瀏覽器 ICU 差異造成 hydration 不一致
  • 愛心與「+1」浮出粒子皆以 motion 自行實作,每顆的飄移、擺幅、縮放與色調由序號推導的確定性偽亂數算出,render 期間不呼叫 Math.random;粒子壽命結束即移除並清理計時器
  • 底層「影片」占位是漸層+兩顆緩慢漂移的光暈,不用外部影片/圖片;傳入 children 時會被拉伸填滿(object-cover)並置於所有疊層之下,上下漸暗遮罩確保白字、留言與商品卡在任何底圖上都可讀
  • 庫存倒數:商品卡進度條隨每筆 +1 縮短,剩 3 件以內轉紅並顯示「最後 N 件」,扣到 0 顯示「已完售」並停用喊單按鈕

可及性

  • 最外層為 role="region" 並以 aria-label 帶入直播間標題;愛心按鈕與「+1 喊單」皆為 type="button",具 focus-visible 環,完售時喊單按鈕 disabled
  • 留言流為 role="log"aria-live="off"——模擬留言每一兩秒一則,逐則播報會淹沒螢幕閱讀器;只有自己按下「+1 喊單」時,才透過隱形的 role="status" 區域播報累計單數與剩餘庫存
  • 觀看人數不放 aria-live(每隔數秒就變),改以 sr-only 文字補上「人觀看中」單位;愛心按鈕的 aria-label 帶入已送出次數
  • 所有裝飾性元素(光暈、漸暗遮罩、頭像色塊、粒子、進度條)皆 aria-hidden,留言文字本身仍是可讀的 DOM 內容
  • 使用者系統開啟「減少動態效果」時,停用光暈漂移、LIVE 呼吸點、愛心與「+1」粒子、數字滾動與留言滑入動畫,只保留數字、高亮與文字更新;模擬留言與觀看人數變動的間隔放慢一倍

本頁目錄