WebberUI

Tri-Pane Workspace Shell

A nav + list + detail master-detail application shell with built-in collapsing, an overlay mode, and a page-by-page responsive state machine, its transitions choreographed as a spring sequence.

This is a WebberUI Pro component

Free during the launch campaign: sign up or sign in, then hit “Copy install command” in the preview above and it installs straight away — no payment, no credit card. The command below returns 401 while you are signed out.

How to install Pro components →See the plans →

Loading preview…
npx shadcn@latest add "https://webberui.com/r/tri-pane-workspace-shell.json?t=<install token>"

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

256
300
64
1024
640
<TriPaneWorkspaceShell />

Installation

npx shadcn@latest add "https://webberui.com/r/tri-pane-workspace-shell.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/tri-pane-workspace-shell.

Usage

The three columns are passed in through the nav / list / detail slots. The shell derives its mode from the container width: on desktop the three columns sit side by side (the nav column can collapse to an icon rail), on tablet the nav degrades to an overlay, and on mobile it turns into page-by-page navigation.

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

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

Inside any of the columns, use useTriPaneWorkspace() to read the current mode and advance to the next column in mobile page-by-page mode:

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

Props

PropTypeDefaultDescription
navReactNodeNav column content (primary navigation)
listReactNodeList column content (the "master" of master-detail)
detailReactNodeDetail column content (the "detail" of master-detail)
navHeaderReactNodeNav column header; hidden automatically when collapsed to an icon rail
collapsiblebooleantrueWhether the nav column may be collapsed to an icon rail on desktop
navCollapsedbooleanControlled: whether it is collapsed to an icon rail (desktop only)
defaultNavCollapsedbooleanfalseUncontrolled: initial collapsed state
onNavCollapsedChange(collapsed: boolean) => voidCollapsed-state change callback
activePane"nav" | "list" | "detail"Controlled: the column shown in mobile page-by-page mode
defaultActivePane"nav" | "list" | "detail""list"Uncontrolled: initially visible column
onActivePaneChange(pane) => voidVisible-column change callback
onModeChange(mode) => voidMode (breakpoint) change callback
navWidthnumber256Nav column width when expanded (px)
navCollapsedWidthnumber64Width when collapsed to an icon rail (px)
listWidthnumber300List column width (px); the detail column takes the remaining space
mobileBreakpointnumber640Below this container width the shell switches to mobile page-by-page
desktopBreakpointnumber1024Below this width, the tablet overlay mode; at or above it, the desktop three-column mode
navLabel / listLabel / detailLabelstring"導覽" / "清單" / "詳情"Label for each column (used in the small-screen top bar and for a11y)
classNamestringAppended to the outermost container's className

useTriPaneWorkspace()

Callable from any column inside the shell. It returns { mode, activePane, showPane, navCollapsed, setNavCollapsed, navOpen, openNav, closeNav } for advancing pages and keeping state in sync.

How it works

  • Breakpoints on container width, not window width: a ResizeObserver measures the shell itself, so it degrades correctly no matter where it is embedded (including next to a sidebar).
  • Unified geometry + spring sequence: the three columns are absolutely positioned and tween their x / width; on a mode change the same spring set carries them, and a small increasing delay produces a left-to-right sense of choreography.
  • Spring parameters can be tuned alongside the interaction color transitions through tokens such as var(--wb-duration-fast,200ms).

Accessibility

  • When the tablet overlay opens, focus moves into the nav column, Esc closes it, and focus returns to the trigger afterwards; clicking the overlay also closes it.
  • A column that has left (moved off screen, or an overlay that closed) gets aria-hidden and inert, so it is neither reachable by Tab nor announced by assistive technology.
  • The nav column is a navigation landmark (a dialog while it is an overlay); the collapse button carries aria-expanded, and the small-screen top bar's menu button links to the nav column with aria-controls.
  • When the user has "reduce motion" enabled at the system level, all offsets and tweens complete instantly (the layout structure is unchanged).

On this page