components

package
v0.0.41 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package components contains reusable TUI components.

Index

Constants

View Source
const DefaultGrowingTextAreaMaxLines = 6

DefaultGrowingTextAreaMaxLines is the cap used when no MaxLines is set.

View Source
const DefaultGrowingTextInputMaxLines = 3

DefaultGrowingTextInputMaxLines caps scalar inputs that wrap for visibility.

View Source
const FramesPerHop = 5

FramesPerHop is the number of animation frames in a single hop. Frame sequence: crouch(0), rise(1), peak(2), fall(3), land(4).

Variables

This section is empty.

Functions

func ApplyOverlayListStyles

func ApplyOverlayListStyles(m list.Model, st styles.Styles) list.Model

ApplyOverlayListStyles applies shared overlay foreground styling to list empty states.

func BunnyCloseCmd

func BunnyCloseCmd() tea.Cmd

BunnyCloseCmd schedules the eye-open 200 ms from now. It fires after the bunny has blinked, signalling time to reopen.

func BunnyHopIdleCmd

func BunnyHopIdleCmd() tea.Cmd

BunnyHopIdleCmd waits 10–25 seconds and then fires a hop sequence. The hop count (2 or 3) is chosen at fire time so that multiple instances started at the same wall-clock second don't all hop in sync.

func BunnyHopPauseTick

func BunnyHopPauseTick() tea.Cmd

BunnyHopPauseTick schedules a BunnyHopStepMsg after the between-hop pause. This gives the bunny a moment on the box before launching again.

func BunnyHopTick

func BunnyHopTick(d time.Duration) tea.Cmd

BunnyHopTick schedules a BunnyHopStepMsg after the given duration.

func BunnyOpenCmd

func BunnyOpenCmd() tea.Cmd

BunnyOpenCmd schedules the next blink 4 seconds from now. It fires after the bunny's eyes are already open, signalling time to blink.

func CalloutInnerWidth

func CalloutInnerWidth(st styles.Styles, width int) int

CalloutInnerWidth returns the content width available inside the callout shell.

func HopFrameDuration

func HopFrameDuration(frame int) time.Duration

HopFrameDuration returns the tick duration for each frame within a hop. Crouch/land are short (impact), rise/fall are medium, peak is longest (apex hang).

func HopFrameGap

func HopFrameGap(frame int) int

HopFrameGap returns the number of blank lines between the bunny and the box for the given frame index within a hop. This creates the vertical arc: crouch/land on the box (0 gaps), rise/fall at low height (1 gap), peak at max height (2 gaps).

func HopFrameProgress

func HopFrameProgress(frame int) float64

HopFrameProgress returns the horizontal progress (0.0–1.0) through the current individual hop for the given frame. The bunny accelerates during the first half and decelerates during the second half, mimicking a natural parabolic arc.

func NewTextArea

func NewTextArea() textarea.Model

func NewTextInput

func NewTextInput() textinput.Model

NewTextInput returns a textinput.Model ready for use. Use this everywhere in the TUI instead of textinput.New() so that input construction is centralised and any future key-binding or style changes apply uniformly without hunting call sites.

The default textinput key map already covers all standard macOS terminal editing shortcuts (⌥+Backspace → alt+backspace, ⌘+Backspace → ctrl+u, ⌥+←/→ → alt+left/right, ⌘+←/→ → ctrl+a/ctrl+e, word movement via ctrl+left/ctrl+right). No extra bindings are required for textinput.

func PaneInnerSize

func PaneInnerSize(st styles.Styles, width, height int) (int, int)

PaneInnerSize returns the content box available inside a shared pane shell.

func RenderBunny

func RenderBunny(phase int, side BunnySide) string

RenderBunny returns the 3-line ASCII bunny art for the given blink phase and corner side. The bottom line is the feet; callers should join this string above a bordered box using the matching lipgloss alignment so the foot character touches the box corner.

func RenderBunnyCrouch

func RenderBunnyCrouch(phase int) string

RenderBunnyCrouch returns the 3-line crouched bunny art for the given blink phase. Like RenderBunnyHop, lines have no intrinsic horizontal position.

func RenderBunnyHop

func RenderBunnyHop(phase int) string

RenderBunnyHop returns the 3-line airborne bunny art for the given blink phase. Lines have no intrinsic horizontal position: the caller is responsible for padding each line to the desired offset within the container width.

