Documentation
¶
Overview ¶
Package components contains reusable TUI components.
Index ¶
- Constants
- func ApplyOverlayListStyles(m list.Model, st styles.Styles) list.Model
- func BunnyCloseCmd() tea.Cmd
- func BunnyHopIdleCmd() tea.Cmd
- func BunnyHopPauseTick() tea.Cmd
- func BunnyHopTick(d time.Duration) tea.Cmd
- func BunnyOpenCmd() tea.Cmd
- func CalloutInnerWidth(st styles.Styles, width int) int
- func HopFrameDuration(frame int) time.Duration
- func HopFrameGap(frame int) int
- func HopFrameProgress(frame int) float64
- func NewTextArea() textarea.Model
- func NewTextInput() textinput.Model
- func PaneInnerSize(st styles.Styles, width, height int) (int, int)
- func RenderBunny(phase int, side BunnySide) string
- func RenderBunnyCrouch(phase int) string
- func RenderBunnyHop(phase int) string
- func RenderCallout(st styles.Styles, spec CalloutSpec) string
- func RenderDivider(st styles.Styles, width int) string
- func RenderHeaderBlock(st styles.Styles, spec HeaderBlockSpec) string
- func RenderKeyHints(st styles.Styles, hints []KeyHint, separator string) string
- func RenderOverlayDivider(st styles.Styles, width int) string
- func RenderOverlayFrame(st styles.Styles, frameWidth int, spec OverlayFrameSpec) string
- func RenderOverlayPane(st styles.Styles, width, height int, spec OverlayPaneSpec) string
- func RenderPane(st styles.Styles, spec PaneSpec) string
- func RenderProgressBar(st styles.Styles, done, total, width int) string
- func RenderSplitOverlayBody(st styles.Styles, layout SplitOverlayLayout, spec SplitOverlaySpec) string
- func RenderTabs(st styles.Styles, labels []string, active int, separator string) string
- func ToastTickCmd() tea.Cmd
- type BunnyBlinkMsg
- type BunnyHopStepMsg
- type BunnyHopTriggerMsg
- type BunnySide
- type CalloutSpec
- type CalloutVariant
- type ConfirmDialog
- type ConfirmMsg
- type GrowingTextArea
- func (g GrowingTextArea) AtBottom() bool
- func (g GrowingTextArea) AtTop() bool
- func (g *GrowingTextArea) Blur() tea.Cmd
- func (g *GrowingTextArea) Flush()
- func (g *GrowingTextArea) Focus() tea.Cmd
- func (g *GrowingTextArea) FocusKeepMouse() tea.Cmd
- func (g GrowingTextArea) Focused() bool
- func (g GrowingTextArea) Height() int
- func (g *GrowingTextArea) Reset() tea.Cmd
- func (g *GrowingTextArea) SetCharLimit(n int)
- func (g *GrowingTextArea) SetMaxLines(n int)
- func (g *GrowingTextArea) SetPlaceholder(s string)
- func (g *GrowingTextArea) SetValue(s string)
- func (g *GrowingTextArea) SetWidth(w int)
- func (g GrowingTextArea) Update(msg tea.Msg) (GrowingTextArea, tea.Cmd)
- func (g GrowingTextArea) Value() string
- func (g GrowingTextArea) View() string
- func (g GrowingTextArea) Width() int
- type GrowingTextAreaScrollMsg
- type GrowingTextInput
- func (g *GrowingTextInput) Blur()
- func (g *GrowingTextInput) Focus() tea.Cmd
- func (g GrowingTextInput) Focused() bool
- func (g GrowingTextInput) Height() int
- func (g GrowingTextInput) Placeholder() string
- func (g *GrowingTextInput) Reset()
- func (g *GrowingTextInput) SetCharLimit(n int)
- func (g *GrowingTextInput) SetCursor(pos int)
- func (g *GrowingTextInput) SetMaxLines(n int)
- func (g *GrowingTextInput) SetPlaceholder(s string)
- func (g *GrowingTextInput) SetPrompt(s string)
- func (g *GrowingTextInput) SetValue(s string)
- func (g *GrowingTextInput) SetWidth(w int)
- func (g GrowingTextInput) Update(msg tea.Msg) (GrowingTextInput, tea.Cmd)
- func (g GrowingTextInput) Value() string
- func (g GrowingTextInput) View() string
- func (g GrowingTextInput) Width() int
- type HeaderBlockSpec
- type KeyHint
- type OverlayFrameSpec
- type OverlayPaneSpec
- type PaneSpec
- type RenderedKeyHint
- type SplitOverlayLayout
- type SplitOverlaySizingSpec
- type SplitOverlaySpec
- type Toast
- type ToastLevel
- type ToastModel
- type ToastTickMsg
Constants ¶
const DefaultGrowingTextAreaMaxLines = 6
DefaultGrowingTextAreaMaxLines is the cap used when no MaxLines is set.
const DefaultGrowingTextInputMaxLines = 3
DefaultGrowingTextInputMaxLines caps scalar inputs that wrap for visibility.
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 ¶
ApplyOverlayListStyles applies shared overlay foreground styling to list empty states.
func BunnyCloseCmd ¶
BunnyCloseCmd schedules the eye-open 200 ms from now. It fires after the bunny has blinked, signalling time to reopen.
func BunnyHopIdleCmd ¶
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 ¶
BunnyHopPauseTick schedules a BunnyHopStepMsg after the between-hop pause. This gives the bunny a moment on the box before launching again.
func BunnyHopTick ¶
BunnyHopTick schedules a BunnyHopStepMsg after the given duration.
func BunnyOpenCmd ¶
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 ¶
CalloutInnerWidth returns the content width available inside the callout shell.
func HopFrameDuration ¶
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 ¶
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 ¶
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 NewTextInput ¶
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 ¶
PaneInnerSize returns the content box available inside a shared pane shell.
func RenderBunny ¶
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 ¶
RenderBunnyCrouch returns the 3-line crouched bunny art for the given blink phase. Like RenderBunnyHop, lines have no intrinsic horizontal position.
func RenderBunnyHop ¶
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 ¶
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 ¶
RenderKeyHints renders a semantic keybind row.
func RenderOverlayDivider ¶
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 ¶
RenderPane renders shared bordered pane chrome around already-sized content.
func RenderProgressBar ¶
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 ¶
RenderTabs renders an active/inactive semantic tabs row.
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.
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 ¶
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 OverlayFrameSpec ¶
OverlayFrameSpec describes the outer overlay shell.
type OverlayPaneSpec ¶
OverlayPaneSpec describes a bordered pane inside a split overlay body.
type RenderedKeyHint ¶
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 ¶
ToastTickMsg is sent every second to prune expired toasts.