Skip to content

Application

Workspace

Resizable panes, a focus mode, an inspector and a local layout that survives a reload. Not a drag-and-drop dashboard: the layout is the component tree, so a pane cannot be moved somewhere the code does not describe.

import { InspectorPane, InspectorRow, InspectorSection, InspectorToggle, Workspace, WorkspaceGroup, WorkspacePane, WorkspacePaneBody, WorkspacePaneFooter, WorkspacePaneHeader, WorkspaceResizeHandle, } from "@luc/ui/workspace";

Table, inspector, persistence

Drag the divider, or focus it with Tab and resize with the arrow keys. Sizes persist under this demo's key; Reset returns to the defaults. Below 64rem the panes stack and the handles disappear.

three panesnested split

Research runs

48 prepared rows

Selection is not in the URL; it is not shareable state.

Research runs
Equity
NDXMean reversionFailedTrend0.4825.4%-13.7%29759.9%Sep 9
NDXVolatility carryLiveStress1.5523.0%-26.0%42345.5%Sep 9
AAPLCross-sectional momentumLiveStress1.73-3.8%-32.4%39440.2%Aug 24
MSFTTrend breakoutFailedRange0.339.4%-26.8%22323.3%Sep 21
BTC-USDVolatility carryPausedRange2.0041.7%-29.1%34156.7%Sep 13
NVDAMean reversionPausedStress1.32-2.0%-15.0%53293.3%Aug 19
MSFTRegime switchPausedStress0.267.0%-12.0%73086.0%Aug 20
MSFTTrend breakoutLiveStress1.2230.9%-15.5%58889.8%Sep 2
SPXRegime switchPausedStress0.3136.5%-17.1%23264.3%Aug 13
AAPLMean reversionPausedRange-0.1636.6%-33.7%13653.4%Sep 5
SOL-USDTrend breakoutLiveStress-0.1313.8%-36.5%9923.4%Aug 26
NVDATrend breakoutLiveTrend1.5421.7%-10.5%76957.3%Sep 19
MSFTRegime switchLiveRange1.230.3%-3.6%75683.4%Aug 19
SPXVolatility carryPausedTrend-0.278.2%-16.9%21487.1%Sep 9
SOL-USDFunding basisFailedStress1.05-3.8%-5.0%70933.2%Aug 22
AAPLMean reversionFailedStress0.2326.7%-19.4%44224.3%Aug 28
NVDACross-sectional momentumLiveRange0.1117.2%-28.3%61542.8%Sep 7
GCTrend breakoutDraftTrend-0.4138.2%-29.9%80623.4%Aug 15
SPXMean reversionFailedRange-0.0833.7%-30.8%28540.5%Sep 15
ETH-USDVolatility carryDraftStress1.3637.9%-3.2%2461.0%Sep 16

Notes

A second pane in a nested split

Vertical splits are ordinary groups inside a pane. A pane may hold a chart, a table, a form, an editor or another workspace — the layout engine only knows about boxes.

3 fields

Inspector

NDX

Selected run

SymbolNDX
StrategyMean reversion
Statusfailed
Sharpe0.48
Trades297

Panes, handles, focus mode

A handle is a real separator with a value, a name and arrow-key resizing; the visible line is a hairline while the hit area is wide. Focus mode expands one pane to fill its group and Escape leaves it.

Sizes are personal state

A layout is stored per pane set, versioned, and validated on read: an incompatible shape is discarded rather than migrated. Sizes are never written to the URL — a shared link describes a view, not your window.

<WorkspaceGroup orientation="horizontal" persistKey="product:research" persistVersion={1} > <WorkspacePane id="chart" minSize="18rem">…</WorkspacePane> <WorkspaceResizeHandle label="Resize inspector" /> <InspectorPane id="inspector" open={open} onOpenChange={setOpen}> … </InspectorPane> </WorkspaceGroup>

When not to use a workspace

  • A document: use the page and the shell.
  • Two fixed columns: use the grid primitives.
  • A phone: it stacks, so design the stacked order first.
  • Anything a reader must not resize: pass locked.