func RenderCallout

func RenderCallout(st styles.Styles, spec CalloutSpec) string

RenderCallout renders semantic bordered content.

func RenderDivider

func RenderDivider(st styles.Styles, width int) string

RenderDivider renders a full-width semantic divider.

func RenderHeaderBlock

func RenderHeaderBlock(st styles.Styles, spec HeaderBlockSpec) string

RenderHeaderBlock renders shared title/meta/divider workflow chrome.

func RenderKeyHints

func RenderKeyHints(st styles.Styles, hints []KeyHint, separator string) string

RenderKeyHints renders a semantic keybind row.

func RenderOverlayDivider

func RenderOverlayDivider(st styles.Styles, width int) string

RenderOverlayDivider renders a semantic divider line for overlay content.

func RenderOverlayFrame

func RenderOverlayFrame(st styles.Styles, frameWidth int, spec OverlayFrameSpec) string

RenderOverlayFrame renders the outer overlay shell around header, body, and footer content.

func RenderOverlayPane added in v0.0.39

func RenderOverlayPane(st styles.Styles, width, height int, spec OverlayPaneSpec) string

RenderOverlayPane renders a bordered pane with an optional title row and divider.

func RenderPane

func RenderPane(st styles.Styles, spec PaneSpec) string

RenderPane renders shared bordered pane chrome around already-sized content.

func RenderProgressBar

func RenderProgressBar(st styles.Styles, done, total, width int) string

RenderProgressBar renders a semantic text progress bar of the given width.

func RenderSplitOverlayBody

func RenderSplitOverlayBody(st styles.Styles, layout SplitOverlayLayout, spec SplitOverlaySpec) string

RenderSplitOverlayBody renders a split left/right pane body using a computed layout.

func RenderTabs

func RenderTabs(st styles.Styles, labels []string, active int, separator string) string

RenderTabs renders an active/inactive semantic tabs row.

func ToastTickCmd

func ToastTickCmd() tea.Cmd

ToastTickCmd returns a Cmd that fires after 1s.

Types

type BunnyBlinkMsg

type BunnyBlinkMsg struct{ Phase int }

BunnyBlinkMsg is dispatched when the blink animation state should change. Phase 0 = eyes open, phase 1 = eyes closed.

type BunnyHopStepMsg

type BunnyHopStepMsg struct{}

BunnyHopStepMsg advances the hop animation by one frame. It is reused for both in-hop frame advances and between-hop pauses.

type BunnyHopTriggerMsg

type BunnyHopTriggerMsg struct{ Hops int }

BunnyHopTriggerMsg begins a hop sequence. Hops is the number of individual hops (2 or 3), chosen randomly at fire time. A 2-hop sequence touches the box once; a 3-hop sequence touches it twice.

type BunnySide

type BunnySide int

BunnySide determines on which corner of the box the bunny sits. The value is chosen randomly at startup and held for the lifetime of the model.

const (
	BunnySideLeft  BunnySide = iota // bunny sits on the top-left corner  (╭)
	BunnySideRight                  // bunny sits on the top-right corner (╮)
)

type CalloutSpec

type CalloutSpec struct {
	Body    string
	Width   int
	Variant CalloutVariant
}

CalloutSpec describes a bordered content box.

type CalloutVariant

type CalloutVariant int

CalloutVariant selects the semantic surface treatment.

const (
	CalloutDefault CalloutVariant = iota
	CalloutCard
	CalloutWarning
	CalloutRunning // active/accent border color for in-progress tool cards
	CalloutError   // error border color for failed tool cards
	CalloutTool    // completed tool call — more visible border than CalloutDefault
	CalloutPrompt  // user prompt / feedback input blocks
)

type ConfirmDialog

type ConfirmDialog struct {
	Title   string
	Message string
	OnYes   tea.Cmd
	Active  bool
	Styles  styles.Styles
}

ConfirmDialog is a generic yes/no confirmation modal.

func NewConfirmDialog

func NewConfirmDialog(st styles.Styles, title, message string, onYes tea.Cmd) ConfirmDialog

NewConfirmDialog creates an active confirmation dialog.

func (ConfirmDialog) View

func (d ConfirmDialog) View() string

View renders the dialog; returns empty string when inactive.

type ConfirmMsg

type ConfirmMsg struct{ Confirmed bool }

ConfirmMsg is emitted when the dialog is resolved.

