pane

package
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package pane provides a bordered, titled, scrollable region for Bubble Tea TUIs. A Pane owns a viewport and renders a vertical scrollbar along its right edge. Any string content can be placed inside — render a child model to a string via its View() method and pass it to SetContent. While SetLoading(true) is in effect, the body is replaced by a centered spinner (with optional LoadingLabel) until SetLoading(false) restores the content.

Index

Constants

View Source
const (
	ScrollbarWidth  = 1
	ScrollbarHeight = 1
)
View Source
const HScrollStep = 4

HScrollStep is how many cells left/right scroll the pane horizontally.

View Source
const WheelStep = 3

WheelStep is how many lines one wheel notch scrolls. Three matches the convention terminals and GUI toolkits share.

Variables

This section is empty.

Functions

func Borderize

func Borderize(
	content string,
	border lipgloss.Border,
	color lipgloss.TerminalColor,
	embedded map[BorderPosition]string,
	slotBrackets SlotBracketStyle,
) string

Borderize wraps content in the given border with up to six embedded text slots (top/bottom × left/middle/right). Embedded text is flanked by inverted corner glyphs so it renders like `┤ title ├`. The border and all slot glyphs are drawn in color; embedded text passes through verbatim, so pre-style it with lipgloss if you want bold/colored labels.

func HScrollbar

func HScrollbar(width, total, visible, offset int) string

HScrollbar renders a single-row horizontal scrollbar of the given width. total is the total content width (longest line), visible is how much fits in the viewport, and offset is the current horizontal scroll column. When content fits entirely, returns a blank row.

func Scrollbar

func Scrollbar(height, total, visible, offset int) string

Scrollbar renders a single-column vertical scrollbar of the given height. total is the total number of lines in the content, visible is how many fit in the viewport, and offset is the current scroll offset from the top. When content fits entirely, returns a blank column of the given height.

Types

type BorderPosition

type BorderPosition int
const (
	TopLeftBorder BorderPosition = iota
	TopMiddleBorder
	TopRightBorder
	BottomLeftBorder
	BottomMiddleBorder
	BottomRightBorder
)

type Keys

type Keys struct {
	Left, Right key.Binding
	LeftEdge    key.Binding
	RightEdge   key.Binding
}

Keys is the pane's keymap for horizontal scroll. Each binding carries both its dispatch keys (WithKeys) and its help label (WithHelp); embedding components surface these in their own Help() so the hint strip stays honest when callers override defaults.

func DefaultKeys

func DefaultKeys() Keys

DefaultKeys returns the pane's stock h-scroll keymap.

func (*Keys) FillDefaults

func (k *Keys) FillDefaults()

FillDefaults fills any zero-valued binding in k with its DefaultKeys() counterpart. Exported so embedders (list/table/tree/inspector/logview) can call it on their nested pane.Keys field without re-implementing the merge.

type Options

type Options struct {
	Width, Height int
	Title         string
	// TitlePosition picks which border slot the title occupies. Defaults to
	// TopLeftBorder (the zero value).
	TitlePosition BorderPosition
	Focused       bool
	ActiveColor   lipgloss.TerminalColor
	InactiveColor lipgloss.TerminalColor
	// ActiveBorder is drawn when the Pane is focused. Defaults to
	// lipgloss.ThickBorder().
	ActiveBorder lipgloss.Border
	// InactiveBorder is drawn when the Pane is not focused. Defaults to
	// lipgloss.NormalBorder().
	InactiveBorder lipgloss.Border
	// SlotBrackets controls how the title and other border slot text are
	// bracketed against the border line. Defaults to SlotBracketsNone
	// (text sits inline on the border with no surrounding glyphs).
	SlotBrackets SlotBracketStyle
	// HScrollbar reserves a single row at the bottom of the inner content
	// area for a horizontal scrollbar. The thumb tracks xOffset against
	// the longest line; when content fits, the track renders blank.
	HScrollbar bool
	// Spinner picks the spinner frames used while the pane is in a
	// loading state (see SetLoading). When zero, defaults to spinner.Dot.
	Spinner *spinner.Spinner
	// SpinnerStyle is applied to the spinner glyph. The zero value
	// renders without any style; pass via theme.Pane() for a sensible
	// foreground.
	SpinnerStyle lipgloss.Style
	// LoadingLabel is rendered next to the spinner while loading. Use it
	// to give the user context — e.g. "loading cities…" or "fetching".
	LoadingLabel string

	// Keys overrides the pane's h-scroll keymap. Fields left zero fall
	// back to DefaultKeys(); embedders typically forward their own Keys
	// here so the user-facing override surface stays one struct per
	// component.
	Keys Keys
}

