Comprehensive UI widget toolkit for building desktop-like web applications with layouts, panels, tabs, menus, and other interactive components
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Panel widgets combine layout managers with widget collections to provide common UI patterns. These high-level containers handle both the arrangement and management of child widgets, offering complete solutions for building complex user interfaces with tabs, splits, docking, accordions, and other organizational patterns.
The base panel class that provides a foundation for all other panel widgets.
/**
* A simple widget that acts as a base class for other panels.
* Provides basic child widget management with a customizable layout.
*/
class Panel extends Widget {
/**
* Construct a new panel.
* @param options - The options for initializing the panel
*/
constructor(options?: Panel.IOptions);
/** The child widgets in the panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** Add a child widget to the end of the panel */
addWidget(widget: Widget): void;
/** Insert a child widget at the specified index */
insertWidget(index: number, widget: Widget): void;
}
namespace Panel {
/**
* Options for initializing a panel.
*/
interface IOptions extends Widget.IOptions {
/** A custom layout for the panel (default: PanelLayout) */
layout?: PanelLayout;
}
}A panel that arranges child widgets in a single row or column with flexible sizing.
/**
* A panel that arranges widgets in a single row or column.
* Combines the BoxLayout with Panel for easy linear arrangements.
*/
class BoxPanel extends Panel {
/**
* Construct a new box panel.
* @param options - The options for initializing the box panel
*/
constructor(options?: BoxPanel.IOptions);
/** The layout direction for the box panel */
direction: BoxPanel.Direction;
/** The content alignment for the box panel */
alignment: BoxPanel.Alignment;
/** The inter-element spacing for the box panel */
spacing: number;
/** The child widgets in the panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** Add a child widget to the end of the panel */
addWidget(widget: Widget): void;
/** Insert a child widget at the specified index */
insertWidget(index: number, widget: Widget): void;
}
namespace BoxPanel {
/**
* Options for initializing a box panel.
*/
interface IOptions extends Panel.IOptions {
/** The layout direction (default: 'top-to-bottom') */
direction?: Direction;
/** The content alignment (default: 'start') */
alignment?: Alignment;
/** The inter-element spacing (default: 4) */
spacing?: number;
/** A custom box layout for the panel */
layout?: BoxLayout;
}
/** Type alias for box layout directions */
type Direction = BoxLayout.Direction;
/** Type alias for box layout alignments */
type Alignment = BoxLayout.Alignment;
}
/**
* Functions for managing box panel widget properties.
*/
namespace BoxPanel {
/**
* Get the size basis for a widget in a box panel.
* @param widget - The widget of interest
* @returns The size basis for the widget
*/
function getSizeBasis(widget: Widget): number;
/**
* Set the size basis for a widget in a box panel.
* @param widget - The widget of interest
* @param value - The value for the size basis
*/
function setSizeBasis(widget: Widget, value: number): void;
/**
* Get the stretch factor for a widget in a box panel.
* @param widget - The widget of interest
* @returns The stretch factor for the widget
*/
function getStretch(widget: Widget): number;
/**
* Set the stretch factor for a widget in a box panel.
* @param widget - The widget of interest
* @param value - The value for the stretch factor
*/
function setStretch(widget: Widget, value: number): void;
}Usage Examples:
import { Widget, BoxPanel } from "@lumino/widgets";
// Create horizontal toolbar
const toolbar = new BoxPanel({
direction: 'left-to-right',
spacing: 4
});
const button1 = new Widget();
const button2 = new Widget();
const spacer = new Widget();
toolbar.addWidget(button1);
toolbar.addWidget(spacer);
toolbar.addWidget(button2);
// Make spacer flexible to push button2 to the right
BoxPanel.setStretch(button1, 0);
BoxPanel.setStretch(spacer, 1);
BoxPanel.setStretch(button2, 0);A panel that arranges widgets into resizable sections with split handles.
/**
* A panel that arranges widgets into resizable sections.
* Provides user-resizable panes with interactive split handles.
*/
class SplitPanel extends Panel {
/**
* Construct a new split panel.
* @param options - The options for initializing the split panel
*/
constructor(options?: SplitPanel.IOptions);
/** The orientation of the split panel */
orientation: SplitPanel.Orientation;
/** The content alignment for the split panel */
alignment: SplitPanel.Alignment;
/** The inter-element spacing for the split panel */
spacing: number;
/** The renderer for the split panel (read-only) */
readonly renderer: SplitPanel.IRenderer;
/** The split handles managed by the panel (read-only) */
readonly handles: ReadonlyArray<HTMLDivElement>;
/** A signal emitted when a split handle is moved */
readonly handleMoved: ISignal<this, void>;
/** Dispose of the panel and its resources */
dispose(): void;
/** Get the relative sizes of the widgets in the panel */
relativeSizes(): number[];
/**
* Set the relative sizes for the widgets in the panel.
* @param sizes - The relative sizes for the widgets
* @param update - Whether to update the layout immediately
*/
setRelativeSizes(sizes: number[], update?: boolean): void;
/** Handle DOM events for the panel */
handleEvent(event: Event): void;
/** Release the mouse grab for the split handles */
releaseMouse(): void;
}
namespace SplitPanel {
/**
* Options for initializing a split panel.
*/
interface IOptions extends Panel.IOptions {
/** The renderer for creating split handles */
renderer?: IRenderer;
/** The orientation of the split panel (default: 'horizontal') */
orientation?: Orientation;
/** The content alignment (default: 'start') */
alignment?: Alignment;
/** The inter-element spacing (default: 4) */
spacing?: number;
/** A custom split layout for the panel */
layout?: SplitLayout;
}
/** Type alias for split layout orientations */
type Orientation = SplitLayout.Orientation;
/** Type alias for split layout alignments */
type Alignment = SplitLayout.Alignment;
/** Type alias for split layout renderer interface */
type IRenderer = SplitLayout.IRenderer;
/**
* Default renderer implementation for split panels.
*/
class Renderer implements IRenderer {
/**
* Create a new split handle for use by a split panel.
* @returns A new split handle element
*/
createHandle(): HTMLDivElement;
}
}
/**
* Functions for managing split panel widget properties.
*/
namespace SplitPanel {
/**
* Get the stretch factor for a widget in a split panel.
* @param widget - The widget of interest
* @returns The stretch factor for the widget
*/
function getStretch(widget: Widget): number;
/**
* Set the stretch factor for a widget in a split panel.
* @param widget - The widget of interest
* @param value - The value for the stretch factor
*/
function setStretch(widget: Widget, value: number): void;
}Usage Examples:
import { Widget, SplitPanel } from "@lumino/widgets";
// Create vertical split panel
const splitPanel = new SplitPanel({
orientation: 'vertical',
spacing: 1
});
const topPane = new Widget();
const bottomPane = new Widget();
splitPanel.addWidget(topPane);
splitPanel.addWidget(bottomPane);
// Set initial sizes (60% top, 40% bottom)
splitPanel.setRelativeSizes([0.6, 0.4]);
// Listen for handle moves
splitPanel.handleMoved.connect(() => {
console.log('Split sizes changed:', splitPanel.relativeSizes());
});A panel that shows only one child widget at a time from a stack.
/**
* A panel that shows only one of its child widgets at a time.
* Provides navigation between multiple content areas.
*/
class StackedPanel extends Panel {
/**
* Construct a new stacked panel.
* @param options - The options for initializing the stacked panel
*/
constructor(options?: StackedPanel.IOptions);
/** The index of the current widget, or -1 if no widget is current */
currentIndex: number;
/** The current widget, or null if no widget is current */
currentWidget: Widget | null;
/** The child widgets in the panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** The method for hiding inactive widgets */
hiddenMode: Widget.HiddenMode;
/** A signal emitted when the current widget changes */
readonly currentChanged: ISignal<this, StackedPanel.ICurrentChangedArgs>;
/** A signal emitted when a widget is removed from the panel */
readonly widgetRemoved: ISignal<this, Widget>;
/** Add a child widget to the end of the panel */
addWidget(widget: Widget): void;
/** Insert a child widget at the specified index */
insertWidget(index: number, widget: Widget): void;
}
namespace StackedPanel {
/**
* Options for initializing a stacked panel.
*/
interface IOptions extends Panel.IOptions {
/** A custom stacked layout for the panel */
layout?: StackedLayout;
}
/**
* The arguments for the current changed signal.
*/
interface ICurrentChangedArgs {
/** The previous index, or -1 if no previous widget */
previousIndex: number;
/** The previous widget, or null if no previous widget */
previousWidget: Widget | null;
/** The current index, or -1 if no current widget */
currentIndex: number;
/** The current widget, or null if no current widget */
currentWidget: Widget | null;
}
}Usage Examples:
import { Widget, StackedPanel } from "@lumino/widgets";
// Create stacked panel for multi-page content
const stackedPanel = new StackedPanel();
const welcomePage = new Widget();
const settingsPage = new Widget();
const aboutPage = new Widget();
stackedPanel.addWidget(welcomePage); // Index 0, becomes current
stackedPanel.addWidget(settingsPage); // Index 1, hidden
stackedPanel.addWidget(aboutPage); // Index 2, hidden
// Switch to settings page
stackedPanel.currentIndex = 1;
// Listen for page changes
stackedPanel.currentChanged.connect((sender, args) => {
console.log(`Switched from page ${args.previousIndex} to ${args.currentIndex}`);
});A panel that arranges widgets as collapsible accordion sections.
/**
* A panel that arranges widgets as collapsible accordion sections.
* Each widget gets a title bar that can be clicked to expand/collapse the section.
*/
class AccordionPanel extends Panel {
/**
* Construct a new accordion panel.
* @param options - The options for initializing the accordion panel
*/
constructor(options?: AccordionPanel.IOptions);
/** The renderer for the accordion panel (read-only) */
readonly renderer: AccordionPanel.IRenderer;
/** The accordion section titles (read-only) */
readonly titles: ReadonlyArray<Title<Widget>>;
/** The orientation of the accordion panel */
orientation: AccordionPanel.Orientation;
/** The spacing between accordion sections */
spacing: number;
/** The space allocated for section titles */
titleSpace: number;
/** The child widgets in the panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** Add a child widget to the end of the panel */
addWidget(widget: Widget): void;
/** Insert a child widget at the specified index */
insertWidget(index: number, widget: Widget): void;
/**
* Collapse an accordion section.
* @param widget - The widget to collapse
* @returns Whether the operation was successful
*/
collapse(widget: Widget): boolean;
/**
* Expand an accordion section.
* @param widget - The widget to expand
* @returns Whether the operation was successful
*/
expand(widget: Widget): boolean;
/**
* Test whether an accordion section is expanded.
* @param widget - The widget of interest
* @returns Whether the section is expanded
*/
isExpanded(widget: Widget): boolean;
}
namespace AccordionPanel {
/**
* Options for initializing an accordion panel.
*/
interface IOptions extends Panel.IOptions {
/** The renderer for creating accordion elements */
renderer?: IRenderer;
/** The orientation of the accordion (default: 'vertical') */
orientation?: Orientation;
/** The spacing between sections (default: 4) */
spacing?: number;
/** The space allocated for titles (default: 22) */
titleSpace?: number;
/** A custom accordion layout for the panel */
layout?: AccordionLayout;
}
/** Type alias for accordion orientations */
type Orientation = AccordionLayout.Orientation;
/** Type alias for accordion renderer interface */
type IRenderer = AccordionLayout.IRenderer;
/**
* Default renderer implementation for accordion panels.
*/
class Renderer implements IRenderer {
/**
* Create a section title element for an accordion.
* @param data - The render data for the section
* @returns The section title element
*/
createSectionTitle(data: AccordionLayout.IRenderData<Widget>): HTMLElement;
}
}
/**
* Functions for managing accordion expansion state.
*/
namespace AccordionPanel {
/**
* Get the expanded state for a widget in an accordion panel.
* @param widget - The widget of interest
* @returns Whether the widget is expanded
*/
function getExpanded(widget: Widget): boolean;
/**
* Set the expanded state for a widget in an accordion panel.
* @param widget - The widget of interest
* @param value - Whether the widget should be expanded
*/
function setExpanded(widget: Widget, value: boolean): void;
}Usage Examples:
import { Widget, AccordionPanel } from "@lumino/widgets";
// Create accordion panel
const accordion = new AccordionPanel({
orientation: 'vertical',
titleSpace: 30
});
// Create sections with titles
const generalSection = new Widget();
generalSection.title.label = 'General Settings';
generalSection.title.iconClass = 'fa fa-cog';
const advancedSection = new Widget();
advancedSection.title.label = 'Advanced Settings';
advancedSection.title.iconClass = 'fa fa-wrench';
accordion.addWidget(generalSection);
accordion.addWidget(advancedSection);
// Control expansion
accordion.expand(generalSection); // Expand first section
accordion.collapse(advancedSection); // Collapse second section
// Check state
console.log('General expanded:', accordion.isExpanded(generalSection));A sophisticated panel that provides a flexible docking interface for complex layouts.
/**
* A panel that arranges widgets in a flexible docking interface.
* Supports tabbed interfaces, split panes, and drag-and-drop widget management.
*/
class DockPanel extends Panel {
/**
* Construct a new dock panel.
* @param options - The options for initializing the dock panel
*/
constructor(options?: DockPanel.IOptions);
/** The renderer for the dock panel (read-only) */
readonly renderer: DockPanel.IRenderer;
/** The inter-element spacing for the dock panel */
spacing: number;
/** The mode for the dock panel */
mode: DockPanel.Mode;
/** Whether the tabs are movable by the user */
tabsMovable: boolean;
/** Whether the tabs are constrained to their source dock area */
tabsConstrained: boolean;
/** Whether the add button is enabled for the dock panel */
addButtonEnabled: boolean;
/** Whether the dock panel is empty (read-only) */
readonly isEmpty: boolean;
/** The widgets in the dock panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** The selected widgets in the dock panel (read-only) */
readonly selectedWidgets: ReadonlyArray<Widget>;
/** The tab bars in the dock panel (read-only) */
readonly tabBars: ReadonlyArray<TabBar<Widget>>;
/** The split handles in the dock panel (read-only) */
readonly handles: ReadonlyArray<HTMLDivElement>;
/** The overlay for the dock panel (read-only) */
readonly overlay: DockPanel.IOverlay;
/** A signal emitted when the layout configuration changes */
readonly layoutModified: ISignal<this, void>;
/** A signal emitted when the add button is clicked */
readonly addRequested: ISignal<this, TabBar<Widget>>;
/** Save the current layout configuration */
saveLayout(): DockPanel.ILayoutConfig;
/**
* Restore a previously saved layout configuration.
* @param config - The layout configuration to restore
*/
restoreLayout(config: DockPanel.ILayoutConfig): void;
/**
* Add a widget to the dock panel.
* @param widget - The widget to add
* @param options - The options for adding the widget
*/
addWidget(widget: Widget, options?: DockPanel.IAddOptions): void;
/**
* Activate a widget in the dock panel.
* @param widget - The widget to activate
*/
activateWidget(widget: Widget): void;
/**
* Select a widget in the dock panel.
* @param widget - The widget to select
*/
selectWidget(widget: Widget): void;
/** Handle DOM events for the dock panel */
handleEvent(event: Event): void;
}
namespace DockPanel {
/**
* Options for initializing a dock panel.
*/
interface IOptions extends Panel.IOptions {
/** The renderer for creating dock panel elements */
renderer?: IRenderer;
/** The spacing between dock elements (default: 4) */
spacing?: number;
/** The mode for the dock panel (default: 'multiple-document') */
mode?: Mode;
/** Whether tabs are movable (default: true) */
tabsMovable?: boolean;
/** Whether tabs are constrained (default: false) */
tabsConstrained?: boolean;
/** Whether add button is enabled (default: false) */
addButtonEnabled?: boolean;
}
/**
* The available modes for a dock panel.
*/
enum Mode {
/** Multiple document interface mode */
'multiple-document',
/** Single document interface mode */
'single-document'
}
/** Type alias for dock layout renderer interface */
type IRenderer = DockLayout.IRenderer;
/** Type alias for dock layout add options */
type IAddOptions = DockLayout.IAddOptions;
/** Type alias for dock layout configuration */
type ILayoutConfig = DockLayout.ILayoutConfig;
/**
* An object which provides overlay functionality for dock panels.
*/
interface IOverlay {
/** The DOM node for the overlay */
readonly node: HTMLDivElement;
/** Show the overlay with the specified geometry */
show(geo: IOverlayGeometry): void;
/** Hide the overlay after the specified delay */
hide(delay: number): void;
}
/**
* An object which describes overlay geometry.
*/
interface IOverlayGeometry {
/** The top coordinate in pixels */
top: number;
/** The left coordinate in pixels */
left: number;
/** The width in pixels */
width: number;
/** The height in pixels */
height: number;
}
}
/**
* Functions for managing dock panel tab behavior.
*/
namespace DockPanel {
/**
* Get the tabs movable state for a widget in a dock panel.
* @param widget - The widget of interest
* @returns Whether the widget's tab is movable
*/
function getTabsMovable(widget: Widget): boolean;
/**
* Set the tabs movable state for a widget in a dock panel.
* @param widget - The widget of interest
* @param value - Whether the widget's tab should be movable
*/
function setTabsMovable(widget: Widget, value: boolean): void;
}Usage Examples:
import { Widget, DockPanel } from "@lumino/widgets";
// Create dock panel
const dockPanel = new DockPanel({
mode: DockPanel.Mode['multiple-document'],
spacing: 4
});
// Create widgets to dock
const editor1 = new Widget();
editor1.title.label = 'File 1';
editor1.title.closable = true;
const editor2 = new Widget();
editor2.title.label = 'File 2';
editor2.title.closable = true;
const sidebar = new Widget();
sidebar.title.label = 'Explorer';
// Add widgets with different docking modes
dockPanel.addWidget(editor1); // First widget goes to main area
dockPanel.addWidget(editor2, { mode: 'tab-after', ref: editor1 }); // Tab with editor1
dockPanel.addWidget(sidebar, { mode: 'split-left', ref: editor1 }); // Split to left
// Save and restore layout
const config = dockPanel.saveLayout();
// ... later ...
dockPanel.restoreLayout(config);
// Listen for layout changes
dockPanel.layoutModified.connect(() => {
console.log('Dock layout modified');
});A panel that combines a tab bar with a stacked panel for tabbed interface.
/**
* A widget that combines a TabBar and a StackedPanel.
* Provides a complete tabbed interface with tab navigation and content areas.
*/
class TabPanel extends Panel {
/**
* Construct a new tab panel.
* @param options - The options for initializing the tab panel
*/
constructor(options?: TabPanel.IOptions);
/** The index of the current widget, or -1 if no widget is current */
currentIndex: number;
/** The current widget, or null if no widget is current */
readonly currentWidget: Widget | null;
/** Whether the tabs are movable by the user */
tabsMovable: boolean;
/** Whether the add button is enabled for the tab bar */
addButtonEnabled: boolean;
/** The placement of the tab bar relative to the content */
tabPlacement: TabPanel.TabPlacement;
/** The tab bar for the panel (read-only) */
readonly tabBar: TabBar<Widget>;
/** The stacked panel for the content (read-only) */
readonly stackedPanel: StackedPanel;
/** The widgets in the panel (read-only) */
readonly widgets: ReadonlyArray<Widget>;
/** A signal emitted when the current widget changes */
readonly currentChanged: ISignal<this, TabPanel.ICurrentChangedArgs>;
/** A signal emitted when the add button is clicked */
readonly addRequested: ISignal<this, TabBar<Widget>>;
/** Add a child widget to the end of the panel */
addWidget(widget: Widget): void;
/** Insert a child widget at the specified index */
insertWidget(index: number, widget: Widget): void;
}
namespace TabPanel {
/**
* Options for initializing a tab panel.
*/
interface IOptions extends Panel.IOptions {
/** The document context for the tab panel */
document?: Document | ShadowRoot;
/** Whether tabs are movable (default: false) */
tabsMovable?: boolean;
/** Whether add button is enabled (default: false) */
addButtonEnabled?: boolean;
/** The tab placement (default: 'top') */
tabPlacement?: TabPlacement;
/** The renderer for creating tab elements */
renderer?: TabBar.IRenderer<Widget>;
}
/**
* The available tab placements for a tab panel.
*/
type TabPlacement = 'top' | 'left' | 'right' | 'bottom';
/**
* The arguments for the current changed signal.
*/
interface ICurrentChangedArgs {
/** The previous index, or -1 if no previous widget */
previousIndex: number;
/** The previous widget, or null if no previous widget */
previousWidget: Widget | null;
/** The current index, or -1 if no current widget */
currentIndex: number;
/** The current widget, or null if no current widget */
currentWidget: Widget | null;
}
}Usage Examples:
import { Widget, TabPanel } from "@lumino/widgets";
// Create tab panel
const tabPanel = new TabPanel({
tabPlacement: 'top',
tabsMovable: true,
addButtonEnabled: true
});
// Add tabs
const tab1 = new Widget();
tab1.title.label = 'Welcome';
tab1.title.iconClass = 'fa fa-home';
const tab2 = new Widget();
tab2.title.label = 'Settings';
tab2.title.closable = true;
tabPanel.addWidget(tab1);
tabPanel.addWidget(tab2);
// Switch tabs programmatically
tabPanel.currentIndex = 1;
// Listen for tab changes
tabPanel.currentChanged.connect((sender, args) => {
console.log(`Switched to tab: ${args.currentWidget?.title.label}`);
});
// Handle add button clicks
tabPanel.addRequested.connect(() => {
const newTab = new Widget();
newTab.title.label = `Tab ${tabPanel.widgets.length + 1}`;
tabPanel.addWidget(newTab);
});