type GrowingTextArea added in v0.0.33

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

GrowingTextArea is a single-purpose component: a textarea that starts at one row and grows up to MaxLines as the wrapped content gets taller, then caps.

Usage:

  • Construct with NewGrowingTextArea(); set Placeholder, MaxLines, CharLimit before first SetWidth/Focus as needed.
  • Call SetWidth on every layout change.
  • Call Focus()/Blur() — both return tea.Cmd that toggle terminal mouse reporting (Disable on Focus, Enable on Blur). Batch with any other host command.
  • Forward all key/mouse events that the host does not consume itself to Update; Update returns a tea.Cmd that may carry GrowingTextAreaScrollMsg for the host to route to its viewport.
  • Reset() clears the value, returns the height to 1, blurs, and re-enables mouse reporting. The returned cmd MUST be batched into the host's reply.

Submission semantics are owned by the host. The host MUST intercept `enter` (KeyEnter) before forwarding events; the embedded textarea's keymap (see NewTextArea / macOSTextAreaKeyMap) only treats `alt+enter`, `shift+enter`, and `ctrl+j` as newline insertion, so plain `enter` is safe to use as submit upstream.

func NewGrowingTextArea added in v0.0.33

func NewGrowingTextArea(id string) GrowingTextArea

NewGrowingTextArea returns a GrowingTextArea ready to use. id labels the instance for hosts that route GrowingTextAreaScrollMsg from multiple components; pass "" if you only have one.

func (GrowingTextArea) AtBottom added in v0.0.33

func (g GrowingTextArea) AtBottom() bool

AtBottom reports whether a down-arrow would leave the textarea instead of moving within it.

func (GrowingTextArea) AtTop added in v0.0.33

func (g GrowingTextArea) AtTop() bool

AtTop reports whether an up-arrow would leave the textarea instead of moving within it.

func (*GrowingTextArea) Blur added in v0.0.33

func (g *GrowingTextArea) Blur() tea.Cmd

Blur blurs the textarea and re-enables cell-motion mouse reporting.

func (*GrowingTextArea) Flush added in v0.0.33

func (g *GrowingTextArea) Flush()

Flush resolves any buffered SGR fragment state by inserting the buffered '[' (if any) into the textarea. Hosts that intercept Enter (or any other terminal key) before forwarding to Update MUST call Flush before reading Value(), so a trailing '[' typed by the user is preserved on submit.

func (*GrowingTextArea) Focus added in v0.0.33

func (g *GrowingTextArea) Focus() tea.Cmd

Focus focuses the textarea and disables terminal mouse reporting so wheel events do not leak into the textarea as text. Batch the returned cmd with any host commands.

func (*GrowingTextArea) FocusKeepMouse added in v0.0.35

func (g *GrowingTextArea) FocusKeepMouse() tea.Cmd

FocusKeepMouse focuses the textarea without changing terminal mouse reporting. Use this when the host view must keep receiving wheel events while the input is focused.

func (GrowingTextArea) Focused added in v0.0.33

func (g GrowingTextArea) Focused() bool

Focused reports whether the textarea is focused.

func (GrowingTextArea) Height added in v0.0.33

func (g GrowingTextArea) Height() int

Height returns the current visual row count (1..MaxLines).

func (*GrowingTextArea) Reset added in v0.0.33

func (g *GrowingTextArea) Reset() tea.Cmd

Reset clears value, returns height to 1, blurs, drops any buffered SGR fragment state, and returns a cmd that re-enables cell-motion mouse reporting. Batch the cmd with any host reply.

func (*GrowingTextArea) SetCharLimit added in v0.0.33

func (g *GrowingTextArea) SetCharLimit(n int)

SetCharLimit sets the maximum total characters; 0 = unlimited.

func (*GrowingTextArea) SetMaxLines added in v0.0.33

func (g *GrowingTextArea) SetMaxLines(n int)

SetMaxLines sets the upper bound on visual rows. Values < 1 are clamped to 1. MaxHeight on the underlying textarea is updated to match.

func (*GrowingTextArea) SetPlaceholder added in v0.0.33

func (g *GrowingTextArea) SetPlaceholder(s string)

SetPlaceholder updates the placeholder text shown when empty.

func (*GrowingTextArea) SetValue added in v0.0.33

func (g *GrowingTextArea) SetValue(s string)

