SplitterWidget
A resizable splitter that divides the available space into two panes, either horizontally (left/right) or vertically (top/bottom).
The splitter widget is perfect for creating multi-pane layouts like editor interfaces, file browsers with preview panes, or terminal applications with side panels. Users can resize panes using keyboard navigation or mouse dragging.
Basic Usage
Create a horizontal splitter using the HSplitter extension method:
dotnet runThe splitter displays a visual divider (│ for horizontal, ─ for vertical) between the two panes. Each pane's content is automatically clipped to its allocated space.
Navigation
- Tab to focus the splitter divider
- ←→ arrows to resize horizontal splitters
- ↑↓ arrows to resize vertical splitters
- Mouse drag on the divider to resize (when mouse support is enabled)
Vertical Splitter
Use VSplitter to create a vertical split with top and bottom panes:
dotnet runNested Splitters
Splitters can be nested to create complex multi-pane layouts:
dotnet runYou can nest splitters in any combination:
- Horizontal inside vertical (editor layout with sidebar)
- Vertical inside horizontal (file tree + editor + terminal)
- Multiple levels deep for quad-split layouts
Resizing Behavior
Keyboard Resizing
When the splitter divider is focused:
| Key | Action (Horizontal) | Action (Vertical) |
|---|---|---|
| ← | Decrease first pane width | (not used) |
| → | Increase first pane width | (not used) |
| ↑ | (not used) | Decrease first pane height |
| ↓ | (not used) | Increase first pane height |
The default resize step is 2 characters. Resizing respects minimum pane sizes to prevent either pane from becoming unusable.
Mouse Resizing
Click and drag the divider to resize panes interactively. The divider area has a hit test zone that captures mouse events only on the divider itself, allowing clicks through to child widgets.
Initial Size and Constraints
Set the initial size of the first pane using constructor parameters:
// Horizontal: leftWidth parameter (default: 30)
ctx.HSplitter(leftPane, rightPane, leftWidth: 40)
// Vertical: topHeight parameter (default: 10)
ctx.VSplitter(topPane, bottomPane, topHeight: 8)2
3
4
5
The splitter maintains minimum sizes for both panes to ensure usability. The second pane automatically takes the remaining space.
State Preservation
After a user resizes a splitter, the widget preserves the new size across re-renders through reconciliation. Setting firstSize in the widget only affects the initial creation—manual resizing takes precedence.
Focus Navigation
The splitter participates in the focus system:
- Tab navigation: Tab moves focus through the first pane's widgets, then to the splitter divider, then through the second pane's widgets
- Splitter focus: When the divider is focused, arrow keys resize the panes
- Escape to first: Press Escape while focused on the divider to jump to the first focusable widget
Focus indicators:
- Unfocused divider: displays in the theme's divider color
- Focused divider: inverts colors (divider color becomes background, contrasting foreground)
Extension Methods
The splitter widget provides several convenience extension methods:
HSplitter (Horizontal)
// Basic horizontal split
ctx.HSplitter(leftWidget, rightWidget, leftWidth: 30)
// With callbacks for VStack children
ctx.HSplitter(
left => [
left.Text("Item 1"),
left.Text("Item 2")
],
right => [
right.Text("Content")
],
leftWidth: 25
)2
3
4
5
6
7
8
9
10
11
12
13
14
VSplitter (Vertical)
// Basic vertical split
ctx.VSplitter(topWidget, bottomWidget, topHeight: 10)
// With callbacks for VStack children
ctx.VSplitter(
top => [
top.Text("Header")
],
bottom => [
bottom.Text("Content")
],
topHeight: 3
)2
3
4
5
6
7
8
9
10
11
12
13
Theming
Customize the splitter appearance using theme elements:
var theme = Hex1bTheme.Create()
.Set(SplitterTheme.DividerColor, Hex1bColor.Cyan)
.Set(SplitterTheme.DividerCharacter, "┃")
.Set(SplitterTheme.LeftArrowCharacter, "◀")
.Set(SplitterTheme.RightArrowCharacter, "▶");
await using var terminal = Hex1bTerminal.CreateBuilder()
.WithHex1bApp((app, options) =>
{
options.Theme = theme;
return ctx => /* ... */;
})
.Build();
await terminal.RunAsync();2
3
4
5
6
7
8
9
10
11
12
13
14
15
Available Theme Elements
| Element | Type | Default | Description |
|---|---|---|---|
DividerColor | Hex1bColor | Gray | Color of the divider line |
DividerCharacter | string | "│" | Character for horizontal divider |
HorizontalDividerCharacter | string | "─" | Character for vertical divider |
LeftArrowCharacter | string | "◀" | Left arrow hint (horizontal) |
RightArrowCharacter | string | "▶" | Right arrow hint (horizontal) |
UpArrowCharacter | string | "▲" | Up arrow hint (vertical) |
DownArrowCharacter | string | "▼" | Down arrow hint (vertical) |
LeftArrowColor | Hex1bColor | Default (falls back to divider color at render) | Color for left arrow |
RightArrowColor | Hex1bColor | Default (falls back to divider color at render) | Color for right arrow |
UpArrowColor | Hex1bColor | Default (falls back to divider color at render) | Color for up arrow |
DownArrowColor | Hex1bColor | Default (falls back to divider color at render) | Color for down arrow |
Arrow hints are displayed at the center of the divider when the splitter is tall/wide enough, indicating the resize direction.
Common Use Cases
Editor with Sidebar
ctx.HSplitter(
ctx.Panel(left => [
left.VStack(v => [
v.Text("Files"),
v.List(fileList).Fill()
])
]),
ctx.Panel(right => [
right.VStack(v => [
v.Text("Editor"),
v.TextBox(editorState).Fill()
])
]),
leftWidth: 30
)2
3
4
5
6
7
8
9
10
11
12
13
14
15
Terminal with Output Panel
ctx.VSplitter(
ctx.Panel(top => [
top.Text("Main Content").Fill()
]),
ctx.Panel(bottom => [
bottom.VStack(v => [
v.Text("Output"),
v.Scroll(s => [
s.Text(outputLog)
])
])
]),
topHeight: 20
)2
3
4
5
6
7
8
9
10
11
12
13
14
Quad Layout (IDE-style)
ctx.VSplitter(
ctx.HSplitter(explorerPane, editorPane, leftWidth: 25),
ctx.HSplitter(terminalPane, outputPane, leftWidth: 25),
topHeight: 20
)2
3
4
5
Related Widgets
- VStackWidget - Vertical layout without resizing
- HStackWidget - Horizontal layout without resizing
- BorderWidget - Add borders around splitter panes
- PanelWidget - Add padding to splitter content