網頁簡報

網頁簡報引擎

16:9 網頁簡報容器 React 元件:等比縮放、鍵盤/觸控翻頁、四種轉場、進度條與頁碼、講者備註、網址同步頁碼與列印成每頁一張,內建九種版面子元件。

把簡報直接做成網頁的一頁。投影片以設計稿尺寸(預設 1280×720)排版,再依容器寬高用 transform: scale() 等比縮放,字級與間距不會因螢幕大小變形。支援鍵盤 ← → Space Home End 與觸控左右滑動翻頁、F 全螢幕、N 講者備註、? 快捷鍵說明;換頁有 slide/fade/zoom/none 四種轉場,底部進度條與逐位滾動的頁碼即時更新。開啟 syncHash 後頁碼寫進網址(#3 為第 3 頁),列印或「另存 PDF」時每頁剛好一張投影片。另附 TitleSlide、StatsSlide、CodeSlide 等九種版面子元件,丟進去就是一份完整簡報。

把這個效果裝進你的專案

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

npx webberui@latest add slide-deck-shell

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

Playground

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

400
編輯中的呼叫預設屬性
<SlideDeckShell/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/slide-deck-shell.json

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

使用

import {
  SlideDeckShell,
  TitleSlide,
  ListSlide,
  StatsSlide,
  ClosingSlide,
} from "@/components/ui/slide-deck-shell";

<SlideDeckShell label="Q3 產品回顧" transition="slide" syncHash>
  <TitleSlide
    eyebrow="2026 Q3"
    title="Q3 產品回顧"
    subtitle="三個月、兩次大改版"
    notes="開場先自我介紹"
  />
  <ListSlide
    title="三項主要成果"
    ordered
    items={["編輯器重寫", "團隊素材庫", "行動版審稿"]}
  />
  <StatsSlide
    title="關鍵數字"
    items={[
      { value: 12480, label: "月活躍使用者" },
      { value: 64, suffix: "%", label: "30 日留存率" },
    ]}
  />
  <ClosingSlide title="謝謝大家" contact="hello@example.com" />
</SlideDeckShell>

// 也可以用資料驅動(slides 優先於 children)
<SlideDeckShell
  slides={[
    { id: "cover", content: <TitleSlide title="封面" />, notes: "備註" },
    { id: "end", content: <ClosingSlide title="結束" /> },
  ]}
/>

Props

SlideDeckShell

Prop型別預設值說明
childrenReact.ReactNode—投影片(<Slide> 或內建版面元件);與 slides 擇一,slides 優先
slidesDeckSlideData[]—資料驅動的投影片陣列;提供時忽略 children
indexnumber—受控的目前頁索引(0 起算);未提供時由元件內部管理
defaultIndexnumber0非受控模式的初始頁索引(0 起算)
onIndexChange(index: number) => void—頁索引變動時回呼(0 起算)
transition"slide" | "fade" | "zoom" | "none""slide"換頁轉場;系統開啟減少動態效果時一律改為短淡入
aspectRationumber16 / 9投影片寬高比
baseWidthnumber1280設計稿寬度(px);投影片以此尺寸排版,再依容器等比縮放
showProgressbooleantrue顯示底部進度條
showCounterbooleantrue顯示頁碼
syncHashbooleanfalse以網址 hash(#3 為第 3 頁)同步頁碼;預設關,避免同頁多個簡報互相搶網址
notesboolean—受控的講者備註面板開關;未提供時由元件內部管理
defaultNotesbooleanfalse非受控模式下備註面板是否預設展開
onNotesChange(open: boolean) => void—備註面板開關變動時回呼
keyboard"focus" | "global""focus"focus 只在簡報聚焦或全螢幕時接收按鍵;global 監聽整個視窗
labelstring"簡報"簡報名稱,作為根元素的 aria-label
labelsPartial<SlideDeckShellLabels>—介面文字覆寫
classNamestring—透傳到最外層容器

DeckSlideData

欄位型別預設值說明
idstring—穩定識別碼,作為 React key;未提供時用索引
contentReact.ReactNode—投影片內容(通常是版面元件)
notesReact.ReactNode—講者備註

SlideDeckShellLabels

欄位型別預設值說明
prevstring"上一頁"上一頁按鈕
nextstring"下一頁"下一頁按鈕
fullscreenstring"全螢幕"進入全螢幕按鈕
exitFullscreenstring"離開全螢幕"離開全螢幕按鈕
notesstring"講者備註"講者備註按鈕與面板標題
shortcutsstring"快捷鍵"快捷鍵按鈕與說明層標題
closestring"關閉"關閉說明層按鈕
progressstring"簡報進度"進度條的無障礙名稱
noNotesstring"這一頁沒有備註"當頁沒有備註時的提示
deckstring"簡報"根元素的 aria-roledescription
slidestring"投影片"每頁的 aria-roledescription
page(current: number, total: number) => string第 N 頁,共 M 頁頁碼描述,用於每頁 aria-label 與翻頁朗讀

版面子元件

所有版面元件都接受 notes(講者備註)、background(任何 CSS background 值)與 className。

元件主要 props說明
Slidechildren空白頁,以設計稿尺寸滿版排版,自行放內容
TitleSlideeyebrow、title、subtitle封面頁
SectionSlidenumber、title、description章節分隔頁
TwoColumnSlidetitle、left、right、ratio(預設 [1, 1])雙欄頁
ImageFullSlidesrc、alt、title、caption滿版圖片(自備網址)或漸層,底部疊字卡
StatsSlidetitle、items: DeckStat[]、locale(預設 "zh-TW")數據頁,進場時從 0 計數 1.2 秒
QuoteSlidequote、author、role引言頁
ListSlidetitle、items、ordered條列頁,逐條 stagger 80ms 淡入
CodeSlidetitle、code、language、filename、copyLabel、copiedLabel程式碼頁:等寬字、行號、複製鈕
ClosingSlidetitle、subtitle、contact結尾頁

DeckStat

欄位型別預設值說明
valuenumber—目標數值
labelReact.ReactNode—數據說明
prefixstring—數字前綴(例如 NT$)
suffixstring—數字後綴(例如 %)

細節

  • 縮放:以 ResizeObserver 量測容器,縮放比取「容器寬 ÷ baseWidth」與「容器高 ÷ 設計稿高」的較小者,全螢幕時自動上下或左右留邊。投影片裡可以直接用 px 與一般 Tailwind 字級排版。
  • 轉場:AnimatePresence mode="wait",退場與進場依序播放,整次換頁的總時長是 --wb-deck-duration(預設 400ms),曲線是 --wb-deck-ease(預設 cubic-bezier(0.22,1,0.36,1))。兩個變數在換頁前從 CSS 讀取,可在任何祖先元素覆寫。強調色用 --wb-deck-accent,預設跟隨文字色。
  • 鍵盤:預設 keyboard="focus",只有點過簡報(或 Tab 聚焦)後才接收方向鍵與 Space,不會搶走頁面捲動;全螢幕時改為監聽整個視窗。輸入框裡的按鍵一律放行。
  • 觸控:水平滑動超過 50px,或速度超過 0.3px/ms 即翻頁;垂直滑動交給頁面捲動(touch-action: pan-y)。
  • 全螢幕:F 鍵或按鈕呼叫 Fullscreen API,瀏覽器不支援時隱藏按鈕。Esc 先關閉快捷鍵說明;全螢幕下的 Esc 由瀏覽器處理退出。
  • 講者備註:顯示在簡報下方,全螢幕時改為右側欄。children 模式從每個子元件的 notes prop 收集。
  • 列印:@media print 下隱藏控制列、停用縮放與轉場,所有投影片依序輸出,紙張尺寸設為投影片尺寸,「另存 PDF」時每頁剛好一張。這段 @page 規則在元件掛載期間對整個頁面生效,建議簡報放在獨立路由。
  • 不做 PPTX 匯出:本元件是純前端元件,需要 PPTX 請先用瀏覽器列印成 PDF,或另行轉檔。
  • CodeSlide 只做等寬字、行號與複製鈕,不做語法高亮;需要高亮可以把內容換成 WebberUI 的 code-block。

可及性

  • 根元素為 role="region"、aria-roledescription="簡報" 並以 label 命名;每頁為 role="group"、aria-roledescription="投影片",aria-label 如「第 3 頁,共 8 頁」
  • 只渲染目前這一頁,退場中的頁設為 inert 並對輔助科技隱藏
  • 翻頁時 aria-live="polite" 區域朗讀「第 N 頁,共 M 頁」;底部進度條為 role="progressbar"
  • 所有控制鈕都是 type="button"、帶 aria-label 與 focus-visible 外框;備註按鈕帶 aria-pressed
  • 快捷鍵說明為 role="dialog"、aria-modal,開啟時焦點移到關閉鈕並鎖在對話框內,關閉後焦點回到原處
  • 使用者系統開啟「減少動態效果」時,所有轉場改為 150ms 純淡入,數字直接顯示終值、條列不做 stagger、頁碼不滾動