tui

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package tui provides terminal user interface components.

Package tui provides terminal user interface components.

Index

Constants

View Source
const DefaultAnimation = "outline-in"

DefaultAnimation is the animation used when none is specified.

View Source
const Wordmark = "" +
	"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⣶⣶⣶⣶⣶⣶⣦⣤⣀\n" +
	"⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⣿⣿⠿⠿⠛⠛⠛⠻⠿⣿⣿⣿⣦⣀\n" +
	"⠀⠀⠀⠀⠀⢀⣴⣿⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⣿⣿⣦⡀\n" +
	"⠀⠀⠀⠀⣴⣿⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣄\n" +
	"⠀⠀⢀⣼⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⡀⠀⠀⠀⠀⢻⣿⣿⣆\n" +
	"⠀⢀⣾⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⠃⠀⠀⠀⠀⠀⢻⣿⣿⡄\n" +
	"⠀⣼⣿⣿⠃⠀⠀⣠⣶⣿⣷⣦⣄⠀⠀⢀⣼⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⡀\n" +
	"⢸⣿⣿⠇⠀⢠⣾⣿⡿⠛⠻⣿⣿⣷⣤⣾⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣇\n" +
	"⠈⠉⠉⠀⢠⣿⣿⡟⠁⠀⠀⠈⠻⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿\n" +
	"⠀⠀⠀⢠⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇\n" +
	"⠀⠀⠀⢻⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⠇\n" +
	"⠀⠀⠀⠀⠙⠿⣿⣿⣷⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣶⣿⣿⡿⠋\n" +
	"⠀⠀⠀⠀⠀⠀⠈⠛⠿⣿⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⡿⠟⠉\n" +
	"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠛⠿⠿⠿⠿⠿⠿⠟⠛⠛⠉⠉"

Wordmark is a braille-art rendering of the Basecamp mountain logo.

View Source
const WordmarkLines = 14

WordmarkLines is the number of lines in the Wordmark.

View Source
const WordmarkWidth = 32

WordmarkWidth is the display width (rune count of widest line) of the Wordmark.

Variables

View Source
var BrandColor = lipgloss.Color("#e8a217")

BrandColor is the fixed Basecamp brand yellow, independent of theme.

Functions

func AnimateWordmark added in v0.3.0

func AnimateWordmark(w io.Writer, theme Theme)

AnimateWordmark draws the wordmark with a paint animation. Honors BASECAMP_ANIM to override the default strategy.

func AnimateWordmarkAsync added in v0.3.0

func AnimateWordmarkAsync(w io.Writer, theme Theme) (io.Writer, func())

AnimateWordmarkAsync starts the animation in a background goroutine and returns a writer for subsequent output plus a wait function. Output written through the returned writer appears below the animating logo. Call wait before any interactive prompts or output that bypasses the returned writer. Falls back to static render (returning w unchanged and no-op wait) when not a TTY or NO_COLOR is active.

func AnimateWordmarkWith added in v0.3.0

func AnimateWordmarkWith(w io.Writer, theme Theme, strategy string)

AnimateWordmarkWith draws the wordmark using the named animation strategy. Unknown strategy names fall back to DefaultAnimation. Falls back to static render if w is not a TTY or NO_COLOR is active.

func AnimationNames added in v0.3.0

func AnimationNames() []string

AnimationNames returns the registered animation strategy names.

func Confirm

func Confirm(message string, defaultValue bool) (bool, error)

Confirm shows a yes/no confirmation prompt. Escape or Ctrl+C cancels.

func ConfirmDangerous

func ConfirmDangerous(message string) (bool, error)

ConfirmDangerous shows a confirmation prompt for dangerous actions. Escape or Ctrl+C cancels.

func ConfirmSetDefault

func ConfirmSetDefault(valueName string) (bool, error)

ConfirmSetDefault asks the user if they want to save a value as the default. Escape or Ctrl+C cancels.

func DetectDark added in v0.3.0

func DetectDark() bool

DetectDark returns true if the terminal has a dark background. Non-TTY (piped, tests, CI) defaults to true for deterministic output.

func Form

func Form(title string, fields []FormField) (map[string]string, error)

Form shows a multi-field form and returns a map of key -> value.

func Input

func Input(title, placeholder string) (string, error)

Input shows a text input prompt. Escape or Ctrl+C cancels.

func InputRequired

func InputRequired(title, placeholder string) (string, error)