Options configures a new Pane. Zero-value fields fall back to defaults.

type Pane

type Pane struct {
	// contains filtered or unexported fields
}

Pane is a bordered region with a title, six metadata slots around the border, and a vertical scrollbar down the right edge.

func New

func New(opts Options) Pane

New constructs a Pane. SetContent must be called separately to populate it.

func (Pane) AtBottom

func (p Pane) AtBottom() bool

AtBottom reports whether the viewport is scrolled to the last line — useful for streaming-content components that auto-follow new output only while the user is parked at the bottom.

func (Pane) ContentRect added in v0.18.0

func (p Pane) ContentRect() geom.Rect

ContentRect returns the rect covering the Pane's inner content area — the outer rect less the border, the right-edge scrollbar, and the horizontal scrollbar row when enabled. It is the region row 0 of the content occupies, so RowAt inverts against it.

func (*Pane) EnsureVisible

func (p *Pane) EnsureVisible(n int)

EnsureVisible scrolls the viewport the minimum amount needed to put line `n` inside the visible window. Useful for cursor-driven list views, where moving the cursor past the viewport's bottom should pull the view with it.

func (Pane) Focused

func (p Pane) Focused() bool

Focused reports whether the pane is drawn in its active style.

func (*Pane) GotoBottom

func (p *Pane) GotoBottom()

GotoBottom scrolls the viewport to the last line.

func (*Pane) GotoTop

func (p *Pane) GotoTop()

GotoTop scrolls the viewport to the first line.

func (Pane) HScrollbarRect added in v0.18.0

func (p Pane) HScrollbarRect() geom.Rect

HScrollbarRect returns the rect of the horizontal scrollbar row, drawn below the body when HScrollbar is enabled. Empty when it isn't.

func (*Pane) HandleScrollbar added in v0.18.0

func (p *Pane) HandleScrollbar(e mouse.Msg) (row int, ok bool)

HandleScrollbar processes a mouse event against the Pane's scrollbars. Components call it first from their own mouse handling, so a click on the bar scrolls rather than selecting the row behind it.

ok reports whether the event was a scrollbar interaction at all. row is the content row the interaction targets — meaningful only when ok is true.

For a pane that scrolls its own viewport, the scroll is already applied and row can be ignored. For a component that windows its rows itself (pkg/table and pkg/inspector push metrics through SetVirtualScroll, and derive their window from the cursor), nothing is applied: moving the viewport under such a component would be undone on its next render, so it must move its cursor to row instead.

Pressing anywhere on the track jumps there, the thumb included — grabbing the thumb is a jump to where it already is, which leaves it put. Motion while the button is held keeps jumping, which is what makes it a drag. The pane tracks that state itself because the release can land outside the bar, or outside the pane entirely, and must still end the drag.

func (Pane) Header added in v0.18.1

func (p Pane) Header() string

Header returns the pinned header lines.

func (Pane) Height

func (p Pane) Height() int

Height returns the Pane's outer height.

func (Pane) HelpBindings

func (p Pane) HelpBindings() []key.Binding

HelpBindings returns the bindings to display in a component's hint strip — just the four pane keys (left/right move + edge jumps). The embedder appends these to its own Help() slice.

func (Pane) Init

func (p Pane) Init() tea.Cmd

func (Pane) Keys

func (p Pane) Keys() Keys

Keys returns the pane's h-scroll keymap. Embedding components include these in their own Help() so the hint strip surfaces h-scroll keys honestly (and reflects any caller overrides).

func (Pane) Loading

func (p Pane) Loading() bool

Loading reports whether the pane is currently in its loading state.

func (Pane) MaxXOffset

func (p Pane) MaxXOffset() int

MaxXOffset returns the largest meaningful horizontal scroll column — 0 when content fits in the inner width.

func (Pane) Rect added in v0.18.0

func (p Pane) Rect() geom.Rect

Rect returns the outer rect the Pane was last placed at, border included.

