tui

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package tui hosts the shared Bubble Tea primitives used by every Multiversa wizard. It defines the Step contract that screens satisfy and the messages used to navigate between them. Concrete step types still live in each wizard's own package (e.g. internal/wizard/steps for the `init` wizard) — this package only owns the abstractions.

The Step interface was originally introduced under internal/wizard/steps; v0.4.0 lifts it here so detect/stack/ workspace/usb/lab wizards can share the same shape.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Back

func Back() tea.Msg

Back returns a BackMsg as a tea.Msg.

func Cancel

func Cancel() tea.Msg

Cancel returns a CancelMsg as a tea.Msg.

func Choose

func Choose[T any](v Verbosity, verbose, standard, condensed T) T

Choose returns one of the three strings based on the current verbosity. Useful for inline conditionals in View() methods:

hint := tui.Choose(v, "Press y/n to confirm", "y/n", "")

func ConfirmDecision

func ConfirmDecision(input string) bool

ConfirmDecision interprets a user response to a yes/no prompt. The contract is intentionally strict for destructive operations: only an explicit "y", "Y", "yes", or "YES" returns true. Everything else — including blank, spaces, "no", ambiguous strings — returns false. This is the no-default-yes rule baked into v0.4.0 specs.

func Header(title, subtitle string, step, total int) string

Header renders the canonical Multiversa wizard header: an accented title, a dim subtitle, and an optional step-progress crumb of the form "step 2 of 5". The output never contains ANSI hyperlinks so it stays paste-safe in the user's terminal scrollback.

Pass step=0,total=0 to omit the progress crumb (e.g. for one-shot commands like `detect`).

func Next

func Next() tea.Msg

Next returns a NextMsg as a tea.Msg so callers can use it as a command return value.

Types

type BackMsg

type BackMsg struct{}

BackMsg signals that the user wants to revisit the previous step.

type CancelMsg

type CancelMsg struct{}

CancelMsg signals that the user wants to abort the wizard. The host program is expected to translate this into exit code 2.

type LayerStatus

type LayerStatus struct {
	Name      string // e.g. "Técnica"
	Tagline   string // optional one-line description rendered dim
	Steps     []ProgressItem
	IsCurrent bool // true when the cursor is inside this layer
}

LayerStatus is one layer entry in the Sidebar of the meta-wizard. It represents a vertical group of related Steps (Técnica / Identitaria / Operacional), each with its own per-step progress.

type NextMsg

type NextMsg struct{}

NextMsg signals that the current step is done; the wizard should advance to the next one.

type ProgressItem

type ProgressItem struct {
	Label string
	Note  string
	State ProgressState
}

ProgressItem is one row in a ProgressList.

type ProgressList

type ProgressList struct {
	Items []ProgressItem
}

ProgressList renders a vertical stack of items with state glyphs. Like Selector, it is stateless rendering — the host owns state transitions and feeds in the slice each frame.

func (ProgressList) Counts

func (p ProgressList) Counts() (done, skipped, failed, pending int)

Counts returns done/skipped/failed/pending counts.

func (ProgressList) Render

func (p ProgressList) Render() string

Render returns the multi-line view for the progress list.

type ProgressState

type ProgressState int

ProgressState is the lifecycle of a single ProgressItem.

const (
	// Pending — not started yet. Rendered dim.
	Pending ProgressState = iota
	// Running — in flight. Rendered with the accent color.
	Running
	// Done — completed successfully. Rendered with ✓.
	Done
	// Skipped — intentionally bypassed (e.g. already installed).
	Skipped
	// Failed — completed with error. Rendered as ✗ in warn style.
	Failed
)

type Selector

type Selector struct {
	Items  []SelectorItem
	Cursor int
}

Selector is a stateless renderer for a vertical list with a cursor. It is intentionally pure: no Bubble Tea wiring lives here. Wizards own their tea.Model and call Render() from their View().

func (*Selector) MoveDown

func (s *Selector) MoveDown()

MoveDown advances the cursor, skipping disabled items.

func (*Selector) MoveUp

func (s *Selector) MoveUp()

MoveUp retreats the cursor, skipping disabled items.

func (Selector) Render

func (s Selector) Render() string

Render returns the multi-line view for the selector.

func (Selector) Selected

func (s Selector) Selected() *SelectorItem

Selected returns the currently focused item or nil if the cursor is out of bounds (empty list).

type SelectorItem

type SelectorItem struct {
	Label    string
	Hint     string
	Marker   string // e.g. "✓" for installed
	Disabled bool
}

SelectorItem is one row in a Selector list. Disabled rows are rendered dim and can't be chosen; Marker is an optional glyph the caller can use to flag installed/completed items.

type Sidebar struct {
	Layers []LayerStatus
}

Sidebar renders the layered overview shown on the left of `multiversa lab`. It is intentionally text-only — no fixed-width padding — so the wizard host can wrap it in any layout primitive (lipgloss.JoinHorizontal, etc.) without fighting alignment.

func (Sidebar) Render

func (s Sidebar) Render() string

Render returns the multi-line view for the sidebar.

type Step

type Step interface {
	Init() tea.Cmd
	Update(msg tea.Msg) (Step, tea.Cmd)
	View() string
	Title() string
}

Step is the contract every wizard screen satisfies. Returning a NextMsg from Update advances the wizard; BackMsg goes back; CancelMsg exits the program with status 2 (user cancel) so scripts can distinguish cancellation from a real failure.

type Verbosity

type Verbosity int

Verbosity is the explanation density a wizard renders. It maps one-to-one to profile.Level (newcomer → Verbose, enthusiast → Standard, expert → Condensed) but stays here as a UI concern so the tui package does not depend on internal/profile.

const (
	// Verbose shows the full explanation, hints, and rationale.
	Verbose Verbosity = iota
	// Standard hides only the most expository hints.
	Standard
	// Condensed strips everything except the action — one line per
	// item, keyboard hints kept.
	Condensed
)

func VerbosityForLevel

func VerbosityForLevel(level string) Verbosity

VerbosityForLevel maps a profile level name to the matching Verbosity. Unknown levels default to Standard so missing config never breaks the UI.

func (Verbosity) String

func (v Verbosity) String() string

String returns the human label for a verbosity level.

Jump to

Keyboard shortcuts

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