TermUI.Widgets.SplitPane (TermUI v0.2.0)

View Source

SplitPane widget for resizable multi-pane layouts.

SplitPane divides space between two or more panes with draggable dividers, enabling complex layouts like IDE editors with sidebars and bottom panels.

Usage

SplitPane.new(
  orientation: :horizontal,
  panes: [
    %{id: :left, content: sidebar(), size: 0.25, min_size: 10},
    %{id: :right, content: main_content(), size: 0.75}
  ]
)

Features

  • Horizontal and vertical split orientations
  • Draggable dividers (keyboard and mouse)
  • Min/max size constraints per pane
  • Collapsible panes
  • Nested splits for complex layouts
  • Layout state persistence

Keyboard Controls

  • Tab: Move focus between dividers
  • Left/Up: Move divider left/up (decrease pane before)
  • Right/Down: Move divider right/down (increase pane before)
  • Shift+Left/Up: Move divider by larger step
  • Shift+Right/Down: Move divider by larger step
  • Enter: Toggle collapse of pane after divider
  • Home: Move divider to minimum position
  • End: Move divider to maximum position

Summary

Functions

Collapses a pane by ID.

Expands a collapsed pane by ID.

Gets the focused divider index (0-indexed), or nil if none focused.

Gets the current layout state for persistence.

Gets a list of pane IDs.

Creates new SplitPane widget props.

Creates a pane specification.

Updates content of a pane by ID.

Restores layout from a saved state.

Sets the size of a pane by ID.

Toggles collapse state of a pane by ID.

Types

orientation()

@type orientation() :: :horizontal | :vertical

pane()

@type pane() :: %{
  id: term(),
  content: term(),
  size: number(),
  min_size: non_neg_integer() | nil,
  max_size: non_neg_integer() | nil,
  collapsed: boolean(),
  computed_size: non_neg_integer()
}

pane_spec()

@type pane_spec() :: %{
  id: term(),
  content: term(),
  size: number(),
  min_size: non_neg_integer() | nil,
  max_size: non_neg_integer() | nil,
  collapsed: boolean()
}

Functions

collapse(state, pane_id)

@spec collapse(map(), term()) :: map()

Collapses a pane by ID.

expand(state, pane_id)

@spec expand(map(), term()) :: map()

Expands a collapsed pane by ID.

get_focused_divider(state)

@spec get_focused_divider(map()) :: non_neg_integer() | nil

Gets the focused divider index (0-indexed), or nil if none focused.

get_layout(state)

@spec get_layout(map()) :: map()

Gets the current layout state for persistence.

Returns a map of pane IDs to their sizes and collapsed states.

get_pane_ids(state)

@spec get_pane_ids(map()) :: [term()]

Gets a list of pane IDs.

new(opts)

@spec new(keyword()) :: map()

Creates new SplitPane widget props.

Options

  • :orientation - :horizontal (side by side) or :vertical (stacked) (default: :horizontal)
  • :panes - List of pane specifications (required)
  • :divider_size - Divider thickness in characters (default: 1)
  • :divider_style - Style for dividers
  • :focused_divider_style - Style for focused divider
  • :resizable - Whether dividers can be dragged (default: true)
  • :on_resize - Callback when panes are resized: fn panes -> ... end
  • :on_collapse - Callback when pane is collapsed/expanded: fn {id, collapsed} -> ... end
  • :persist_key - Key for layout persistence (optional)

pane(id, content, opts \\ [])

@spec pane(term(), term(), keyword()) :: pane_spec()

Creates a pane specification.

Options

  • :size - Size as float (0.0-1.0 proportion) or integer (fixed chars/lines)
  • :min_size - Minimum size in characters/lines
  • :max_size - Maximum size in characters/lines
  • :collapsed - Whether pane starts collapsed (default: false)

set_content(state, pane_id, content)

@spec set_content(map(), term(), term()) :: map()

Updates content of a pane by ID.

set_layout(state, layout)

@spec set_layout(map(), map()) :: map()

Restores layout from a saved state.

set_pane_size(state, pane_id, size)

@spec set_pane_size(map(), term(), number()) :: map()

Sets the size of a pane by ID.

toggle(state, pane_id)

@spec toggle(map(), term()) :: map()

Toggles collapse state of a pane by ID.