func (Pane) RowAt added in v0.18.0

func (p Pane) RowAt(x, y int) (row int, ok bool)

RowAt maps a terminal position to a zero-based index into the Pane's content, accounting for the border inset and the current vertical scroll. It reports ok=false when the position is outside the content area or the Pane wasn't drawn in the current frame, so a caller can forward the event on rather than claiming it.

func (*Pane) ScrollWheel added in v0.18.0

func (p *Pane) ScrollWheel(x, y int, up bool) bool

ScrollWheel applies a wheel event to the Pane's vertical scroll and reports whether it was consumed. It is the shared implementation for components that scroll the pane rather than moving a cursor — logview, textview, and a bare pane. Events outside the content area, or aimed at a Pane that wasn't drawn this frame, are declined so a sibling can claim them.

bubbles' viewport handles the wheel on tea.MouseMsg, but tuilib components receive mouse.Msg (which carries the resolved click count), so that path never fires — this is where wheel scrolling actually happens.

func (Pane) ScrollbarDrag added in v0.18.0

func (p Pane) ScrollbarDrag() bool

ScrollbarDrag reports whether a scrollbar drag is in progress.

func (*Pane) SetActiveColor

func (p *Pane) SetActiveColor(c lipgloss.TerminalColor)

SetActiveColor updates the border color used when the pane is focused. Useful when reacting to a theme swap without rebuilding the model.

func (*Pane) SetBottomLeft

func (p *Pane) SetBottomLeft(s string)

func (*Pane) SetBottomMiddle

func (p *Pane) SetBottomMiddle(s string)

func (*Pane) SetBottomRight

func (p *Pane) SetBottomRight(s string)

SetBottomRight overrides the auto-generated scroll percentage. Pass "" to restore the default.

func (*Pane) SetContent

func (p *Pane) SetContent(s string)

SetContent replaces the pane's content. Pass any string — a child model's View() output, a pre-rendered table, a log, raw text — and the pane will scroll it. Long lines are truncated to the inner width so terminal wrap can't break row counting; use left/right (or SetXOffset) to scroll horizontally past the cut.

func (*Pane) SetFocused

func (p *Pane) SetFocused(b bool)

func (*Pane) SetHeader added in v0.18.1

func (p *Pane) SetHeader(s string)

SetHeader pins lines directly under the top border, above the scrolling content. They never scroll, and the viewport shrinks to make room.

This is how a component puts its own chrome inside its pane rather than beside it — a filterable list draws its filter row here, so the filter is visibly *inside* the thing it filters instead of floating above it as an equal-weight sibling. Pass "" to remove it.

The header is rendered as given; a component wanting a rule beneath it should include one (the inner width is available from ContentRect).

func (*Pane) SetInactiveColor

func (p *Pane) SetInactiveColor(c lipgloss.TerminalColor)

SetInactiveColor updates the border color used when the pane is unfocused.

func (*Pane) SetLoading

func (p *Pane) SetLoading(b bool) tea.Cmd

SetLoading toggles the loading state. When entering the loading state, returns the spinner's initial Tick command — propagate it back to bubbletea (typically by returning it from your screen's Update or batching with other commands) so the spinner animates. When leaving the loading state, returns nil; any in-flight TickMsg is silently dropped on the next Update.

func (*Pane) SetLoadingLabel

func (p *Pane) SetLoadingLabel(s string)

SetLoadingLabel updates the text shown next to the spinner while loading.

func (*Pane) SetRect added in v0.18.0

func (p *Pane) SetRect(r geom.Rect)

SetRect places the Pane at an absolute position and outer size (including border). The inner content area is sized as (width-2-scrollbar) × (height-2), shrunk by one more row when HScrollbar is enabled.

The rect is retained so the Pane and the components embedding it can map a mouse position back to a content row — see Rect and ContentRect.

func (*Pane) SetSlotBrackets

func (p *Pane) SetSlotBrackets(s SlotBracketStyle)

SetSlotBrackets controls how the title and other slot text meet the border.

func (*Pane) SetSpinnerStyle

func (p *Pane) SetSpinnerStyle(s lipgloss.Style)

SetSpinnerStyle updates the lipgloss style applied to the spinner glyph. Useful for re-theming without rebuilding the pane.

func (*Pane) SetTitle

