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.json 的 files[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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
nav | ReactNode | — | 導航欄內容(主導覽) |
list | ReactNode | — | 列表欄內容(主從式的「主」) |
detail | ReactNode | — | 詳情欄內容(主從式的「從」) |
navHeader | ReactNode | — | 導航欄頁首;摺疊成圖示欄時自動隱藏 |
collapsible | boolean | true | 是否允許在桌機摺疊導航欄為圖示欄 |
navCollapsed | boolean | — | 受控:是否摺疊為圖示欄(僅桌機生效) |
defaultNavCollapsed | boolean | false | 非受控:初始摺疊狀態 |
onNavCollapsedChange | (collapsed: boolean) => void | — | 摺疊狀態變更回呼 |
activePane | "nav" | "list" | "detail" | — | 受控:手機逐頁模式顯示的欄 |
defaultActivePane | "nav" | "list" | "detail" | "list" | 非受控:初始顯示的欄 |
onActivePaneChange | (pane) => void | — | 顯示欄變更回呼 |
onModeChange | (mode) => void | — | 模式(斷點)變更回呼 |
navWidth | number | 256 | 展開時導航欄寬度(px) |
navCollapsedWidth | number | 64 | 摺疊為圖示欄時的寬度(px) |
listWidth | number | 300 | 列表欄寬度(px);詳情欄佔剩餘空間 |
mobileBreakpoint | number | 640 | 容器寬度低於此值切換為手機逐頁 |
desktopBreakpoint | number | 1024 | 低於此值為平板覆蓋層,以上為桌機三欄 |
navLabel / listLabel / detailLabel | string | "導覽" / "清單" / "詳情" | 各欄標籤(小螢幕頂列與 a11y 用) |
className | string | — | 追加到最外層容器的 className |
useTriPaneWorkspace()
在殼層內的任一欄可呼叫,回傳 { mode, activePane, showPane, navCollapsed, setNavCollapsed, navOpen, openNav, closeNav },用於逐頁推進與同步狀態。
細節
- 以容器寬度而非視窗寬度斷點:透過
ResizeObserver量測殼層本身的寬度,因此嵌在任意版位(含側邊欄旁)都能正確降級。 - 統一幾何 + 彈簧序列:三欄以絕對定位並補間
x/width,模式切換時由同一組 spring 承接,並以遞增的微小延遲形成由左而右的編排感。 - 彈簧參數可透過
var(--wb-duration-fast,200ms)等 token 一併調校互動色彩過渡。
可及性
- 平板覆蓋層開啟時焦點移入導航欄、
Esc可關閉、關閉後焦點歸還觸發鈕;遮罩點擊關閉。 - 退場(離屏或覆蓋層關閉)的欄會加上
aria-hidden與inert,不會被 Tab 聚焦、也不會被輔助科技朗讀。 - 導航欄為
navigation地標(覆蓋層時為dialog);摺疊鈕帶aria-expanded,小螢幕頂列的選單鈕以aria-controls連結導航欄。 - 使用者系統開啟「減少動態效果」時,所有位移 / 補間即時完成(不改變版面結構)。