@sqlrooms/layout
Layout slice and renderer for SQLRooms panel-based UIs.
This package renders layout trees using react-resizable-panels for split layouts, dnd-kit for dockable panel rearrangement, and react-grid-layout for scrollable grid dashboard layouts.
Installation
bash
npm install @sqlrooms/layoutMain exports
createLayoutSlice(),useStoreWithLayout()LayoutRenderercomponent — renders aLayoutNodetree using resizable panels, tabs, and generic dockinguseExpandGridPanel()— expands a grid child panel horizontally to available row space- Grid layout defaults/helpers:
DEFAULT_GRID_COLS,DEFAULT_GRID_BREAKPOINTS,getResponsiveGridCols(),getGridColsForBreakpoint() - Layout helpers:
visitLayoutLeafNodesgetVisibleLayoutPanelsremoveLayoutNodeByKeyfindNodeById,findTabsNodeForPanelmovePanel
- Layout config schemas/types re-exported from
@sqlrooms/layout-config
Store usage
tsx
import {LayoutSliceState, createLayoutSlice} from '@sqlrooms/layout';
import {
BaseRoomStoreState,
createBaseRoomSlice,
createRoomStore,
} from '@sqlrooms/room-store';
function DataPanel() {
return <div>Data</div>;
}
function MainPanel() {
return <div>Main</div>;
}
type State = BaseRoomStoreState & LayoutSliceState;
export const {roomStore, useRoomStore} = createRoomStore<State>(
(set, get, store) => ({
...createBaseRoomSlice()(set, get, store),
...createLayoutSlice({
config: {
type: 'split',
direction: 'row',
children: [
{type: 'panel', id: 'data', defaultSize: '30%'},
{type: 'panel', id: 'main', defaultSize: '70%'},
],
},
panels: {
data: {
title: 'Data',
component: DataPanel,
},
main: {
title: 'Main',
component: MainPanel,
},
},
})(set, get, store),
}),
);Render callbacks
createLayoutSlice accepts optional render callbacks for custom panel and tab strip rendering:
ts
createLayoutSlice({
config: {
/* ... */
},
panels: {
/* ... */
},
renderPanel: (context) => {
// Return custom JSX or undefined to fall back to the default renderer
},
});Tabs layout composition
TabsLayout.TabContent accepts forceMount to keep all visible tab contents mounted while hiding inactive tabs. This is useful for expensive panels that should preserve local state or setup work during tab changes:
tsx
<TabsLayout.TabContentContainer>
<TabsLayout.TabContent forceMount />
</TabsLayout.TabContentContainer>Area-based panel management
Named tabs nodes (with an id) act as areas that can be managed programmatically:
tsx
import {Button} from '@sqlrooms/ui';
function PanelButtons() {
const setActiveTab = useRoomStore((state) => state.layout.setActiveTab);
const addTab = useRoomStore((state) => state.layout.addTab);
const setCollapsed = useRoomStore((state) => state.layout.setCollapsed);
return (
<div className="flex gap-2">
<Button onClick={() => setActiveTab('sidebar', 'data')}>
Show Data Panel
</Button>
<Button onClick={() => addTab('sidebar', 'schema')}>
Add Schema Tab
</Button>
<Button onClick={() => setCollapsed('sidebar', true)}>
Collapse Sidebar
</Button>
</div>
);
}Note
@sqlrooms/layout (panel layout system) is different from @sqlrooms/mosaic (UW IDL data visualization package).
Interfaces
Type Aliases
- LayoutNodeContextTabs
- LayoutNodeContextSplit
- LayoutNodeContextDock
- LayoutNodeContextGrid
- LayoutNodeContextPanel
- LayoutNodeContextLeaf
- LayoutNodeContextValue
- LayoutRendererProps
- DockDirection
- DockAxis
- ParentDirection
- LayoutSliceConfig
- LayoutSliceConfig
- LayoutSliceState
- CreateLayoutSliceProps
- PanelIdentityResult
- LayoutPath
- PanelContainerType
- RoomPanelComponent
- RoomPanelInfo
- PanelDefinitionContext
- PanelDefinition
- Panels
- LayoutNodeKey
- LayoutPanelNode
- LayoutSplitNode
- LayoutTabsNode
- LayoutDockNode
- LayoutGridItem
- LayoutGridNode
- LayoutNode
- LayoutConfig
- LayoutDirection
- LayoutDirection
Variables
- LayoutNodeProvider
- LayoutRenderer
- RoomDndProvider
- DEFAULT_GRID_BREAKPOINTS
- DEFAULT_GRID_COLS
- DockLayout
- GridLayout
- LeafLayout
- SplitLayout
- TabsLayout
- MAIN_VIEW
- LayoutNodeKey
- LayoutPanelNode
- LayoutSplitNode
- LayoutTabsNode
- LayoutDockNode
- LayoutGridNode
- LayoutNode
- LayoutConfig
Functions
- useLayoutNodeContext
- useTabsNodeContext
- useSplitNodeContext
- useDockNodeContext
- useGridNodeContext
- getLayoutNodeContextValue
- createDefaultLayoutConfig
- createLayoutSlice
- useStoreWithLayout
- movePanel
- getGridColsForBreakpoint
- getResponsiveGridCols
- createLayoutId
- visitLayoutLeafNodes
- getVisibleLayoutPanels
- findNodeById
- findTabsNodeForPanel
- findNearestDockAncestor
- isDockablePanel
- removeLayoutNodeByKey
- useLeafLayoutPanelDraggable
- useExpandGridPanel
- resolvePanelDefinition
- resolvePanelIdentity
- useGetPanel
- isLayoutNodeKey
- isLayoutPanelNode
- isLayoutSplitNode
- isLayoutTabsNode
- isLayoutDockNode
- isLayoutGridNode
- createDefaultLayout
- getLayoutNodeId
- getChildrenIds
- getVisibleTabChildren
- getHiddenTabChildren
