Zen Mode Shell
專注模式殼層:一鍵進入時側欄、頂欄與輔助面板依時間軸依序淡出滑離,主內容緩動重新置中放大,退出時反向編排復原整個殼層。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
200
52
220
<ZenModeShell />
安裝
npx shadcn@latest add https://webberui.com/r/zen-mode-shell.json或在 components.json 設定 registries 後,改用 @webberui/zen-mode-shell 安裝。
安裝依賴後,從 registry JSON(/r/zen-mode-shell.json 的 files[0].content)複製 zen-mode-shell.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge lucide-react使用
以 ZenModeShell 為框架,內部放入 ZenMain(主內容)與任意組合的 ZenSidebar、ZenTopbar、ZenPanel 殼層區塊。將 ZenTrigger 置於頂欄即可一鍵切換專注模式。
import {
ZenMain,
ZenModeShell,
ZenPanel,
ZenSidebar,
ZenTopbar,
ZenTrigger,
} from "@/components/ui/zen-mode-shell";
export function Example() {
return (
<ZenModeShell className="h-[420px]">
<ZenSidebar>{/* 導覽 */}</ZenSidebar>
<ZenTopbar>
<span className="ml-auto">
<ZenTrigger />
</span>
</ZenTopbar>
<ZenPanel>{/* 輔助資訊 */}</ZenPanel>
<ZenMain>{/* 主內容 */}</ZenMain>
</ZenModeShell>
);
}主內容的讓位內距由掛載了哪些殼層區塊自動推導——省略 ZenPanel 時,主內容右側便不再預留空間。
受控模式
傳入 active 即進入受控模式,並以 onActiveChange 同步狀態;省略 active 時改用內部非受控狀態(可搭配 defaultActive 設定初始值)。
const [zen, setZen] = React.useState(false);
<ZenModeShell active={zen} onActiveChange={setZen}>
{/* ... */}
</ZenModeShell>;尺寸讓位
sidebarWidth、topbarHeight、panelWidth 同時決定各殼層區塊的尺寸與主內容對應方向的讓位量,兩者恆保持一致,進入專注時內距收回為 0,主內容自然重新置中。
Props
ZenModeShell
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 放入 ZenMain 與 ZenSidebar/ZenTopbar/ZenPanel |
active | boolean | — | 受控:是否處於專注模式;省略則用內部非受控狀態 |
defaultActive | boolean | false | 非受控模式的初始專注狀態 |
onActiveChange | (active: boolean) => void | — | 專注狀態變更時觸發 |
sidebarWidth | number | 200 | 側欄寬度(px),同時決定主內容左側讓位量 |
topbarHeight | number | 52 | 頂欄高度(px),同時決定主內容頂部讓位量 |
panelWidth | number | 220 | 輔助面板寬度(px),同時決定主內容右側讓位量 |
exitLabel | string | "退出專注模式" | 退出鈕的無障礙標籤與文字 |
ZenSidebar / ZenTopbar / ZenPanel
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 區塊內容 |
className | string | — | 追加到區塊容器的 className |
ZenMain
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 主內容 |
className | string | — | 追加到主內容容器的 className |
ZenTrigger
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | 圖示加「專注模式」 | 自訂觸發鈕內容 |
className | string | — | 追加到觸發鈕的 className |
細節
- 進入專注時,側欄、頂欄、輔助面板依
ORDER順序以固定間隔(STEP)先後淡出並向各自邊界滑離,模擬 GSAP 時間軸的逐格編排;退出時以反向順序回填。 - 主內容以現有殼層區塊的尺寸讓位定位,進入時緩動收回內距、重新置中並輕微放大;退出時主內容先復位,殼層才依序回填(
MAIN_LEAD領先量)。 - 殼層區塊以絕對定位貼齊四邊,位移採 transform(
x/y百分比)不觸發回流,動畫皆走 GPU 合成。 - 退出鈕待殼層淡出後才浮現於右上角,退出時快速收起。
可及性
- 支援
Esc鍵退出專注模式。 - 進入專注時焦點自動移至退出鈕,退出時歸還給
ZenTrigger觸發鈕。 - 專注模式下各殼層區塊套用
inert,自動移出 Tab 焦點序並對輔助科技隱藏,避免操作到已離場的介面。 ZenTrigger以aria-pressed反映目前是否處於專注模式。- 開啟「減少動態效果」時,殼層改為純淡入淡出、主內容即時定位不放大,不影響版面與功能。