Exports

Read from the published TypeScript API, so a prop that is not listed here does not exist and a default that is listed is the one the compiler sees.

Exported symbols
ExportKindSignature
useWorkspaceexport() => WorkspaceContextValue
useWorkspaceGroupexport() => WorkspaceGroupContextValue
Workspace4 documented props({ className, mode: modeProp, focusedId: focusedIdProp, onFocusedIdChange, density, children, ...props }: WorkspaceProps) => import("@types/react").JSX.Element
WorkspaceFocusBanner1 documented props({ label }: WorkspaceFocusBannerProps) => import("@types/react").JSX.Element | null
WorkspaceGroup7 documented props({ className, orientation, persistKey, persistVersion, storage, defaultLayout, panelIds, locked, children, ...props }: WorkspaceGroupProps) => import("@types/react").JSX.Element
WorkspacePane9 documented props({ id, defaultSize, minSize, maxSize, collapsible, collapsedSize, hideOnStacked, panelRef, onSizeChange, className, children, ...props }: WorkspacePaneProps) => import("@types/react").JSX.Element | n…
WorkspacePaneBody2 documented props({ className, flush, ariaLabel, ...props }: WorkspacePaneBodyProps) => import("@types/react").JSX.Element
WorkspacePaneFooterexport({ className, ...props }: React.ComponentPropsWithRef<"div">) => import("@types/react").JSX.Element
WorkspacePaneHeader6 documented props({ title, description, icon, actions, paneId, showReset, className, children, ...props }: WorkspacePaneHeaderProps) => import("@types/react").JSX.Element
WorkspaceResizeHandle1 documented props({ className, label, ...props }: WorkspaceResizeHandleProps) => import("@types/react").JSX.Element | null
Exported symbols
ExportKindSignature
InspectorPane16 documented props({ id, open: openProp, defaultOpen, onOpenChange, title, description, actions, footer, side, minSize, defaultSize, className, children, ...props }: InspectorPaneProps) => import("@types/react").JSX.E…
InspectorRow3 documented props({ label, value, numeric, className, ...props }: InspectorRowProps) => import("@types/react").JSX.Element
InspectorSection1 documented props({ label, className, children, ...props }: InspectorSectionProps) => import("@types/react").JSX.Element
InspectorSkeletonexport() => import("@types/react").JSX.Element
InspectorToggle4 documented props({ open, onOpenChange, label, className }: InspectorToggleProps) => import("@types/react").JSX.Element

Workspace props

Type: WorkspaceProps

Values the compiler reads from the declaration.

Workspace props
PropTypeDefaultNotes
density?"compact" | "comfortable" | undefined—
focusedId?string | null | undefined—Controlled focus-mode pane.
mode?WorkspaceMode | undefined—Force a mode. By default the viewport decides: panes at 64rem and up.
onFocusedIdChange?((id: string | null) => void) | undefined—

InspectorPane props

Type: InspectorPaneProps

Values the compiler reads from the declaration.

InspectorPane props
PropTypeDefaultNotes
actions?ReactNode—
childrenReactNode—
defaultOpen?boolean | undefined—
defaultSize?string | number | undefined—
description?ReactNode—
footer?ReactNode—Rendered under the inspector body, e.g. a primary action row.
hideOnStacked?boolean | undefined—Remove the pane instead of stacking it on a narrow viewport.
idstring—Pane id. Required: it keys the saved layout, so an implicit id would make the stored layout depend on render order.
maxSize?string | number | undefined—
minSize?string | number | undefined—
onOpenChange?((open: boolean) => void) | undefined—
onSizeChange?((collapsed: boolean) => void) | undefined—Reports collapse crossing zero. Used by `InspectorPane`.
open?boolean | undefined—Controlled open state.
panelRef?Ref<PanelImperativeHandle | null> | undefined—Forwarded to the engine so a consumer can expand or collapse the pane.
side?"start" | "end" | undefined—Which edge the pane sits on. Affects only the border it draws.
title?ReactNode—
WorkspaceFocusBanner props1 props