SetValue replaces the textarea content and re-syncs visual height.

func (*GrowingTextArea) SetWidth added in v0.0.33

func (g *GrowingTextArea) SetWidth(w int)

SetWidth recomputes the textarea inner width and resyncs the visual height (a width change can change wrapped line count).

func (GrowingTextArea) Update added in v0.0.33

func (g GrowingTextArea) Update(msg tea.Msg) (GrowingTextArea, tea.Cmd)

Update forwards the message to the embedded textarea and grows the visual height to fit. SGR mouse fragments are intercepted: matched wheel events become GrowingTextAreaScrollMsg and never reach the textarea. Returns the updated component and any cmd produced (textarea cmd or scroll-intent).

func (GrowingTextArea) Value added in v0.0.33

func (g GrowingTextArea) Value() string

Value returns the current textarea value.

func (GrowingTextArea) View added in v0.0.33

func (g GrowingTextArea) View() string

View renders the textarea around the actual cursor position. Bubbles only populates the textarea viewport during View(), but its cursor-following reposition happens during Update(). Render once to populate viewport content, run a no-op focused update so Bubbles repositions around the current cursor, then render the positioned viewport. This preserves Bubbles' line-number and cursor rendering instead of slicing raw text ourselves.

func (GrowingTextArea) Width added in v0.0.33

func (g GrowingTextArea) Width() int

Width returns the configured inner width.

type GrowingTextAreaScrollMsg added in v0.0.33

type GrowingTextAreaScrollMsg struct {
	// Source identifies the GrowingTextArea instance that emitted the message
	// when a host owns more than one. Hosts that own a single instance can
	// ignore it.
	Source string
	// Delta is the number of viewport rows to scroll. Negative = up, positive = down.
	Delta int
}

GrowingTextAreaScrollMsg is emitted by GrowingTextArea.Update when SGR mouse wheel fragments leak into the textarea while it is focused (terminals that keep emitting CSI sequences after mouse reporting was disabled, or before the host had a chance to disable it). Hosts forward Delta to their viewport: negative scrolls up, positive scrolls down, in viewport rows.

type GrowingTextInput added in v0.0.33

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

GrowingTextInput is a scalar text input that wraps visually as content grows. It preserves textinput semantics: values are single-line, plain Enter is host-owned, and no newline insertion is supported. Use it for long scalar values such as URLs, names, labels, and settings values that should remain visible on narrow terminals without becoming prose textareas.

func NewGrowingTextInput added in v0.0.33

func NewGrowingTextInput() GrowingTextInput

NewGrowingTextInput returns a scalar input that starts at one row and grows up to DefaultGrowingTextInputMaxLines as its value wraps at the configured width.

func (*GrowingTextInput) Blur added in v0.0.33

func (g *GrowingTextInput) Blur()

func (*GrowingTextInput) Focus added in v0.0.33

func (g *GrowingTextInput) Focus() tea.Cmd

func (GrowingTextInput) Focused added in v0.0.33

func (g GrowingTextInput) Focused() bool

func (GrowingTextInput) Height added in v0.0.33

func (g GrowingTextInput) Height() int

func (GrowingTextInput) Placeholder added in v0.0.33

func (g GrowingTextInput) Placeholder() string

func (*GrowingTextInput) Reset added in v0.0.33

func (g *GrowingTextInput) Reset()

func (*GrowingTextInput) SetCharLimit added in v0.0.33

func (g *GrowingTextInput) SetCharLimit(n int)

func (*GrowingTextInput) SetCursor added in v0.0.33

func (g *GrowingTextInput) SetCursor(pos int)

func (*GrowingTextInput) SetMaxLines added in v0.0.33

func (g *GrowingTextInput) SetMaxLines(n int)

func (*GrowingTextInput) SetPlaceholder added in v0.0.33

func (g *GrowingTextInput) SetPlaceholder(s string)

func (*GrowingTextInput) SetPrompt added in v0.0.33

func (g *GrowingTextInput) SetPrompt(s string)

func (*GrowingTextInput) SetValue added in v0.0.33

func (g *GrowingTextInput) SetValue(s string)

func (*GrowingTextInput) SetWidth added in v0.0.33

func (g *GrowingTextInput) SetWidth(w int)

func (GrowingTextInput) Update added in v0.0.33

func (g GrowingTextInput) Update(msg tea.Msg) (GrowingTextInput, tea.Cmd)

