A dockable panel layout system for building IDE-style UIs.
Download the tarball from the latest GitHub Release and install it:
npm install https://github.com/SoureCode/frame/releases/download/v0.1.0/sourecode-frame-0.1.0.tgzImport the stylesheet:
import'@sourecode/frame/styles';import{FrameLayout,LocalStorageAdapter,SlotName}from'@sourecode/frame';importtype{PanelConfig}from'@sourecode/frame';constpanels: PanelConfig[]=[{id: 'explorer',title: 'Explorer',slot: SlotName.LeftTop,pinned: true},{id: 'debug',title: 'Debug',slot: SlotName.LeftBottom,pinned: true},{id: 'outline',title: 'Outline',slot: SlotName.RightTop,pinned: false},];constlayout=newFrameLayout(document.getElementById('app')!,panels,{animated: true,storage: newLocalStorageAdapter('my-layout'),});| Parameter | Type | Description |
|---|---|---|
mount | HTMLElement | Element to render the layout into |
panels | PanelConfig[] | Panel definitions |
options | FrameOptions | Optional configuration |
| Property | Type | Description |
|---|---|---|
animated | boolean | Enable CSS transitions |
transition | TransitionConfig | Custom { duration, easing } |
storage | StorageAdapter | Persist layout state |
rails | Partial<Record<DockEdge, RailConfig>> | Per-rail configuration |
| Member | Description |
|---|---|
element | The root HTMLElement |
getStage() | Returns the central content area HTMLElement |
getState() | Returns the current LayoutState |
getTheme() | Returns the current Theme | string |
setTheme(theme) | Set theme by name (Theme or custom string) |
setWidescreen(enabled) | Toggle widescreen mode |
setAnimated(enabled) | Toggle animations at runtime |
openPanel(id) | Activate a panel |
closePanel(id) | Deactivate a panel |
toggleFullscreen(id) | Toggle a panel to fullscreen over the frame |
movePanel(id, slot) | Move a panel to a different SlotName |
disableRail(edge, autoMoveTarget?) | Disable a rail and its dock |
enableRail(edge) | Re-enable a disabled rail |
isRailDisabled(edge) | Check if a rail is disabled |
destroy() | Remove the layout from the DOM and clean up |
| Property | Type | Description |
|---|---|---|
id | string | Unique panel identifier |
title | string | Display title |
slot | SlotName | Initial slot position |
pinned | boolean | Keep panel open when dock is inactive |
fullscreenable | boolean | Show fullscreen button (default true) |
icon | PanelIcon | Optional icon (HTMLElement, SVG string, or factory) |
content | HTMLElement | Optional panel body element |
enumSlotName{LeftTop,LeftBottom,RightTop,RightBottom,TopLeft,TopRight,BottomLeft,BottomRight,}enumDockEdge{Left,Right,Top,Bottom,}| Property | Type | Description |
|---|---|---|
disabled | boolean | Disable this rail (default false) |
autoMoveTarget | DockEdge | Move panels to this edge when disabling |
Persists layout state to localStorage.
conststorage=newLocalStorageAdapter('storage-key');Implements StorageAdapter:
interfaceStorageAdapter{load(): LayoutState|null;save(state: LayoutState): void;}All events are CustomEvents dispatched on the frame element with bubbles: true.
| Event | Detail | Description |
|---|---|---|
frame:theme | { theme, previous } | Theme changed via setTheme() |
frame:fullscreen | { panelId, slot } | Panel fullscreen toggled |
frame:pin | { panelId, slot } | Panel pin toggled |
frame:close | { panelId, slot } | Panel closed |
frame:rail-click | { panelId, slot } | Rail icon clicked |
frame:rail-move | { panelId, toSlot, beforePanelId } | Panel moved via rail drag |
frame:splitter-change | { edge, ratio } | Splitter position changed |
frame:resizer-change | { edge, size } | Dock resized |
frame:rail-disabled | { edge, disabled } | Rail enabled or disabled |
frame:overlay-close | { edge } | Click outside unpinned dock |
Set data-theme on the mount element or use setTheme() / getTheme():
layout.setTheme('dracula');layout.element.addEventListener('frame:theme',(e)=>{console.log(e.detail.previous,'->',e.detail.theme);});Available themes:
obsidian(default; omitdata-themeor set it to empty)lightsolarizedrosepaperhigh-contrastwarmnordterminaldraculamonokaiglass-darkglass-lightcatppuccingruvboxtokyo-nightsynthwaveeverforestsepiagithub-lightgithub-darkgithub-dimmedayumintlavenderskysand