WorkspaceFocusBanner props

Type: WorkspaceFocusBannerProps

Values the compiler reads from the declaration.

WorkspaceFocusBanner props
PropTypeDefaultNotes
label?string | undefined—Wording for the banner.
WorkspaceGroup props7 props

WorkspaceGroup props

Type: WorkspaceGroupProps

Values the compiler reads from the declaration.

WorkspaceGroup props
PropTypeDefaultNotes
defaultLayout?Layout | undefined—Explicit starting layout, keyed by pane id.
locked?boolean | undefined—Disable dragging entirely.
orientation?"horizontal" | "vertical" | undefined—Horizontal splits side by side; vertical splits stack.
panelIds?readonly string[] | undefined—Panel ids the stored layout must match. Derived from the children by default.
persistKey?string | undefined—Persist this group's layout locally under this key. Omit to keep the layout for the session only.
persistVersion?number | undefined—
storage?KeyValueStorage | undefined—
WorkspacePane props9 props

WorkspacePane props

Type: WorkspacePaneProps

Values the compiler reads from the declaration.

WorkspacePane props
PropTypeDefaultNotes
collapsedSize?string | number | undefined—
collapsible?boolean | undefined—Allow the pane to be dragged down to `collapsedSize`.
defaultSize?string | number | undefined—
hideOnStacked?boolean | undefined—Remove the pane instead of stacking it on a narrow viewport.
idstring—Required: pane ids key the saved layout.
maxSize?string | number | undefined—
minSize?string | number | undefined—
onSizeChange?((collapsed: boolean) => void) | undefined—Reports collapse crossing zero. Used by `InspectorPane`.
panelRef?Ref<PanelImperativeHandle | null> | undefined—Forwarded to the engine so a consumer can expand or collapse the pane.
WorkspacePaneBody props2 props

WorkspacePaneBody props

Type: WorkspacePaneBodyProps

Values the compiler reads from the declaration.

WorkspacePaneBody props
PropTypeDefaultNotes
ariaLabel?string | undefined—Accessible name for the scrollable region.
flush?boolean | undefined—Remove the padding for a pane that fills itself, e.g. a chart or a table.
WorkspacePaneHeader props6 props

WorkspacePaneHeader props

Type: WorkspacePaneHeaderProps

Values the compiler reads from the declaration.

WorkspacePaneHeader props
PropTypeDefaultNotes
actions?ReactNode—Trailing controls.
description?ReactNode—
icon?ReactNode—Leading marker, e.g. an icon. Decorative.
paneId?string | undefined—Adds a focus-mode toggle for this pane.
showReset?boolean | undefined—Adds a reset action when the group persists its layout.
titleReactNode—
WorkspaceResizeHandle props1 props

WorkspaceResizeHandle props

Type: WorkspaceResizeHandleProps

Values the compiler reads from the declaration.

WorkspaceResizeHandle props
PropTypeDefaultNotes
label?string | undefined—Accessible name; a separator without one is hard to use by voice.
InspectorRow props3 props

InspectorRow props

Type: InspectorRowProps

Values the compiler reads from the declaration.

InspectorRow props
PropTypeDefaultNotes
labelReactNode—
numeric?boolean | undefined—Use tabular figures for the value.
valueReactNode—
InspectorSection props1 props

InspectorSection props

Type: InspectorSectionProps

Values the compiler reads from the declaration.

InspectorSection props
PropTypeDefaultNotes
labelReactNode—
InspectorToggle props4 props

InspectorToggle props

Type: InspectorToggleProps

Values the compiler reads from the declaration.

InspectorToggle props
PropTypeDefaultNotes
className?string | undefined—
label?string | undefined—Accessible name. Defaults to open/close wording.
onOpenChange(open: boolean) => void—
openboolean—
Luc UI v1.0Workspacedark theme