func (GrowingTextInput) Value added in v0.0.33

func (g GrowingTextInput) Value() string

func (GrowingTextInput) View added in v0.0.33

func (g GrowingTextInput) View() string

func (GrowingTextInput) Width added in v0.0.33

func (g GrowingTextInput) Width() int

type HeaderBlockSpec

type HeaderBlockSpec struct {
	Title   string
	Meta    string
	Width   int
	Divider bool
	// StatusLine, when non-empty and Divider is true, replaces the ─── divider
	// row with this pre-rendered string. The header line count is unchanged;
	// callers can use this to show a transient warning in-place without pushing
	// subsequent content down.
	StatusLine string
}

HeaderBlockSpec describes a semantic title/meta/divider block.

type KeyHint

type KeyHint struct {
	Key   string
	Label string
}

KeyHint is a semantic key/label pair.

type OverlayFrameSpec

type OverlayFrameSpec struct {
	HeaderLines []string
	Body        string
	Footer      string
	Focused     bool
}

OverlayFrameSpec describes the outer overlay shell.

type OverlayPaneSpec

type OverlayPaneSpec struct {
	Title        string
	DividerWidth int
	Body         string
	Focused      bool
}

OverlayPaneSpec describes a bordered pane inside a split overlay body.

type PaneSpec

type PaneSpec struct {
	Content string
	Width   int
	Height  int
	Focused bool
}

PaneSpec describes a bordered application pane.

type RenderedKeyHint

type RenderedKeyHint struct {
	Raw      string
	Rendered string
}

RenderedKeyHint preserves both rendered and plain-text forms for layout decisions.

func RenderKeyHintFragments

func RenderKeyHintFragments(st styles.Styles, hints []KeyHint) []RenderedKeyHint

RenderKeyHintFragments styles individual keybind hints for shared consumption.

type SplitOverlayLayout

type SplitOverlayLayout struct {
	FrameWidth      int
	ContentWidth    int
	InputWidth      int
	BodyHeight      int
	LeftPaneWidth   int
	RightPaneWidth  int
	LeftInnerWidth  int
	RightInnerWidth int
	ListHeight      int
	ViewportWidth   int
	ViewportHeight  int
}

SplitOverlayLayout is the computed geometry for rendering a split overlay.

func ComputeSplitOverlayLayout

func ComputeSplitOverlayLayout(termWidth, termHeight, chromeLines int, spec SplitOverlaySizingSpec) SplitOverlayLayout

ComputeSplitOverlayLayout calculates the shared geometry for split overlays.

type SplitOverlaySizingSpec

type SplitOverlaySizingSpec struct {
	MaxOverlayWidth   int
	LeftMinWidth      int
	RightMinWidth     int
	LeftWeight        int
	RightWeight       int
	MinBodyHeight     int
	MaxBodyHeight     int // 0 means no upper limit
	DefaultBodyHeight int
	HeightRatioNum    int
	HeightRatioDen    int
	InputWidthOffset  int
}

SplitOverlaySizingSpec describes the geometry constraints for a split list/detail overlay.

type SplitOverlaySpec

type SplitOverlaySpec struct {
	LeftPane  OverlayPaneSpec
	RightPane OverlayPaneSpec
}

SplitOverlaySpec describes the split-pane body content.

type Toast

type Toast struct {
	Message string
	Level   ToastLevel
	Expires time.Time
	// contains filtered or unexported fields
}

type ToastLevel

type ToastLevel int
const (
	ToastInfo ToastLevel = iota
	ToastSuccess
	ToastWarning
	ToastError
)

type ToastModel

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

func NewToastModel

func NewToastModel(st styles.Styles) ToastModel

func (*ToastModel) AddToast

func (m *ToastModel) AddToast(msg string, level ToastLevel)

func (*ToastModel) HasToasts

func (m *ToastModel) HasToasts() bool

func (*ToastModel) Prune

func (m *ToastModel) Prune()

func (*ToastModel) SetWidth

func (m *ToastModel) SetWidth(terminalWidth int)

func (*ToastModel) StackView

func (m *ToastModel) StackView(pinned ...Toast) string

func (*ToastModel) View

func (m *ToastModel) View() string

type ToastTickMsg

type ToastTickMsg time.Time

ToastTickMsg is sent every second to prune expired toasts.

Jump to

Keyboard shortcuts

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