InputRequired shows a required text input prompt. Escape or Ctrl+C cancels.

func MultiSelect

func MultiSelect(title string, options []SelectOption) ([]string, error)

MultiSelect shows a multi-select prompt. Escape or Ctrl+C cancels.

func Note

func Note(title, body string) error

Note shows an informational note (non-interactive).

func RenderWordmark added in v0.3.0

func RenderWordmark(theme Theme) string

RenderWordmark renders the wordmark in Basecamp brand yellow with "Basecamp" to the right of the logo. Returns plain text with NoColorTheme.

func Select

func Select(title string, options []SelectOption) (string, error)

Select shows a single-select prompt. Escape or Ctrl+C cancels.

func SelectScope

func SelectScope() (string, error)

SelectScope shows a prompt for selecting the config scope (global or local).

func SelectWithDescription

func SelectWithDescription(title, description string, options []SelectOption) (string, error)

SelectWithDescription shows a select prompt with descriptions. Escape or Ctrl+C cancels.

func TextArea

func TextArea(title, placeholder string) (string, error)

TextArea shows a multiline text input prompt. Escape or Ctrl+C cancels.

func ThemeFilePath added in v0.2.0

func ThemeFilePath() string

ThemeFilePath returns the resolved path to the active theme file, or "" if using defaults or NO_COLOR is set.

Types

type AnimWriter added in v0.3.0

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

AnimWriter is a mutex-protected io.Writer that tracks terminal rows written below the animation area. The animation goroutine uses this count to cursor-up past both the logo and any caller output, then cursor-down to restore the caller's write position. When cols > 0, it accounts for soft-wrapping at the terminal width.

func (*AnimWriter) Wait added in v0.3.0

func (aw *AnimWriter) Wait()

Wait blocks until the animation goroutine finishes. Idempotent.

func (*AnimWriter) Write added in v0.3.0

func (aw *AnimWriter) Write(p []byte) (int, error)

Write writes p through to the underlying writer and counts visual rows consumed, including rows added by soft-wrapping at the terminal width.

type FormField

type FormField struct {
	Key         string
	Title       string
	Placeholder string
	Required    bool
	Default     string
}

FormField represents a field in a form.

type ItemLoader

type ItemLoader func() ([]PickerItem, error)

ItemLoader is a function that loads items asynchronously.

type PageFetcher

type PageFetcher func(ctx context.Context, cursor string) (*PageResult, error)

PageFetcher fetches a page of items. It receives the cursor from the previous page (empty string for the first page) and returns the items and pagination info.

type PageResult

type PageResult struct {
	Items   []PickerItem
	HasMore bool
	// NextCursor can be used by the PageFetcher to track pagination state.
	// The paginated picker doesn't interpret this value; it just passes it back.
	NextCursor string
}

PageResult represents a page of items from a paginated API.

type PaginatedPicker

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

PaginatedPicker shows a fuzzy-search picker with progressive pagination.

func NewPaginatedPicker

func NewPaginatedPicker(ctx context.Context, fetcher PageFetcher, opts ...PaginatedPickerOption) *PaginatedPicker

NewPaginatedPicker creates a new paginated picker.

func (*PaginatedPicker) Run

func (p *PaginatedPicker) Run() (*PickerItem, error)

Run shows the picker and returns the selected item. Returns nil if the user canceled.

type PaginatedPickerOption

type PaginatedPickerOption func(*paginatedPickerModel)

PaginatedPickerOption configures a paginated picker.

func WithFetchThreshold

func WithFetchThreshold(n int) PaginatedPickerOption

WithFetchThreshold sets how many items from the bottom triggers a fetch.

func WithLoadingMessage

func WithLoadingMessage(msg string) PaginatedPickerOption

WithLoadingMessage sets the loading message.

func WithPaginatedMaxVisible

func WithPaginatedMaxVisible(n int) PaginatedPickerOption

WithPaginatedMaxVisible sets the maximum number of visible items.

func WithPaginatedPickerTitle

func WithPaginatedPickerTitle(title string) PaginatedPickerOption

WithPaginatedPickerTitle sets the picker title.

type Picker

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

Picker shows a fuzzy-search picker and returns the selected item.

func NewPicker

func NewPicker(items []PickerItem, opts ...PickerOption) *Picker

NewPicker creates a new picker.

func NewPickerWithLoader

func NewPickerWithLoader(loader ItemLoader, opts ...PickerOption) *Picker