func (p *Pane) SetTitle(s string)

func (*Pane) SetTitlePosition

func (p *Pane) SetTitlePosition(pos BorderPosition)

func (*Pane) SetTopLeft

func (p *Pane) SetTopLeft(s string)

func (*Pane) SetTopRight

func (p *Pane) SetTopRight(s string)

func (*Pane) SetVirtualScroll

func (p *Pane) SetVirtualScroll(total, visible, offset int)

SetVirtualScroll overrides the right-edge scrollbar's source data. Instead of computing thumb size and position from the viewport's in-memory line count, the bar uses (total, visible, offset) directly — in any units the caller chooses, commonly logical row counts. Used by components that window their own content outside the viewport so the scrollbar still reflects the full dataset rather than the in-viewport slice (e.g. pkg/table reserves the top inner row for a sticky header and feeds the bar with len(rows) / dataRowsWindow / firstVisibleRow).

While virtual scroll is active the bottom-right "%" auto-fill is suppressed so the caller can paint a more meaningful indicator (e.g. "5 / 100") via SetBottomRight. Pass total <= 0 to disable and revert to viewport-driven metrics.

func (*Pane) SetXOffset

func (p *Pane) SetXOffset(n int)

SetXOffset jumps to the given horizontal scroll column, clamped into [0, MaxXOffset()].

func (*Pane) SetYOffset

func (p *Pane) SetYOffset(n int)

SetYOffset jumps to the given vertical scroll offset.

func (Pane) Update

func (p Pane) Update(msg tea.Msg) (Pane, tea.Cmd)

Update forwards key/mouse events to the embedded viewport so vertical scroll keys (pgup/pgdn/up/down/mouse wheel) work by default. Horizontal scroll keys are intercepted: left/h and right/l step by HScrollStep; 0 and home jump to the left edge; $ and end jump to the right edge. The content is re-cut to the visible window via ansi.Cut so ANSI styles stay intact across the slice. While loading, spinner.TickMsg events are consumed to advance the spinner; the chained next-tick command is returned so the animation keeps running.

func (Pane) VScrollbarRect added in v0.18.0

func (p Pane) VScrollbarRect() geom.Rect

VScrollbarRect returns the rect of the vertical scrollbar column, which View draws immediately right of the viewport.

func (Pane) View

func (p Pane) View() string

View renders the pane: content inside viewport, scrollbar on the right, both wrapped in a titled border with metadata slots. While loading, the inner content area is replaced with a centered spinner glyph (plus an optional label) and scroll chrome is suppressed.

func (Pane) VisibleRows

func (p Pane) VisibleRows() int

VisibleRows returns the inner viewport height — the number of content rows the pane can display at once, after subtracting borders and the horizontal scrollbar (when enabled). Useful for components that need to move a cursor by a window-relative amount (e.g. half-page jumps).

func (Pane) VisibleWidth

func (p Pane) VisibleWidth() int

VisibleWidth returns the inner viewport width — the number of visible cells the pane can display per row, after subtracting borders and the vertical scrollbar gutter. Useful for components that distribute horizontal space across sub-elements (e.g. flex columns).

func (Pane) Width

func (p Pane) Width() int

Width returns the Pane's outer width.

func (Pane) XOffset

func (p Pane) XOffset() int

XOffset returns the current horizontal scroll column.

func (Pane) YOffset

func (p Pane) YOffset() int

YOffset returns the current vertical scroll offset (top visible line).

type SlotBracketStyle

type SlotBracketStyle int

SlotBracketStyle controls how embedded slot text (titles, labels, scroll percentages) is bracketed against the surrounding border line.

const (
	// SlotBracketsNone draws the border edge straight through the slot region,
	// so text sits inline on the border line: `── text ──`. This is the
	// default — a titled pane reads as a plain rectangle with the title
	// floating on its top edge.
	SlotBracketsNone SlotBracketStyle = iota
	// SlotBracketsCorners wraps slot text with inverted corner glyphs so it
	// looks like a tab dipping into the pane: `┐ text ┌`. Matches pug's
	// aesthetic; useful when you want the title to read as a labeled tab.
	SlotBracketsCorners
	// SlotBracketsTees uses junction tees pointing into the slot text:
	// `─┤ text ├─`.
	SlotBracketsTees
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL