WebberUI

Tri-Pane Workspace Shell

導航+列表+詳情的三欄主從式應用殼層,內建摺疊、覆蓋層、逐頁的響應式狀態機,轉換以彈簧序列編排。

載入預覽⋯

Playground

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

256
300
64
1024
640
<TriPaneWorkspaceShell />

安裝

npx shadcn@latest add https://webberui.com/r/tri-pane-workspace-shell.json

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

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

npm install motion clsx tailwind-merge lucide-react

使用

三欄以 nav / list / detail 三個插槽傳入。殼層依「容器寬度」推導模式:桌機三欄並排(導航欄可摺疊為圖示欄)、平板將導航降級為覆蓋層、手機轉為逐頁推進。

import {
  TriPaneWorkspaceShell,
  useTriPaneWorkspace,
} from "@/components/ui/tri-pane-workspace-shell";

<div className="h-[600px]">
  <TriPaneWorkspaceShell
    navHeader={<span>工作區</span>}
    nav={<NavList />}
    list={<MailList />}
    detail={<MailDetail />}
  />
</div>;

在任一欄的內容中,用 useTriPaneWorkspace() 取得目前模式並在手機逐頁模式下推進到下一欄:

function MailList() {
  const { mode, showPane } = useTriPaneWorkspace();
  return (
    <button
      onClick={() => {
        if (mode !== "desktop") showPane("detail");
      }}
    >
      開啟郵件
    </button>
  );
}

Props

Prop型別預設值說明
navReactNode導航欄內容(主導覽)
listReactNode列表欄內容(主從式的「主」)
detailReactNode詳情欄內容(主從式的「從」)
navHeaderReactNode導航欄頁首;摺疊成圖示欄時自動隱藏
collapsiblebooleantrue是否允許在桌機摺疊導航欄為圖示欄
navCollapsedboolean受控:是否摺疊為圖示欄(僅桌機生效)
defaultNavCollapsedbooleanfalse非受控:初始摺疊狀態
onNavCollapsedChange(collapsed: boolean) => void摺疊狀態變更回呼
activePane"nav" | "list" | "detail"受控:手機逐頁模式顯示的欄
defaultActivePane"nav" | "list" | "detail""list"非受控:初始顯示的欄
onActivePaneChange(pane) => void顯示欄變更回呼
onModeChange(mode) => void模式(斷點)變更回呼
navWidthnumber256展開時導航欄寬度(px)
navCollapsedWidthnumber64摺疊為圖示欄時的寬度(px)
listWidthnumber300列表欄寬度(px);詳情欄佔剩餘空間
mobileBreakpointnumber640容器寬度低於此值切換為手機逐頁
desktopBreakpointnumber1024低於此值為平板覆蓋層,以上為桌機三欄
navLabel / listLabel / detailLabelstring"導覽" / "清單" / "詳情"各欄標籤(小螢幕頂列與 a11y 用)
classNamestring追加到最外層容器的 className

useTriPaneWorkspace()

在殼層內的任一欄可呼叫,回傳 { mode, activePane, showPane, navCollapsed, setNavCollapsed, navOpen, openNav, closeNav },用於逐頁推進與同步狀態。

細節

  • 以容器寬度而非視窗寬度斷點:透過 ResizeObserver 量測殼層本身的寬度,因此嵌在任意版位(含側邊欄旁)都能正確降級。
  • 統一幾何 + 彈簧序列:三欄以絕對定位並補間 x / width,模式切換時由同一組 spring 承接,並以遞增的微小延遲形成由左而右的編排感。
  • 彈簧參數可透過 var(--wb-duration-fast,200ms) 等 token 一併調校互動色彩過渡。

可及性

  • 平板覆蓋層開啟時焦點移入導航欄、Esc 可關閉、關閉後焦點歸還觸發鈕;遮罩點擊關閉。
  • 退場(離屏或覆蓋層關閉)的欄會加上 aria-hiddeninert,不會被 Tab 聚焦、也不會被輔助科技朗讀。
  • 導航欄為 navigation 地標(覆蓋層時為 dialog);摺疊鈕帶 aria-expanded,小螢幕頂列的選單鈕以 aria-controls 連結導航欄。
  • 使用者系統開啟「減少動態效果」時,所有位移 / 補間即時完成(不改變版面結構)。

On this page