NewPickerWithLoader creates a picker that loads items asynchronously.

func (*Picker) Run

func (p *Picker) Run() (*PickerItem, error)

Run shows the picker and returns the selected item. Returns nil if the user canceled.

type PickerItem

type PickerItem struct {
	ID          string
	Title       string
	Description string
}

PickerItem represents an item in a picker.

func Pick

func Pick(title string, items []PickerItem) (*PickerItem, error)

Pick is a convenience function for simple picking.

func PickAccount

func PickAccount(accounts []PickerItem) (*PickerItem, error)

PickAccount shows a picker for accounts.

func PickHost

func PickHost(hosts []PickerItem) (*PickerItem, error)

PickHost shows a picker for hosts/environments.

func PickPaginated

func PickPaginated(ctx context.Context, title string, fetcher PageFetcher) (*PickerItem, error)

PickPaginated is a convenience function for paginated picking.

func PickPerson

func PickPerson(people []PickerItem) (*PickerItem, error)

PickPerson shows a picker for people.

func PickProject

func PickProject(projects []PickerItem) (*PickerItem, error)

PickProject shows a picker for projects.

func PickTodolist

func PickTodolist(todolists []PickerItem) (*PickerItem, error)

PickTodolist shows a picker for todolists.

func (PickerItem) FilterValue

func (i PickerItem) FilterValue() string

FilterValue returns the string to filter on.

func (PickerItem) String

func (i PickerItem) String() string

type PickerItemsLoadedMsg

type PickerItemsLoadedMsg struct {
	Items []PickerItem
	Err   error
}

PickerItemsLoadedMsg is sent when items are loaded asynchronously.

type PickerOption

type PickerOption func(*pickerModel)

PickerOption configures a picker.

func WithAutoSelectSingle

func WithAutoSelectSingle() PickerOption

WithAutoSelectSingle automatically selects and returns if only one item exists.

func WithEmptyMessage

func WithEmptyMessage(msg string) PickerOption

WithEmptyMessage sets a custom message shown when no items are available.

func WithHelp

func WithHelp(show bool) PickerOption

WithHelp shows keyboard shortcuts in the picker.

func WithLoading

func WithLoading(msg string) PickerOption

WithLoading sets the picker to start in loading state.

func WithMaxVisible

func WithMaxVisible(n int) PickerOption

WithMaxVisible sets the maximum number of visible items.

func WithPickerTitle

func WithPickerTitle(title string) PickerOption

WithPickerTitle sets the picker title.

func WithRecentItems

func WithRecentItems(items []PickerItem) PickerOption

WithRecentItems prepends recently used items to the list, marked with a prefix.

type SelectOption

type SelectOption struct {
	Value string
	Label string
}

SelectOption represents an option in a select prompt.

type Spinner

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

Spinner runs a spinner while a function executes.

func NewSpinner

func NewSpinner(message string, opts ...SpinnerOption) *Spinner

NewSpinner creates a new spinner with a message.

func (*Spinner) Run

func (s *Spinner) Run(fn func() (string, error)) (string, error)

Run executes the given function while displaying a spinner. Returns the result and any error from the function.

func (*Spinner) RunSimple

func (s *Spinner) RunSimple(fn func() error) error

RunSimple executes a function while displaying a spinner. Use this for functions that don't return a result message.

type SpinnerOption

type SpinnerOption func(*spinnerModel)

SpinnerOption configures a spinner.

func WithSpinnerColor

func WithSpinnerColor(c color.Color) SpinnerOption

WithSpinnerColor sets the spinner color.

func WithSpinnerStyle

func WithSpinnerStyle(style SpinnerStyle) SpinnerOption

WithSpinnerStyle sets the spinner animation style.

type SpinnerStyle

type SpinnerStyle int

SpinnerStyle defines the visual style of a spinner.

const (
	SpinnerDots SpinnerStyle = iota
	SpinnerLine
	SpinnerPulse
	SpinnerPoints
	SpinnerGlobe
	SpinnerMoon
	SpinnerMonkey
	SpinnerMeter
	SpinnerHamburger
)

type Styles

type Styles struct {

	// Text styles
	Title    lipgloss.Style
	Subtitle lipgloss.Style
	Heading  lipgloss.Style
	Body     lipgloss.Style
	Muted    lipgloss.Style
	Bold     lipgloss.Style
	Success  lipgloss.Style
	Warning  lipgloss.Style
	Error    lipgloss.Style

	// Container styles
	Box   lipgloss.Style
	Card  lipgloss.Style
	Panel lipgloss.Style

	// Interactive styles
	Focused  lipgloss.Style
	Selected lipgloss.Style
	Cursor   lipgloss.Style

	// Status styles
	StatusOK    lipgloss.Style
	StatusError lipgloss.Style
	StatusInfo  lipgloss.Style
	// contains filtered or unexported fields
}

Styles holds the styled components for the TUI.

func NewStyles

func NewStyles() *Styles

NewStyles creates a new Styles with the default dark theme.

func NewStylesWithTheme

func NewStylesWithTheme(theme Theme) *Styles

NewStylesWithTheme creates a new Styles with a custom theme.

func (*Styles) RenderCheckbox

func (s *Styles) RenderCheckbox(checked bool, label string) string

RenderCheckbox renders a checkbox item.

func (*Styles) RenderKeyValue

func (s *Styles) RenderKeyValue(key, value string) string

RenderKeyValue renders a key-value pair.

func (*Styles) RenderStatus

func (s *Styles) RenderStatus(ok bool, message string) string

RenderStatus renders a status message with appropriate styling.

func (*Styles) RenderTitle

func (s *Styles) RenderTitle(title string, subtitle ...string) string

RenderTitle renders a title with optional subtitle.

func (*Styles) Theme

func (s *Styles) Theme() Theme

Theme returns the current theme.

func (*Styles) UpdateTheme added in v0.2.0

func (s *Styles) UpdateTheme(theme Theme)

UpdateTheme re-applies a theme to the existing Styles in place. Because all components hold a *Styles pointer, the next View() call picks up the new colors with zero propagation.

type Theme

type Theme struct {
	Dark       bool // how this theme was resolved (for downstream LightDark calls)
	Primary    color.Color
	Secondary  color.Color
	Success    color.Color
	Warning    color.Color
	Error      color.Color
	Muted      color.Color
	Background color.Color
	Foreground color.Color
	Border     color.Color
	RoomColors []color.Color
}

Theme defines the color palette for the TUI.

func DefaultTheme

func DefaultTheme(dark bool) Theme

DefaultTheme returns the default basecamp theme resolved for the given background.

func LoadThemeFromFile

func LoadThemeFromFile(path string, dark bool) (Theme, error)

LoadThemeFromFile parses a colors.toml file and returns a Theme.

func LoadUserTheme

func LoadUserTheme(dark bool) (Theme, error)

LoadUserTheme attempts to load a theme from the user's basecamp config. The theme directory can be a symlink to another theme system.

func NoColorTheme

func NoColorTheme() Theme

NoColorTheme returns a theme with empty colors (honors NO_COLOR standard). lipgloss.NoColor{} means "no styling", resulting in plain text output.

func ResolveTheme

func ResolveTheme(dark bool) Theme

ResolveTheme loads a theme with the following precedence:

  1. NO_COLOR env var set → returns NoColorTheme (industry standard)
  2. BASECAMP_THEME env var → parse custom colors.toml file
  3. User theme from ~/.config/basecamp/theme/colors.toml
  4. Default basecamp theme

On systems like Omarchy, users can symlink to their system theme:

ln -s ~/.config/omarchy/current/theme ~/.config/basecamp/theme

type TraceFunc added in v0.3.0

type TraceFunc func(grid [][]rune, numLines int) []paintCell

TraceFunc computes the order in which non-blank cells are revealed. It receives the rune grid and returns cells in first-visit order.

Directories

Path Synopsis
Package empty provides empty state messages for TUI components.
Package empty provides empty state messages for TUI components.
Package format provides formatting helpers for TUI components.
Package format provides formatting helpers for TUI components.
Package recents provides a store for tracking recently used items.
Package recents provides a store for tracking recently used items.
Package resolve provides interactive prompts for resolving missing CLI options.
Package resolve provides interactive prompts for resolving missing CLI options.
Package workspace provides the persistent TUI application.
Package workspace provides the persistent TUI application.
chrome
Package chrome provides always-visible shell components for the workspace.
Package chrome provides always-visible shell components for the workspace.
views
Package views provides the individual screens for the workspace TUI.
Package views provides the individual screens for the workspace TUI.
widget
Package widget provides reusable TUI components.
Package widget provides reusable TUI components.

Jump to

Keyboard shortcuts

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