blit

package module
v0.2.24 Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2026 License: MIT Imports: 49 Imported by: 0

README

blit

CI Go Reference Go Report Card Latest Release

The pragmatic TUI toolkit for shipping CLI tools fast. Wraps Bubble Tea + Lip Gloss with reusable components, a layout engine, a keybinding registry, a theme system, and built-in binary self-update.

Features

  • 30+ components — Table (virtualized, 1M+ rows), Tree, Form, Tabs, Picker, FilePicker, LogViewer, ListView, and more
  • Rich overlays — Dialog, Menu, Tooltip, Toast notifications, command bar
  • Interactive widgets — Accordion, Stepper, Spinner, ProgressBar, Timeline, Kanban, Breadcrumb
  • Layout system — dual-pane, HBox/VBox flex, split panes with draggable dividers
  • Charts — bar, line, ring, gauge, heatmap
  • 11 theme presets — Dracula, Catppuccin Mocha, Tokyo Night, Nord, Gruvbox Dark, Rose Pine, Kanagawa, One Dark, Solarized Dark, Everforest, Nightfox
  • Theme system — semantic color tokens, hot-reload, terminal theme importers (iTerm2, Alacritty, Gogh)
  • Keybinding registry with auto-generated help screen
  • CLI primitives (confirm, select, input, spinner, progress) for non-TUI workflows
  • btest virtual terminal testing framework with golden files, snapshot diffing, and a vitest-style CLI runner
  • Self-update — binary replacement with SHA256/cosign verification, delta patches, rollback, channels, and rate-limit backoff
  • SSH serve — host any blit app over SSH via Charm Wish

Install

go get github.com/blitui/blit

blit CLI (project scaffolding, test runner, dev tools):

# Homebrew
brew install blitui/tap/blit

# Scoop
scoop bucket add blitui https://github.com/blitui/scoop-bucket
scoop install blit

# Go
go install github.com/blitui/blit/cmd/blit@latest

Quick Start

Scaffold a new project with the CLI:

blit init

Choose from three starter templates (minimal, dashboard, form) and get a buildable project with tests out of the box.

Or start from scratch:

package main

import (
    "fmt"
    blit "github.com/blitui/blit"
)

func main() {
    table := blit.NewTable(
        []blit.Column{
            {Title: "Name", Width: 20, Sortable: true},
            {Title: "Status", Width: 15},
        },
        []blit.Row{
            {"Alice", "Online"},
            {"Bob", "Away"},
        },
        blit.TableOpts{Sortable: true, Filterable: true},
    )

    app := blit.NewApp(
        blit.WithTheme(blit.DefaultTheme()),
        blit.WithComponent("main", table),
        blit.WithStatusBar(
            func() string { return " ? help  q quit" },
            func() string { return fmt.Sprintf(" %d items", 2) },
        ),
        blit.WithHelp(),
    )

    app.Run()
}

More examples in examples/.

Documentation

  • Docs site — guides, component reference, theming, self-update setup
  • Examples — 15 runnable demos from minimal to full dashboard
  • pkg.go.dev — API reference

Repository Layout

Directory Purpose
charts/ Chart components (bar, line, ring, gauge, heatmap)
cli/ Interactive CLI prompt primitives (non-TUI)
cmd/ CLI binaries (blit runner)
docs/ Design docs and generated GIFs
examples/ Runnable example apps
internal/ Private packages (fuzzy search, scaffold, tape)
scripts/ GIF generation and VHS tape scripts
site/ MkDocs Material documentation site
templates/ Starter project template
testdata/ Test fixtures (theme files)
btest/ Virtual terminal testing framework
updatetest/ Self-updater test mocks

Used By

Compatibility

blit follows semantic versioning. Within a major version, the public API is stable — no breaking changes in minor or patch releases. Pre-v1.0 releases (v0.x) may include breaking changes in minor versions, documented in the changelog.

Contributing

See CONTRIBUTING.md.

License

MIT

Documentation

Overview

Package blit is a pragmatic TUI toolkit for shipping Go CLI tools fast.

It wraps Bubble Tea and Lip Gloss with reusable components (Table, ListView, Tabs, Picker, Form, Tree, LogViewer), a layout engine (DualPane, HBox, VBox, Split), a keybinding registry with auto-generated help, a dark/light theme system with hot-reload, and built-in binary self-update.

All bubbletea and lipgloss types are re-exported so consumers only need to import blit: Msg, Cmd, KeyMsg, Color, Style, NewStyle, JoinVertical, etc.

Quick start:

app := blit.NewApp(
    blit.WithTheme(blit.DefaultTheme()),
    blit.WithComponent("main", myTable),
    blit.WithHelp(),
)
app.Run()

See https://blitui.github.io/blit/ for guides and examples.

Package blit provides TUI components and update utilities.

Cosign signature verification — implementation notes:

We deliberately avoid the full sigstore/cosign library (github.com/sigstore/cosign) because it pulls in hundreds of transitive dependencies (OCI registry clients, Fulcio/Rekor TLS stacks, OIDC flows) that would bloat every consumer binary.

Instead we implement the narrow subset that covers the common offline case: a detached ed25519 signature over the raw asset bytes, stored as a <asset>.sig release attachment and signed with `cosign sign-blob --key <ed25519.key>`. The corresponding public key (PEM or bare base64) is embedded in UpdateConfig.

If CosignPublicKey is empty the verification step is skipped entirely, keeping the feature strictly opt-in and zero-cost for existing consumers.

Index

Examples

Constants

View Source
const (
	ChannelStable     = "stable"
	ChannelBeta       = "beta"
	ChannelPrerelease = "prerelease"
)

Update channels.

View Source
const DeltaPatchSuffix = ".bsdiff"

DeltaPatchSuffix is appended to the binary name when building a delta patch asset name. A patch asset is expected to be named:

<binary>_<fromVersion>_to_<toVersion>_<goos>_<goarch>.bsdiff

The <fromVersion> is the version the patch applies against (the caller's current version) and <toVersion> is the version the release publishes.

View Source
const EnvDisableUpdate = "BLIT_UPDATE_DISABLE"

EnvDisableUpdate is the environment variable name that, when set to "1", "true", or "yes" (case-insensitive), short-circuits CheckForUpdate and SelfUpdate without making any network calls. Intended as a kill switch for CI, tests, and users who want to disable updates temporarily without changing code.

Variables

View Source
var (
	KeyUp        = tea.KeyUp
	KeyDown      = tea.KeyDown
	KeyLeft      = tea.KeyLeft
	KeyRight     = tea.KeyRight
	KeyHome      = tea.KeyHome
	KeyEnd       = tea.KeyEnd
	KeyPgUp      = tea.KeyPgUp
	KeyPgDown    = tea.KeyPgDown
	KeyDelete    = tea.KeyDelete
	KeyInsert    = tea.KeyInsert
	KeyBackspace = tea.KeyBackspace
	KeySpace     = tea.KeySpace
	KeyTab       = tea.KeyTab
	KeyShiftTab  = tea.KeyShiftTab
	KeyEnter     = tea.KeyEnter
	KeyEscape    = tea.KeyEscape
	KeyRunes     = tea.KeyRunes
)

Arrow and navigation keys.

View Source
var (
	KeyCtrlA = tea.KeyCtrlA
	KeyCtrlB = tea.KeyCtrlB
	KeyCtrlC = tea.KeyCtrlC
	KeyCtrlD = tea.KeyCtrlD
	KeyCtrlE = tea.KeyCtrlE
	KeyCtrlF = tea.KeyCtrlF
	KeyCtrlG = tea.KeyCtrlG
	KeyCtrlH = tea.KeyCtrlH
	KeyCtrlJ = tea.KeyCtrlJ
	KeyCtrlK = tea.KeyCtrlK
	KeyCtrlL = tea.KeyCtrlL
	KeyCtrlN = tea.KeyCtrlN
	KeyCtrlO = tea.KeyCtrlO
	KeyCtrlP = tea.KeyCtrlP
	KeyCtrlQ = tea.KeyCtrlQ
	KeyCtrlR = tea.KeyCtrlR
	KeyCtrlS = tea.KeyCtrlS
	KeyCtrlT = tea.KeyCtrlT
	KeyCtrlU = tea.KeyCtrlU
	KeyCtrlV = tea.KeyCtrlV
	KeyCtrlW = tea.KeyCtrlW
	KeyCtrlX = tea.KeyCtrlX
	KeyCtrlY = tea.KeyCtrlY
	KeyCtrlZ = tea.KeyCtrlZ
)

Control keys.

View Source
var (
	F1  = tea.KeyF1
	F2  = tea.KeyF2
	F3  = tea.KeyF3
	F4  = tea.KeyF4
	F5  = tea.KeyF5
	F6  = tea.KeyF6
	F7  = tea.KeyF7
	F8  = tea.KeyF8
	F9  = tea.KeyF9
	F10 = tea.KeyF10
	F11 = tea.KeyF11
	F12 = tea.KeyF12
)

Function keys.

View Source
var (
	KeyCtrlBackslash = tea.KeyCtrlBackslash
	KeyShiftDown     = tea.KeyShiftDown
	KeyShiftUp       = tea.KeyShiftUp
	KeyShiftLeft     = tea.KeyShiftLeft
	KeyShiftRight    = tea.KeyShiftRight
)

Special keys.

View Source
var (
	// Batch performs the given commands simultaneously with no ordering
	// guarantees about the results.
	Batch = tea.Batch

	// Quit is a command that tells the Bubble Tea runtime to exit.
	Quit = tea.Quit

	// Sequence runs the given commands one at a time, in order.
	Sequence = tea.Sequence
)
View Source
var (
	// NewStyle creates a new Style.
	NewStyle = lipgloss.NewStyle

	// Width measures the visual width of a string, accounting for ANSI
	// escape sequences and double-width runes.
	Width = lipgloss.Width

	// Height measures the visual height of a string (number of newlines).
	Height = lipgloss.Height

	// JoinVertical joins strings vertically, aligned along the given
	// position.
	JoinVertical = lipgloss.JoinVertical

	// JoinHorizontal joins strings horizontally, aligned along the given
	// position.
	JoinHorizontal = lipgloss.JoinHorizontal

	// Place places a string or text block in a box of the given dimensions.
	Place = lipgloss.Place
)
View Source
var (
	// PosCenter is lipgloss.Center, for use with Place and JoinVertical.
	PosCenter = lipgloss.Center
	// PosTop is lipgloss.Top, for use with Place and JoinVertical.
	PosTop = lipgloss.Top
	// PosBottom is lipgloss.Bottom, for use with Place and JoinVertical.
	PosBottom = lipgloss.Bottom
	// PosLeft is lipgloss.Left, for use with Place and JoinHorizontal.
	PosLeft = lipgloss.Left
	// PosRight is lipgloss.Right, for use with Place and JoinHorizontal.
	PosRight = lipgloss.Right
)
View Source
var (
	RoundedBorder = lipgloss.RoundedBorder
	DoubleBorder  = lipgloss.DoubleBorder
	ThickBorder   = lipgloss.ThickBorder
	ASCIIBorder   = lipgloss.ASCIIBorder
	NormalBorder  = lipgloss.NormalBorder
)
View Source
var (
	// StringWidth measures the visual width of a string, accounting for
	// ANSI escape sequences and East Asian wide characters.
	StringWidth = ansi.StringWidth

	// TruncateWith truncates a string to the given visual width, appending
	// the tail string if truncation occurs. Use this when you need a custom
	// tail indicator. For the common case (tail = "…"), use blit.Truncate.
	TruncateWith = ansi.Truncate
)

Functions

func ApplyDeltaPatch

func ApplyDeltaPatch(exePath string, patch []byte) ([]byte, error)

ApplyDeltaPatch reconstructs the new binary by applying a bsdiff patch to the current on-disk binary at exePath. The returned bytes are the new binary contents ready for checksum verification and replacement. On any failure the caller should fall back to a full download.

func Badge

func Badge(text string, fg lipgloss.Color, bold bool) string

Badge renders a short text label with foreground color and optional bold. Useful for category tags in detail bars and status displays.

func CleanupOldBinary

func CleanupOldBinary()

CleanupOldBinary removes a leftover .old binary from a previous update. Call this early in main() or in the update check flow.

func ClearSkippedVersions

func ClearSkippedVersions(cfg UpdateConfig) error

ClearSkippedVersions removes all skip entries. Useful for tests and for a "reset" menu item in a consumer app.

func Consumed

func Consumed() tea.Cmd

Consumed returns a tea.Cmd that signals the App that a key was handled. When a component's Update returns this, the App stops dispatching the key to other components.

func Contrast

func Contrast(bg, fg lipgloss.Color) float64

Contrast computes the WCAG 2.1 contrast ratio between bg and fg colors. Returns a value in [1, 21]; 4.5 satisfies WCAG AA for normal text.

func CopyToClipboardCmd added in v0.1.1

func CopyToClipboardCmd(text string) tea.Cmd

CopyToClipboardCmd returns a tea.Cmd that copies text to the system clipboard using the OSC 52 escape sequence. This works over SSH and in most modern terminal emulators without requiring external tools.

func CopyToClipboardWithNotify added in v0.1.1

func CopyToClipboardWithNotify(text string) tea.Cmd

CopyToClipboardWithNotify returns a tea.Batch that copies text to the clipboard and sends a CopyToClipboardMsg so the app can show feedback.

func DefaultConfigPath added in v0.1.1

func DefaultConfigPath(appName string) (string, error)

DefaultConfigPath returns the default configuration file path for an application: <UserConfigDir>/<appName>/config.yaml. On Linux this is typically ~/.config/<appName>/config.yaml.

func DevConsoleToggleCmd

func DevConsoleToggleCmd() tea.Cmd

DevConsoleToggleCmd returns a tea.Cmd that toggles the dev console.

func Divider

func Divider(width int, theme Theme) string

Divider renders a horizontal line of ─ characters at the given width, styled with the theme's Border color.

func EaseInCubic

func EaseInCubic(t float64) float64

EaseInCubic - slow start, fast end.

func EaseInOut

func EaseInOut(t float64) float64

EaseInOut - slow start and end, fast middle.

func EaseOutCubic

func EaseOutCubic(t float64) float64

EaseOutCubic - fast start, slow end.

func EaseOutExpo

func EaseOutExpo(t float64) float64

EaseOutExpo - exponential deceleration.

func EnsureConfigDir added in v0.1.1

func EnsureConfigDir(appName string) (string, error)

EnsureConfigDir creates the configuration directory for appName if it does not already exist. Returns the directory path.

func ExtractBinary

func ExtractBinary(archive []byte, binaryName, format string) ([]byte, error)

ExtractBinary extracts the named binary from a tar.gz or zip archive.

func GitHubAPIURL added in v0.2.24

func GitHubAPIURL(endpoint string, perPage, page int) string

GitHubAPIURL builds a GitHub API URL for the given endpoint with per_page and page parameters. This is the most common use case for TUI apps that poll GitHub.

func HealthDot added in v0.2.24

func HealthDot(label string, ok bool, theme Theme) string

HealthDot renders a coloured dot indicator for a status line. ok=true shows a positive (green) dot, ok=false shows a negative (red) dot, and unknown shows a muted dot. The label is rendered in Muted after the dot.

func HealthDotUnknown added in v0.2.24

func HealthDotUnknown(label string, theme Theme) string

HealthDotUnknown renders a muted empty dot for an unknown/unchecked status.

func Hyperlink(url, text string) string

Hyperlink is an alias for OSC8Link — wraps text in a clickable terminal hyperlink. Supported in modern terminals (iTerm2, Kitty, WezTerm, Windows Terminal, etc.).

func Interpolate

func Interpolate[T any](from, to T, t float64, e Ease) T

Interpolate interpolates between from and to using easing e at progress t in [0,1]. Supported types: float64, int, lipgloss.Color.

func IsBackspace added in v0.2.24

func IsBackspace(msg Msg) bool

IsBackspace reports whether msg is the Backspace key.

func IsEnter added in v0.2.24

func IsEnter(msg Msg) bool

IsEnter reports whether msg is the Enter key.

func IsEscape added in v0.2.24

func IsEscape(msg Msg) bool

IsEscape reports whether msg is the Escape key.

func IsKey added in v0.2.24

func IsKey(msg Msg, key string) bool

IsKey reports whether msg is a KeyMsg whose string representation equals key.

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited reports whether err is a RateLimitError.

func IsRunes added in v0.2.24

func IsRunes(msg Msg) bool

IsRunes reports whether msg is a KeyRunes event (regular character input).

func IsTab added in v0.2.24

func IsTab(msg Msg) bool

IsTab reports whether msg is the Tab key.

func IsVersionSkipped

func IsVersionSkipped(cfg UpdateConfig, v string) bool

IsVersionSkipped reports whether v has been previously passed to SkipVersion for this cfg. Missing file or unreadable file returns false.

func KeyString added in v0.2.24

func KeyString(msg Msg) string

KeyString returns the string representation of a KeyMsg, or "" if msg is not a KeyMsg.

func Linear

func Linear(t float64) float64

Linear easing - constant rate.

func LoadYAML added in v0.1.1

func LoadYAML(path string, dst any) error

LoadYAML reads a YAML file at path and unmarshals it into dst. dst must be a pointer to the target struct. If the file does not exist, dst is left unchanged and no error is returned, allowing callers to rely on struct zero values as defaults.

func LogAppendCmd

func LogAppendCmd(line LogLine) tea.Cmd

LogAppendCmd returns a tea.Cmd that appends a LogLine to any LogViewer that receives it via Update.

func LogRedact added in v0.2.24

func LogRedact(v any) slog.LogValuer

LogRedact wraps a value so that slog emits "[REDACTED]" instead of the actual content. Use it when logging sensitive data (tokens, keys, paths) that should not appear in log output.

func Markdown

func Markdown(md string, theme Theme) string

Markdown renders md as a terminal-formatted string styled using the semantic color tokens from theme. Headings use theme.Accent, code block backgrounds use theme.Muted, body text uses theme.Text.

The rendered string includes trailing newlines added by glamour; callers may trim with strings.TrimSpace if needed.

func NotifyCmd

func NotifyCmd(text string, duration time.Duration) tea.Cmd

NotifyCmd returns a tea.Cmd that sends a NotifyMsg.

func OSC8Link(url, text string) string

OSC8Link wraps text in an OSC8 terminal hyperlink escape sequence. If url is empty, the plain text is returned unchanged.

func OpenURL

func OpenURL(url string)

OpenURL opens a URL in the user's default browser. It runs the command asynchronously and does not block.

func ParseJSONObject added in v0.2.24

func ParseJSONObject[T any]() func(body []byte) (any, error)

ParseJSONObject is a convenience Parse function for APIs that return a single JSON object of type T.

func ParseJSONSlice added in v0.2.24

func ParseJSONSlice[T any]() func(body []byte) (any, error)

ParseJSONSlice is a convenience Parse function for APIs that return a JSON array of type T.

func Presets

func Presets() map[string]Theme

Presets returns a copy of the global theme registry.

func Register

func Register(name string, t Theme)

Register adds a named theme to the global preset registry.

func RelativeTime

func RelativeTime(t time.Time, now time.Time) string

RelativeTime returns a short human-readable duration string like "3m ago" or "2h ago". If the duration is negative (future time), it returns "now".

func RenderGradient

func RenderGradient(text string, g Gradient) string

RenderGradient renders text with the given gradient. Convenience wrapper for Gradient.RenderText.

func RetryCmd added in v0.1.1

func RetryCmd(fn func() (tea.Msg, error), opts RetryOpts) tea.Cmd

RetryCmd wraps a fallible function with exponential backoff retry. On the first successful call, the resulting tea.Msg is returned. If all attempts fail, a RetryErrorMsg is returned.

Usage with Poller:

poller := NewPoller(30*time.Second, func() tea.Cmd {
    return RetryCmd(fetchData, RetryOpts{MaxAttempts: 3, Backoff: 500 * time.Millisecond})
})

func Runes added in v0.2.24

func Runes(msg Msg) []rune

Runes returns the typed rune characters if msg is a KeyRunes event, or nil otherwise.

func SaveYAML added in v0.1.1

func SaveYAML(path string, src any) error

SaveYAML marshals src to YAML and writes it atomically to path. The file is written to a temporary location first, then renamed to avoid partial writes on crash.

func SelfUpdate

func SelfUpdate(cfg UpdateConfig) error

SelfUpdate downloads the latest release and replaces the current binary. Only works for manual installs (not Homebrew/Scoop). Honors the BLIT_UPDATE_DISABLE env var, cfg.Disabled, and cfg.Mode == UpdateDryRun (which logs every step without writing anything). Before/After/Error hooks on cfg are called at the corresponding points.

func SelfUpdateRollback

func SelfUpdateRollback() error

SelfUpdateRollback restores the previous binary from <exePath>.old. Returns an error if no .old file exists or the restore fails. Used when a post-install verification step detects a broken new binary.

func Serve

func Serve(ctx context.Context, cfg ServeConfig) error

Serve hosts a blit App over SSH via Charm Wish. It blocks until ctx is cancelled or the server exits.

Each inbound SSH session receives a fresh *App produced by cfg.Factory, ensuring per-connection state isolation.

blit.Serve(ctx, blit.ServeConfig{
    Addr:    ":2222",
    Factory: func() *blit.App { return blit.NewApp(...) },
})

func SetThemeCmd

func SetThemeCmd(t Theme) func() tea.Msg

SetThemeCmd returns a tea.Cmd that emits a SetThemeMsg.

func SkipVersion

func SkipVersion(cfg UpdateConfig, v string) error

SkipVersion marks v as skipped so future CheckForUpdate calls return Available=false for that exact tag. Writes to <CacheDir>/skipped-versions.json. Errors are returned but not logged.

func Sparkline

func Sparkline(data []float64, maxWidth int, opts *SparklineOpts) (string, int)

Sparkline renders a Unicode block sparkline from a slice of float64 values. The output is trimmed or sampled to fit within maxWidth characters. Each bar uses one of ▁▂▃▄▅▆▇█ based on the value's position in the min-max range. Returns the styled string and the number of characters rendered.

func ToastCmd

func ToastCmd(severity ToastSeverity, title, body string, duration time.Duration, actions ...ToastAction) tea.Cmd

ToastCmd returns a tea.Cmd that sends a ToastMsg.

func ToastError added in v0.1.1

func ToastError(title, body string) tea.Cmd

ToastError returns a tea.Cmd that shows an error toast with a 6s duration.

func ToastInfo added in v0.1.1

func ToastInfo(title, body string) tea.Cmd

ToastInfo returns a tea.Cmd that shows an informational toast with a 4s duration.

func ToastSuccess added in v0.1.1

func ToastSuccess(title, body string) tea.Cmd

ToastSuccess returns a tea.Cmd that shows a success toast with a 4s duration.

func ToastWarn added in v0.1.1

func ToastWarn(title, body string) tea.Cmd

ToastWarn returns a tea.Cmd that shows a warning toast with a 6s duration.

func Truncate

func Truncate(s string, maxWidth int) string

Truncate shortens s to maxWidth characters, appending "…" if truncated. Uses visual width (lipgloss.Width) so ANSI sequences are handled correctly. If s fits within maxWidth, it is returned unchanged.

func ValidateConfig

func ValidateConfig(cfg UpdateConfig) error

ValidateConfig checks that cfg has all required fields set. Returns a descriptive error if any required field is missing.

func VerifyChecksum

func VerifyChecksum(data []byte, assetName string, checksumFile []byte) error

VerifyChecksum verifies the SHA256 checksum of data against a GoReleaser checksums.txt file. The checksums file format is: "<hex> <filename>\n" per line.

func VerifyCosignSignature

func VerifyCosignSignature(assetData []byte, sigData []byte, pubKeyPEM string) error

VerifyCosignSignature verifies a detached ed25519 signature over assetData.

sigData is the raw content of the <asset>.sig file as produced by `cosign sign-blob --key <ed25519.key>` — a base64-encoded signature. pubKeyPEM is the signer's public key in PEM or bare base64 format.

func VerifyInstalled

func VerifyInstalled(expectedTag string) error

VerifyInstalled spawns the newly-installed binary with "--version" and checks its output contains the expected tag. If it does not, the update is rolled back via SelfUpdateRollback. Intended to run immediately after SelfUpdate in modes that can recover from a bad install.

func WriteCache

func WriteCache(path string, cache UpdateCache) error

WriteCache writes the update check result to disk.

Types

type Accordion added in v0.2.12

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

Accordion is a vertically stacked set of collapsible sections. Implements Component and Themed.

func NewAccordion added in v0.2.12

func NewAccordion(sections []AccordionSection, opts AccordionOpts) *Accordion

NewAccordion creates an Accordion with the given sections and options.

func (*Accordion) CursorIndex added in v0.2.12

func (a *Accordion) CursorIndex() int

CursorIndex returns the currently highlighted section index.

func (*Accordion) Focused added in v0.2.12

func (a *Accordion) Focused() bool

Focused implements Component.

func (*Accordion) Init added in v0.2.12

func (a *Accordion) Init() tea.Cmd

Init implements Component.

func (*Accordion) KeyBindings added in v0.2.12

func (a *Accordion) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Accordion) Sections added in v0.2.12

func (a *Accordion) Sections() []AccordionSection

Sections returns the current sections.

func (*Accordion) SetFocused added in v0.2.12

func (a *Accordion) SetFocused(f bool)

SetFocused implements Component.

func (*Accordion) SetSize added in v0.2.12

func (a *Accordion) SetSize(w, h int)

SetSize implements Component.

func (*Accordion) SetTheme added in v0.2.12

func (a *Accordion) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Accordion) Update added in v0.2.12

func (a *Accordion) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Accordion) View added in v0.2.12

func (a *Accordion) View() string

View implements Component.

type AccordionOpts added in v0.2.12

type AccordionOpts struct {
	// Exclusive limits expansion to one section at a time (true = only one open).
	Exclusive bool

	// OnToggle is called when a section is expanded or collapsed.
	OnToggle func(index int, expanded bool)
}

AccordionOpts configures an Accordion.

type AccordionSection added in v0.2.12

type AccordionSection struct {
	// Title is the header text.
	Title string
	// Content is the body text shown when expanded.
	Content string
	// Expanded controls whether this section is open.
	Expanded bool
}

AccordionSection is a collapsible section in an Accordion.

type Activatable

type Activatable interface {
	SetActive(bool)
}

Activatable is implemented by overlays that can be explicitly activated.

type Alignment

type Alignment int

Alignment controls text alignment in table columns.

const (
	// Left aligns text to the left (default).
	Left Alignment = iota
	// Right aligns text to the right.
	Right
	// Center aligns text to the center.
	Center
)

type AnySignal

type AnySignal interface {
	// contains filtered or unexported methods
}

AnySignal is the untyped interface implemented by every *Signal[T]. It is used as the dependency type for Computed so that signals of mixed element types can be combined.

type App

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

App is the main entry point for a blit application.

func NewApp

func NewApp(opts ...Option) *App

NewApp creates a new App with the given options.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	app := blit.NewApp(
		blit.WithTheme(blit.DefaultTheme()),
		blit.WithHelp(),
	)
	// app.Run() starts the TUI event loop.
	_ = app
}
Example (WithStatusBar)
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	app := blit.NewApp(
		blit.WithTheme(blit.DefaultTheme()),
		blit.WithStatusBar(
			func() string { return " ? help  q quit" },
			func() string { return "" },
		),
		blit.WithHelp(),
	)
	_ = app
}

func (*App) AddKeyBind

func (a *App) AddKeyBind(kb KeyBind)

AddKeyBind adds a global keybinding after construction. The binding appears in the help screen and its Handler is called on key press.

func (*App) Done added in v0.2.24

func (a *App) Done() <-chan struct{}

Done returns a channel that is closed when the App finishes running. Use this to orchestrate clean shutdown of background goroutines:

go func() {
    <-app.Done()
    close(dbConn)
}()

func (*App) Model

func (a *App) Model() tea.Model

Model returns the underlying tea.Model for use with btest or other testing frameworks that need a tea.Model directly.

func (*App) Notify

func (a *App) Notify(msg string, duration time.Duration)

Notify displays a timed notification. If duration is 0, defaults to 2 seconds.

func (*App) Run

func (a *App) Run() (UpdateAction, error)

Run starts the TUI application. It blocks until the user quits.

If WithAutoUpdate is configured, Run may return with an UpdateAction requesting the caller to restart or exit instead of running the TUI. Check the returned UpdateAction:

action, err := app.Run()
if action == blit.UpdateActionRestart {
    // Binary was replaced; advise user to relaunch.
}

func (*App) Send

func (a *App) Send(msg tea.Msg)

Send pushes a message into the running App from outside the Bubble Tea event loop. Use this to push data from background goroutines (WebSocket streams, API polling, etc.). The message will be delivered to all components via Update.

func (*App) ToastError added in v0.2.24

func (a *App) ToastError(title, body string)

ToastError sends an error toast with a 6s duration.

func (*App) ToastInfo added in v0.2.24

func (a *App) ToastInfo(title, body string)

ToastInfo sends an informational toast with a 4s duration.

func (*App) ToastSuccess added in v0.2.24

func (a *App) ToastSuccess(title, body string)

ToastSuccess sends a success toast with a 4s duration.

func (*App) ToastWarn added in v0.2.24

func (a *App) ToastWarn(title, body string)

ToastWarn sends a warning toast with a 6s duration.

type BackoffStrategy added in v0.1.3

type BackoffStrategy interface {
	// NextBackoff returns the delay before the next retry attempt.
	// A negative return value means no more retries.
	NextBackoff(attempt int) time.Duration
}

BackoffStrategy defines retry behavior on transient errors.

func ExponentialBackoff added in v0.1.3

func ExponentialBackoff(initial, max time.Duration) BackoffStrategy

ExponentialBackoff returns a strategy starting at initial, doubling each attempt, capped at max.

Example
package main

import (
	"fmt"
	"time"

	blit "github.com/blitui/blit"
)

func main() {
	backoff := blit.ExponentialBackoff(time.Second, 5*time.Minute)

	fmt.Println(backoff.NextBackoff(0)) // 1s
	fmt.Println(backoff.NextBackoff(1)) // 2s
	fmt.Println(backoff.NextBackoff(2)) // 4s
}
Output:
1s
2s
4s

func FixedBackoff added in v0.1.3

func FixedBackoff(delay time.Duration, maxAttempts int) BackoffStrategy

FixedBackoff returns a strategy with constant delay for up to maxAttempts.

Example
package main

import (
	"fmt"
	"time"

	blit "github.com/blitui/blit"
)

func main() {
	backoff := blit.FixedBackoff(2*time.Second, 3)

	fmt.Println(backoff.NextBackoff(0)) // 2s
	fmt.Println(backoff.NextBackoff(2)) // 2s
	fmt.Println(backoff.NextBackoff(3)) // -1ns (no more retries)
}
Output:
2s
2s
-1ns

func NoBackoff added in v0.1.3

func NoBackoff() BackoffStrategy

NoBackoff returns a strategy that never retries.

type Border added in v0.2.24

type Border = lipgloss.Border

Border is an alias for lipgloss.Border, a set of border characters.

type BorderSet

type BorderSet struct {
	Rounded lipgloss.Border
	Double  lipgloss.Border
	Thick   lipgloss.Border
	Ascii   lipgloss.Border
	Minimal lipgloss.Border
}

BorderSet groups named lipgloss border styles for consistent component use.

func DefaultBorders

func DefaultBorders() BorderSet

DefaultBorders returns the standard lipgloss border set.

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

Breadcrumb is an interactive, cursor-driven breadcrumb navigation component with selection support. It displays a navigable path of items and allows the user to move between them with keyboard input and invoke an OnSelect callback. It implements Component and Themed.

For a simple display-only path trail, see Breadcrumbs.

func NewBreadcrumb added in v0.2.12

func NewBreadcrumb(items []BreadcrumbItem, opts BreadcrumbOpts) *Breadcrumb

NewBreadcrumb creates a Breadcrumb with the given items and options.

func (b *Breadcrumb) CursorIndex() int

CursorIndex returns the currently highlighted item index.

func (b *Breadcrumb) Focused() bool

Focused implements Component.

func (b *Breadcrumb) Init() tea.Cmd

Init implements Component.

func (b *Breadcrumb) Items() []BreadcrumbItem

Items returns the current breadcrumb items.

func (b *Breadcrumb) KeyBindings() []KeyBind

KeyBindings implements Component.

func (b *Breadcrumb) Pop() BreadcrumbItem

Pop removes and returns the last item, moving the cursor back. Returns the zero value if there are no items.

func (b *Breadcrumb) Push(item BreadcrumbItem)

Push appends an item and moves the cursor to it.

func (b *Breadcrumb) SetFocused(f bool)

SetFocused implements Component.

func (b *Breadcrumb) SetItems(items []BreadcrumbItem)

SetItems replaces the items and resets the cursor to the last item.

func (b *Breadcrumb) SetSize(w, h int)

SetSize implements Component.

func (b *Breadcrumb) SetTheme(theme Theme)

SetTheme implements Themed.

func (b *Breadcrumb) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (b *Breadcrumb) View() string

View implements Component.

type BreadcrumbItem struct {
	// Label is the display text.
	Label string
	// Data is an arbitrary payload the caller can attach.
	Data any
}

BreadcrumbItem is a single segment in a Breadcrumb path.

type BreadcrumbOpts struct {
	// Separator is the string between items. Defaults to " > ".
	Separator string

	// OnSelect is called when enter is pressed on an item.
	OnSelect func(item BreadcrumbItem, index int)
}

BreadcrumbOpts configures a Breadcrumb.

type Breadcrumbs struct {
	// Segments are the individual path parts, e.g. []string{"home", "docs", "api"}.
	Segments []string

	// Separator is placed between segments. Defaults to " / ".
	Separator string

	// MaxWidth is the maximum render width in columns. 0 means unlimited.
	MaxWidth int
	// contains filtered or unexported fields
}

Breadcrumbs is a passive, display-only path trail. It renders a horizontal sequence of path segments separated by a configurable separator. When the rendered width exceeds MaxWidth the leading segments are replaced with "…" until it fits.

For an interactive breadcrumb with cursor navigation and selection, see Breadcrumb.

func NewBreadcrumbs

func NewBreadcrumbs(segments []string) *Breadcrumbs

NewBreadcrumbs creates a Breadcrumbs component with default separator " / ".

func (b *Breadcrumbs) Focused() bool

Focused reports whether the Breadcrumbs is focused.

func (b *Breadcrumbs) Init() tea.Cmd

Init initializes the Breadcrumbs component. It returns nil.

func (b *Breadcrumbs) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Breadcrumbs.

func (b *Breadcrumbs) SetFocused(f bool)

SetFocused sets the focus state of the Breadcrumbs.

func (b *Breadcrumbs) SetSize(w, h int)

SetSize sets the width and height of the Breadcrumbs.

func (b *Breadcrumbs) SetTheme(th Theme)

SetTheme updates the theme used by the Breadcrumbs.

func (b *Breadcrumbs) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Breadcrumbs state.

func (b *Breadcrumbs) View() string

View renders the Breadcrumbs as a string.

type CLIApp added in v0.2.24

type CLIApp struct {
	Name     string
	Version  string
	Commands []Subcommand
	RunTUI   func() error
}

CLIApp is a lightweight subcommand router for TUI applications. Many TUI apps need a CLI layer for config management (add/remove/list) alongside the main TUI. CLIApp handles this pattern uniformly.

Usage:

app := blit.NewCLIApp(blit.CLIAppOpts{
    Name:    "myapp",
    Version: "1.0.0",
    Commands: []blit.Subcommand{
        {Name: "add", Usage: "add <item>", Run: func(args []string) error { ... }},
        {Name: "list", Aliases: []string{"ls"}, Run: func(args []string) error { ... }},
    },
    RunTUI: func() error { return runTUI() },
})
os.Exit(app.Execute(os.Args[1:]))

func NewCLIApp added in v0.2.24

func NewCLIApp(opts CLIAppOpts) *CLIApp

NewCLIApp creates a CLIApp with the given options.

func (*CLIApp) Execute added in v0.2.24

func (a *CLIApp) Execute(args []string) int

Execute dispatches a subcommand or launches the TUI. It returns an exit code: 0 for success, 1 for error. When no subcommand matches, it calls RunTUI. When args is empty, it also calls RunTUI.

func (*CLIApp) PrintHelp added in v0.2.24

func (a *CLIApp) PrintHelp()

PrintHelp prints usage information for all registered subcommands.

type CLIAppOpts added in v0.2.24

type CLIAppOpts struct {
	Name     string
	Version  string
	Commands []Subcommand
	RunTUI   func() error
}

CLIAppOpts configures a CLIApp.

type CLICommand added in v0.1.13

type CLICommand func(args []string) error

CLICommand is a config subcommand that can be invoked from a CLI.

type CellRenderer

type CellRenderer func(row Row, colIdx int, isCursor bool, theme Theme) string

CellRenderer renders a single cell with full styling control. Parameters: row data, column index, whether this row has cursor, theme. Return a styled string (use lipgloss). If nil, the table uses plain text.

type ChartPanel added in v0.2.12

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

ChartPanel is a container that displays one of several chart Components with a title bar and tab-style switcher. Implements Component and Themed.

func NewChartPanel added in v0.2.12

func NewChartPanel(opts ChartPanelOpts) *ChartPanel

NewChartPanel creates a ChartPanel with the given options.

func (*ChartPanel) ActiveIndex added in v0.2.12

func (c *ChartPanel) ActiveIndex() int

ActiveIndex returns the index of the currently displayed chart.

func (*ChartPanel) Focused added in v0.2.12

func (c *ChartPanel) Focused() bool

Focused implements Component.

func (*ChartPanel) Init added in v0.2.12

func (c *ChartPanel) Init() tea.Cmd

Init implements Component.

func (*ChartPanel) KeyBindings added in v0.2.12

func (c *ChartPanel) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*ChartPanel) SetActive added in v0.2.12

func (c *ChartPanel) SetActive(idx int)

SetActive switches to the chart at the given index (clamped).

func (*ChartPanel) SetFocused added in v0.2.12

func (c *ChartPanel) SetFocused(f bool)

SetFocused implements Component.

func (*ChartPanel) SetSize added in v0.2.12

func (c *ChartPanel) SetSize(w, h int)

SetSize implements Component.

func (*ChartPanel) SetTheme added in v0.2.12

func (c *ChartPanel) SetTheme(theme Theme)

SetTheme implements Themed.

func (*ChartPanel) Update added in v0.2.12

func (c *ChartPanel) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*ChartPanel) View added in v0.2.12

func (c *ChartPanel) View() string

View implements Component.

type ChartPanelOpts added in v0.2.12

type ChartPanelOpts struct {
	// Title is optional text shown above the chart.
	Title string

	// Charts are the available chart components. The panel shows one at a time.
	Charts []Component

	// Labels are optional display names for each chart (e.g., "Line", "Bar").
	// If shorter than Charts, indices are used for unlabelled charts.
	Labels []string
}

ChartPanelOpts configures a ChartPanel.

type Clock

type Clock interface {
	Now() time.Time
}

Clock abstracts time.Now so Poller can be tested deterministically. Production code uses realClock (via NewPoller). Tests can pass a FakeClock from the blit package (or any type that implements this interface).

type Cmd added in v0.2.24

type Cmd = tea.Cmd

Cmd is an alias for tea.Cmd, a function that returns a message.

type CollapsibleSection

type CollapsibleSection struct {
	Title     string
	Collapsed bool

	// Content is the text rendered below the header when expanded.
	// Set this directly or use Render() with a contentFunc for lazy evaluation.
	Content string
	// contains filtered or unexported fields
}

CollapsibleSection is a render helper for collapsible panel sections. It can be used in two ways:

  1. As a render helper: call Render() directly from a parent component.
  2. As a Component: embed it in a layout and let the App manage it.

When used as a Component, it handles its own key events (enter/space to toggle), focus, size, and theming.

func NewCollapsibleSection

func NewCollapsibleSection(title string) *CollapsibleSection

NewCollapsibleSection creates an expanded section with the given title.

func (*CollapsibleSection) Focused added in v0.2.24

func (s *CollapsibleSection) Focused() bool

Focused implements Component.

func (*CollapsibleSection) Init added in v0.2.24

func (s *CollapsibleSection) Init() Cmd

Init implements Component.

func (*CollapsibleSection) KeyBindings added in v0.2.24

func (s *CollapsibleSection) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*CollapsibleSection) Render

func (s *CollapsibleSection) Render(theme Theme, contentFunc func() string) string

Render returns the section header and, if expanded, the content. contentFunc is only called when expanded to avoid wasted work.

func (*CollapsibleSection) SetFocused added in v0.2.24

func (s *CollapsibleSection) SetFocused(f bool)

SetFocused implements Component.

func (*CollapsibleSection) SetSize added in v0.2.24

func (s *CollapsibleSection) SetSize(w, h int)

SetSize implements Component.

func (*CollapsibleSection) SetTheme added in v0.2.24

func (s *CollapsibleSection) SetTheme(t Theme)

SetTheme implements Themed.

func (*CollapsibleSection) Toggle

func (s *CollapsibleSection) Toggle()

Toggle flips the collapsed state.

func (*CollapsibleSection) Update added in v0.2.24

func (s *CollapsibleSection) Update(msg Msg, ctx Context) (Component, Cmd)

Update implements Component.

func (*CollapsibleSection) View added in v0.2.24

func (s *CollapsibleSection) View() string

View implements Component.

type Color added in v0.2.24

type Color = lipgloss.Color

Color is an alias for lipgloss.Color, a terminal color value.

type Column

type Column struct {
	Title      string    // Column header text
	Width      int       // Proportional width weight
	MaxWidth   int       // Cap column at this many characters (0 = no cap)
	MinWidth   int       // Hide column when terminal width is below this (0 = always show)
	Align      Alignment // Text alignment within the column
	Sortable   bool      // Whether this column supports sorting
	NoRowStyle bool      // Exempt this column from row-level background styling
}

Column defines a table column with responsive visibility.

type Command

type Command struct {
	Name    string               // Primary name: "quit", "sort", "go"
	Aliases []string             // Alternatives: ["q"] for "quit"
	Args    bool                 // Whether it takes an argument
	Hint    string               // Help text
	Run     func(string) tea.Cmd // Handler, receives args string
}

Command defines a single command for the CommandBar.

type CommandBar

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

CommandBar is a vim-style : command input overlay.

func NewCommandBar

func NewCommandBar(commands []Command) *CommandBar

NewCommandBar creates a command bar with the given commands.

func (*CommandBar) Close

func (c *CommandBar) Close()

Close deactivates the CommandBar and resets its state.

func (*CommandBar) Focused

func (c *CommandBar) Focused() bool

Focused reports whether the CommandBar is focused.

func (*CommandBar) Init

func (c *CommandBar) Init() tea.Cmd

Init initializes the CommandBar component.

func (*CommandBar) Inline

func (c *CommandBar) Inline() bool

Inline returns true — the CommandBar renders as a line at the bottom, not a fullscreen overlay.

func (*CommandBar) IsActive

func (c *CommandBar) IsActive() bool

IsActive reports whether the CommandBar overlay is currently visible.

func (*CommandBar) KeyBindings

func (c *CommandBar) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the CommandBar.

func (*CommandBar) SetActive

func (c *CommandBar) SetActive(v bool)

SetActive shows or hides the CommandBar overlay.

func (*CommandBar) SetFocused

func (c *CommandBar) SetFocused(f bool)

SetFocused sets the focus state of the CommandBar.

func (*CommandBar) SetSize

func (c *CommandBar) SetSize(w, h int)

SetSize sets the width and height of the CommandBar.

func (*CommandBar) SetTheme

func (c *CommandBar) SetTheme(t Theme)

SetTheme implements the Themed interface.

func (*CommandBar) Update

func (c *CommandBar) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates CommandBar state.

func (*CommandBar) View

func (c *CommandBar) View() string

View renders the CommandBar as a string.

type Component

type Component interface {
	// Init returns an initial command, like tea.Model.
	Init() tea.Cmd

	// Update handles a message and returns the updated component and command.
	// Return Consumed() to signal the App that this key was handled.
	// ctx carries the ambient Theme, Size, Focus, Hotkeys, Clock, and Logger
	// for the current dispatch.
	Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

	// View renders the component to a string.
	View() string

	// KeyBindings returns the keybindings this component handles.
	KeyBindings() []KeyBind

	// SetSize sets the available width and height for rendering.
	SetSize(width, height int)

	// Focused returns whether this component currently has focus.
	Focused() bool

	// SetFocused sets the focus state of this component.
	SetFocused(focused bool)
}

Component is the core interface for all blit UI elements. It extends Bubble Tea's Model with size, focus, and keybinding support.

type ComponentHeader added in v0.2.24

type ComponentHeader struct {
	Title       string
	Subtitle    string
	StatusParts []HeaderStatusPart
}

ComponentHeader renders a structured header with title, subtitle, and status line parts. This is a common pattern in TUI components that display a title bar with health indicators, filter state, or sparklines.

Usage:

h := ComponentHeader{
    Title:    "myapp",
    Subtitle: "Watching: owner/repo-a, owner/repo-b",
    StatusParts: []HeaderStatusPart{
        {Text: "Poll 5s ago"},
        {Text: "● repo-a", Color: theme.Positive},
        {Text: "API 4500/5000", Color: theme.Warn},
    },
}
header := h.Render(width, theme)

func (ComponentHeader) Render added in v0.2.24

func (h ComponentHeader) Render(width int, theme Theme) string

Render produces a multi-line header string: title, subtitle, status.

type Config added in v0.1.3

type Config[T any] struct {
	// Value holds the current configuration state.
	Value T
	// contains filtered or unexported fields
}

Config manages loading, saving, and editing application configuration. T must be a struct type with exported fields. Fields are discovered via reflection and configured with `blit:"..."` struct tags.

func LoadConfig added in v0.1.3

func LoadConfig[T any](appName string, opts ...ConfigOption) (*Config[T], error)

LoadConfig loads configuration for the named app from the platform-appropriate config directory. Missing files use struct defaults. Fields with `default` tags are populated if the loaded value is zero.

Config file paths follow os.UserConfigDir():

  • Linux: ~/.config/<appName>/config.yaml
  • macOS: ~/Library/Application Support/<appName>/config.yaml
  • Windows: %APPDATA%\<appName>\config.yaml
Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	type AppConfig struct {
		Interval int    `yaml:"interval" blit:"label=Interval (sec),group=Polling,default=30,min=5"`
		Theme    string `yaml:"theme"    blit:"label=Theme,group=Appearance,default=dark"`
	}

	cfg, err := blit.LoadConfig[AppConfig]("myapp")
	if err != nil {
		// Handle missing or invalid config file.
		fmt.Println("config error:", err)
	}
	_ = cfg
}

func (*Config[T]) AsSignal added in v0.1.13

func (c *Config[T]) AsSignal() *Signal[T]

AsSignal returns a reactive Signal that tracks the config value. The signal is created lazily on first call and emits whenever the config changes via SetValue or WatchFile reload. Components can Subscribe to the returned signal for reactive updates.

Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	type AppConfig struct {
		Interval int    `yaml:"interval" blit:"label=Interval (sec),group=Polling,default=30,min=5"`
		Theme    string `yaml:"theme"    blit:"label=Theme,group=Appearance,default=dark"`
	}

	cfg := &blit.Config[AppConfig]{
		Value: AppConfig{Interval: 30, Theme: "dark"},
	}

	// AsSignal returns a reactive signal that tracks config changes.
	sig := cfg.AsSignal()
	fmt.Println(sig.Get().Theme)

	// SetValue updates both cfg.Value and the signal.
	_ = cfg.SetValue(func(v *AppConfig) { v.Theme = "light" })
	fmt.Println(sig.Get().Theme)
}
Output:
dark
light

func (*Config[T]) CLICommands added in v0.1.13

func (c *Config[T]) CLICommands() map[string]CLICommand

CLICommands returns a command registry for config CLI integration. Commands use the yaml tag name (or lowercased Go field name) as keys.

Supported commands:

  • get <field>: print the current value of a field
  • set <field> <value>: update a field and save
  • list: print all fields and their current values

func (*Config[T]) Defaults added in v0.1.3

func (c *Config[T]) Defaults() T

Defaults returns a new T with all `default` tags applied.

func (*Config[T]) Editor added in v0.1.3

func (c *Config[T]) Editor() *ConfigEditor

Editor returns a ConfigEditor auto-generated from the struct tags. Each exported field with a `blit` tag becomes a ConfigField entry.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	type AppConfig struct {
		Interval int    `yaml:"interval" blit:"label=Interval (sec),group=Polling,default=30,min=5"`
		Theme    string `yaml:"theme"    blit:"label=Theme,group=Appearance,default=dark"`
	}

	cfg := &blit.Config[AppConfig]{
		Value: AppConfig{Interval: 30, Theme: "dark"},
	}

	// Editor auto-generates a ConfigEditor from struct tags.
	editor := cfg.Editor()
	_ = editor
}

func (*Config[T]) IsDirty added in v0.1.3

func (c *Config[T]) IsDirty() bool

IsDirty returns whether unsaved changes exist.

func (*Config[T]) Path added in v0.1.3

func (c *Config[T]) Path() string

Path returns the config file path.

func (*Config[T]) Reset added in v0.1.3

func (c *Config[T]) Reset() error

Reset restores all fields to their default values and saves.

func (*Config[T]) Save added in v0.1.3

func (c *Config[T]) Save() error

Save persists the current config to disk as YAML.

func (*Config[T]) SetValue added in v0.1.3

func (c *Config[T]) SetValue(fn func(*T)) error

SetValue updates the config via a mutator function and marks it dirty.

func (*Config[T]) WatchFile added in v0.1.13

func (c *Config[T]) WatchFile(ctx context.Context, onChange func(T)) error

WatchFile watches the config file for changes and reloads automatically. On each detected change, the YAML is re-read and Value is updated in place. The onChange callback (if non-nil) is invoked after a successful reload. WatchFile blocks until ctx is cancelled; run it in a goroutine.

File events are debounced by 200ms to avoid flicker from editors that save in multiple steps (write tmp + rename).

type ConfigEditor

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

ConfigEditor is an overlay for editing application settings. Fields are declared with getter/setter closures for config-format-agnostic editing.

func NewConfigEditor

func NewConfigEditor(fields []ConfigField) *ConfigEditor

NewConfigEditor creates a config editor overlay with the given fields.

func (*ConfigEditor) Close

func (c *ConfigEditor) Close()

Close deactivates the ConfigEditor and resets its state.

func (*ConfigEditor) Focused

func (c *ConfigEditor) Focused() bool

Focused reports whether the ConfigEditor is focused.

func (*ConfigEditor) Init

func (c *ConfigEditor) Init() tea.Cmd

Init initializes the ConfigEditor component.

func (*ConfigEditor) IsActive

func (c *ConfigEditor) IsActive() bool

IsActive reports whether the ConfigEditor overlay is currently visible.

func (*ConfigEditor) KeyBindings

func (c *ConfigEditor) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the ConfigEditor.

func (*ConfigEditor) SetFocused

func (c *ConfigEditor) SetFocused(f bool)

SetFocused sets the focus state of the ConfigEditor.

func (*ConfigEditor) SetSize

func (c *ConfigEditor) SetSize(w, h int)

SetSize sets the width and height of the ConfigEditor.

func (*ConfigEditor) SetTheme

func (c *ConfigEditor) SetTheme(t Theme)

SetTheme implements the Themed interface.

func (*ConfigEditor) Update

func (c *ConfigEditor) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates ConfigEditor state.

func (*ConfigEditor) View

func (c *ConfigEditor) View() string

View renders the ConfigEditor as a string.

type ConfigField

type ConfigField struct {
	Label    string             // Display label
	Group    string             // Group heading (e.g., "General", "Display")
	Hint     string             // Help text shown below the field
	Get      func() string      // Legacy getter. Ignored when Source is set.
	Source   any                // Optional: func() string, *Signal[string], or StringSource.
	Set      func(string) error // Sets a new value, returns error if invalid
	Validate func(string) error // Optional: validates input before Set is called
}

ConfigField defines a single editable field in the config editor.

Get accepts either the legacy `func() string` getter or a `*Signal[string]` (v0.10+). The Source field takes precedence when both are set. Setting Source with a signal lets background updates (e.g., a value polled from disk) appear in the editor without wiring a manual refresh.

type ConfigOption added in v0.1.3

type ConfigOption func(*configOpts)

ConfigOption configures LoadConfig behavior.

func WithConfigPath added in v0.1.3

func WithConfigPath(path string) ConfigOption

WithConfigPath overrides the default config file path.

type ConfirmField

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

ConfirmField is a yes/no boolean field.

func NewConfirmField

func NewConfirmField(id, label string) *ConfirmField

NewConfirmField creates a new yes/no confirm field.

func (*ConfirmField) FieldID

func (f *ConfirmField) FieldID() string

func (*ConfirmField) Init

func (f *ConfirmField) Init() tea.Cmd

Init initializes the ConfirmField component.

func (*ConfirmField) Label

func (f *ConfirmField) Label() string

func (*ConfirmField) SetFocused

func (f *ConfirmField) SetFocused(_ bool)

SetFocused sets the focus state of the ConfirmField.

func (*ConfirmField) SetValue

func (f *ConfirmField) SetValue(v string)

SetValue sets the current value of the ConfirmField.

func (*ConfirmField) Update

func (f *ConfirmField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates ConfirmField state.

func (*ConfirmField) Validate

func (f *ConfirmField) Validate() error

Validate checks the current value against the field's validation rules.

func (*ConfirmField) Value

func (f *ConfirmField) Value() string

Value returns the current value of the ConfirmField.

func (*ConfirmField) View

func (f *ConfirmField) View(focused bool, theme Theme, _ int) string

View renders the ConfirmField as a string.

func (*ConfirmField) WithDefault

func (f *ConfirmField) WithDefault(v bool) *ConfirmField

WithDefault sets the initial boolean value.

func (*ConfirmField) WithHint

func (f *ConfirmField) WithHint(hint string) *ConfirmField

WithHint sets the hint text.

type Context

type Context struct {
	// Theme is the currently active theme. Components can pull semantic
	// colors from it without needing a separate SetTheme call per frame.
	Theme Theme

	// Size is the viewport size at the time of dispatch (width, height).
	Size Size

	// Focus describes which component currently holds focus. Components
	// can compare against their own identity / index to decide whether to
	// react to key input.
	Focus Focus

	// Hotkeys exposes the app-wide keybinding registry. Components can
	// consult it to resolve chord conflicts or render inline hints.
	Hotkeys *Registry

	// Clock abstracts time.Now so components can be tested with a fake
	// clock. It is nil-safe: if unset, callers should fall back to
	// time.Now directly.
	Clock Clock

	// Logger is an optional structured logger. Components should treat a
	// nil Logger as "logging disabled" rather than panicking.
	Logger *slog.Logger

	// Flags exposes the app-wide feature flag registry. Components can
	// check flags to conditionally enable or disable behavior at runtime.
	// Nil means no flags are configured — callers should treat this as
	// "all features at their defaults".
	Flags *FeatureFlag

	// TraceID identifies the current message dispatch cycle. Every call
	// to App.Update generates a unique trace ID so that components can
	// correlate log entries and metrics across the dispatch chain.
	// Components can log it or pass it to downstream systems for
	// end-to-end message tracing.
	TraceID uint64
}

Context carries ambient state that every Component.Update call receives. It is constructed by the App on each dispatch and passed down through the focused-component chain. Prefer reading values from Context over stashing copies on the component itself — Context always reflects the latest frame.

type CopyToClipboardMsg added in v0.1.1

type CopyToClipboardMsg struct {
	Text string
}

CopyToClipboardMsg is sent after a successful clipboard copy to notify the application. Components can listen for this to show confirmation.

type CursorChangeHandler

type CursorChangeHandler func(row Row, rowIdx int)

CursorChangeHandler is called when the cursor moves to a different row.

type CursorStyle

type CursorStyle int

CursorStyle controls how the cursor is rendered in a table.

const (
	// CursorRow highlights the entire row.
	CursorRow CursorStyle = iota
)

type DebugDataProvider added in v0.1.3

type DebugDataProvider interface {
	DebugProvider
	// Data returns structured key-value data for this provider.
	Data() map[string]any
}

DebugDataProvider is an optional extension of DebugProvider that exposes structured data for machine consumption (JSON export, alternative renders).

type DebugProvider added in v0.1.3

type DebugProvider interface {
	// Name returns the display name for this provider (used as tab label or section header).
	Name() string

	// View renders the provider's content. width and height are the available space.
	View(width, height int, theme Theme) string
}

DebugProvider supplies a named debug section for the DevConsole overlay. Providers are queried each frame when the console is visible.

type DebugProviderWithLifecycle added in v0.1.13

type DebugProviderWithLifecycle interface {
	DebugProvider
	// Init is called once when the provider is registered.
	Init() error
	// Destroy is called when the App is shutting down.
	Destroy() error
}

DebugProviderWithLifecycle is an optional extension of DebugProvider that supports initialization and cleanup. Init is called when the provider is registered with the DevConsole. Destroy is called when the App shuts down.

type DetailOverlay

type DetailOverlay[T any] struct {
	// contains filtered or unexported fields
}

DetailOverlay is a generic full-screen overlay for displaying item details.

func NewDetailOverlay

func NewDetailOverlay[T any](opts DetailOverlayOpts[T]) *DetailOverlay[T]

NewDetailOverlay creates a detail overlay with the given options.

func (*DetailOverlay[T]) Close

func (d *DetailOverlay[T]) Close()

Close deactivates the DetailOverlay and resets its state.

func (*DetailOverlay[T]) Focused

func (d *DetailOverlay[T]) Focused() bool

Focused reports whether the DetailOverlay is focused.

func (*DetailOverlay[T]) Init

func (d *DetailOverlay[T]) Init() tea.Cmd

Init initializes the DetailOverlay component.

func (*DetailOverlay[T]) IsActive

func (d *DetailOverlay[T]) IsActive() bool

IsActive reports whether the DetailOverlay overlay is currently visible.

func (*DetailOverlay[T]) Item

func (d *DetailOverlay[T]) Item() T

Item returns the currently displayed item.

func (*DetailOverlay[T]) KeyBindings

func (d *DetailOverlay[T]) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the DetailOverlay.

func (*DetailOverlay[T]) SetActive

func (d *DetailOverlay[T]) SetActive(v bool)

SetActive shows or hides the DetailOverlay overlay.

func (*DetailOverlay[T]) SetFocused

func (d *DetailOverlay[T]) SetFocused(f bool)

SetFocused sets the focus state of the DetailOverlay.

func (*DetailOverlay[T]) SetSize

func (d *DetailOverlay[T]) SetSize(w, h int)

SetSize sets the width and height of the DetailOverlay.

func (*DetailOverlay[T]) SetTheme

func (d *DetailOverlay[T]) SetTheme(t Theme)

SetTheme implements the Themed interface.

func (*DetailOverlay[T]) Show

func (d *DetailOverlay[T]) Show(item T)

Show opens the overlay with the given item.

func (*DetailOverlay[T]) Update

func (d *DetailOverlay[T]) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates DetailOverlay state.

func (*DetailOverlay[T]) View

func (d *DetailOverlay[T]) View() string

View renders the DetailOverlay as a string.

type DetailOverlayOpts

type DetailOverlayOpts[T any] struct {
	// Render draws the item detail content. Required.
	Render func(item T, width, height int, theme Theme) string

	// Title is shown at the top of the overlay. Optional.
	Title string

	// KeyBindings are extra bindings shown in help. Optional.
	KeyBindings []KeyBind

	// OnKey handles custom key events. Optional.
	// Return Consumed() if handled, nil to let the App handle it.
	OnKey func(item T, key tea.KeyMsg) tea.Cmd
}

DetailOverlayOpts configures a DetailOverlay.

type DetailRenderer

type DetailRenderer func(row Row, rowIdx int, width int, theme Theme) string

DetailRenderer renders a detail bar for the selected row. Parameters: row data, row index, available width, theme. Return a styled multi-line string. Shown below the table rows when focused.

type Dialog added in v0.2.12

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

Dialog is a modal overlay that displays a message with action buttons. It implements the Overlay interface.

func NewDialog added in v0.2.12

func NewDialog(opts DialogOpts) *Dialog

NewDialog creates and opens a Dialog with the given options.

func (*Dialog) Close added in v0.2.12

func (d *Dialog) Close()

Close implements Overlay.

func (*Dialog) CursorIndex added in v0.2.12

func (d *Dialog) CursorIndex() int

CursorIndex returns the currently highlighted button index.

func (*Dialog) Focused added in v0.2.12

func (d *Dialog) Focused() bool

Focused implements Component.

func (*Dialog) Init added in v0.2.12

func (d *Dialog) Init() tea.Cmd

Init implements Component.

func (*Dialog) IsActive added in v0.2.12

func (d *Dialog) IsActive() bool

IsActive implements Overlay.

func (*Dialog) KeyBindings added in v0.2.12

func (d *Dialog) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Dialog) SetFocused added in v0.2.12

func (d *Dialog) SetFocused(f bool)

SetFocused implements Component.

func (*Dialog) SetSize added in v0.2.12

func (d *Dialog) SetSize(w, h int)

SetSize implements Component.

func (*Dialog) SetTheme added in v0.2.12

func (d *Dialog) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Dialog) Update added in v0.2.12

func (d *Dialog) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Dialog) View added in v0.2.12

func (d *Dialog) View() string

View implements Component.

type DialogButton added in v0.2.12

type DialogButton struct {
	// Label is the text shown on the button.
	Label string
	// Action is called when the button is activated. Optional.
	Action func()
}

DialogButton represents a button in a Dialog.

type DialogOpts added in v0.2.12

type DialogOpts struct {
	// Title is optional text rendered in the top border.
	Title string

	// Body is the main content of the dialog.
	Body string

	// Buttons are the action buttons shown at the bottom.
	// If empty, a single "OK" button that closes the dialog is added.
	Buttons []DialogButton

	// OnClose is called when the dialog is dismissed (Esc or button action).
	OnClose func()
}

DialogOpts configures a Dialog.

type DualPane

type DualPane struct {
	Main         Component // Main pane component
	Side         Component // Sidebar component
	MainName     string    // Display name for focus badge (default: "Main")
	SideName     string    // Display name for focus badge (default: "Side")
	SideWidth    int       // Fixed width of the sidebar
	MinMainWidth int       // Sidebar auto-hides below this main width
	SideRight    bool      // true = sidebar on right, false = on left
	ToggleKey    string    // Key to toggle sidebar visibility
	// contains filtered or unexported fields
}

DualPane is a layout with a main component and a collapsible sidebar.

func (*DualPane) Toggle

func (d *DualPane) Toggle()

Toggle flips sidebar visibility on/off.

type Ease

type Ease func(t float64) float64

Ease is an easing function mapping t in [0,1] to value in [0,1].

type FeatureFlag added in v0.2.24

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

FeatureFlag provides runtime feature toggling for blit applications.

Use feature flags to gate experimental components, A/B test UI behavior, or conditionally enable functionality without rebuilding. Flags can be set programmatically or via environment variables (BLIT_FLAG_<NAME>=1).

Flag resolution order (first match wins):

  1. Explicit override set via Set or WithFeatureFlags
  2. Environment variable BLIT_FLAG_<NAME> (1 = enabled, 0 = disabled)
  3. Default value from the flag definition

func NewFeatureFlag added in v0.2.24

func NewFeatureFlag(defs ...FlagDef) *FeatureFlag

NewFeatureFlag creates a flag registry with the given definitions. Each entry is (name, defaultValue, description).

func (*FeatureFlag) Clear added in v0.2.24

func (ff *FeatureFlag) Clear(name string)

Clear removes an explicit override, reverting to env/default resolution.

func (*FeatureFlag) Describe added in v0.2.24

func (ff *FeatureFlag) Describe(name string) string

Describe returns the description for a flag, or "" if undefined.

func (*FeatureFlag) Enabled added in v0.2.24

func (ff *FeatureFlag) Enabled(name string) bool

Enabled returns whether the named flag is active.

Resolution: explicit override → env var BLIT_FLAG_<NAME> → default. Returns false for unknown flag names.

func (*FeatureFlag) Names added in v0.2.24

func (ff *FeatureFlag) Names() []string

Names returns all defined flag names.

func (*FeatureFlag) Set added in v0.2.24

func (ff *FeatureFlag) Set(name string, enabled bool)

Set overrides a flag value. The value persists until Clear is called.

func (*FeatureFlag) Snapshot added in v0.2.24

func (ff *FeatureFlag) Snapshot() map[string]bool

Snapshot returns a map of all flags and their current resolved values.

type Field

type Field interface {
	FieldID() string
	Label() string
	Value() string
	SetValue(v string)
	Validate() error
	Init() tea.Cmd
	Update(msg tea.Msg) tea.Cmd
	View(focused bool, theme Theme, width int) string
	SetFocused(focused bool)
}

Field is the interface all form field types implement.

type FilePicker

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

FilePicker wraps a Tree over the local filesystem with lazy-loaded children and a Picker-style fuzzy search box.

func NewFilePicker

func NewFilePicker(opts FilePickerOpts) *FilePicker

NewFilePicker creates a FilePicker rooted at opts.Root (defaults to ".").

func (*FilePicker) Focused

func (fp *FilePicker) Focused() bool

Focused implements Component.

func (*FilePicker) Init

func (fp *FilePicker) Init() tea.Cmd

Init implements Component.

func (*FilePicker) KeyBindings

func (fp *FilePicker) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*FilePicker) SetFocused

func (fp *FilePicker) SetFocused(f bool)

SetFocused implements Component.

func (*FilePicker) SetSize

func (fp *FilePicker) SetSize(w, h int)

SetSize implements Component.

func (*FilePicker) SetTheme

func (fp *FilePicker) SetTheme(t Theme)

SetTheme implements Themed.

func (*FilePicker) Update

func (fp *FilePicker) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*FilePicker) View

func (fp *FilePicker) View() string

View implements Component.

type FilePickerOpts

type FilePickerOpts struct {
	// Root is the starting directory. Defaults to the current directory.
	Root string

	// PreviewPane renders a file preview pane on the right when true.
	PreviewPane bool

	// ShowHidden shows hidden files (dot-prefixed) when true.
	ShowHidden bool

	// OnSelect is called when the user presses Enter on a file node. Optional.
	OnSelect func(path string)

	// OnCancel is called when the user cancels. Optional.
	OnCancel func()
}

FilePickerOpts configures FilePicker behaviour.

type FilterFunc

type FilterFunc func(row Row) bool

FilterFunc returns true if a row should be visible. Used for predicate-based filtering (e.g., show only gainers, filter by type).

type FlagDef added in v0.2.24

type FlagDef struct {
	// Name is the flag identifier. Must be uppercase snake_case (e.g. "NEW_TABLE").
	Name string

	// Default is the value when no override or env var is set.
	Default bool

	// Description explains what the flag controls.
	Description string
}

FlagDef describes a single feature flag.

type Flex

type Flex struct {
	Grow int       // Growth weight (≥1).
	C    Component // The wrapped component.
}

Flex wraps a Component that grows proportionally to fill remaining space. Grow is the relative weight — a child with Grow=2 gets twice as much space as one with Grow=1.

func (Flex) Focused

func (f Flex) Focused() bool

Focused reports whether the Flex is focused.

func (Flex) Init

func (f Flex) Init() tea.Cmd

Init initializes the Flex component.

func (Flex) KeyBindings

func (f Flex) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Flex.

func (Flex) SetFocused

func (f Flex) SetFocused(foc bool)

SetFocused sets the focus state of the Flex.

func (Flex) SetSize

func (f Flex) SetSize(w, h int)

SetSize sets the width and height of the Flex.

func (Flex) SetTheme added in v0.1.3

func (f Flex) SetTheme(th Theme)

SetTheme implements Themed by delegating to the wrapped component.

func (Flex) Update

func (f Flex) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Flex state.

func (Flex) View

func (f Flex) View() string

View renders the Flex as a string.

type FlexAlign

type FlexAlign int

FlexAlign controls cross-axis alignment for HBox/VBox children.

const (
	// FlexAlignStart aligns children to the start of the cross axis.
	FlexAlignStart FlexAlign = iota
	// FlexAlignCenter centers children on the cross axis.
	FlexAlignCenter
	// FlexAlignEnd aligns children to the end of the cross axis.
	FlexAlignEnd
	// FlexAlignStretch stretches children to fill the cross axis.
	FlexAlignStretch
)

type FlexJustify

type FlexJustify int

FlexJustify controls main-axis distribution for HBox/VBox children.

const (
	// FlexJustifyStart packs children toward the start.
	FlexJustifyStart FlexJustify = iota
	// FlexJustifyCenter packs children in the center.
	FlexJustifyCenter
	// FlexJustifyEnd packs children toward the end.
	FlexJustifyEnd
	// FlexJustifySpaceBetween distributes children with equal gaps between them.
	FlexJustifySpaceBetween
	// FlexJustifySpaceAround distributes children with equal space around each.
	FlexJustifySpaceAround
)

type FloatingOverlay

type FloatingOverlay interface {
	Overlay
	// FloatView receives the fully-rendered background content and returns
	// the composited result with the floating panel drawn on top.
	FloatView(background string) string
}

FloatingOverlay is an overlay that composites on top of the main content rather than replacing it. The App renders the normal content first, then calls FloatView with the rendered content so the overlay can composite its panel over it (e.g., a dev console, tooltip, or pop-over).

type Focus

type Focus struct {
	// Index is the position of the focused component in the app's focus
	// order. -1 means no component has focus (e.g., an overlay is active).
	Index int

	// Name is an optional human-readable name for the focused component,
	// sourced from WithComponent / DualPane.MainName / DualPane.SideName.
	Name string
}

Focus identifies the currently focused component in the app's focus chain.

type ForcedChoice

type ForcedChoice int

ForcedChoice records the user's decision on the forced gate.

const (
	// ForcedChoicePending means the user has not chosen yet.
	ForcedChoicePending ForcedChoice = iota
	// ForcedChoiceUpdate means the user accepted the update.
	ForcedChoiceUpdate
	// ForcedChoiceQuit means the user declined and wants to quit.
	ForcedChoiceQuit
)

type ForcedUpdateScreen

type ForcedUpdateScreen struct {
	Result  *UpdateResult
	Cfg     UpdateConfig
	Choice  ForcedChoice
	Width   int
	Height  int
	Message string // post-action status (e.g., "updating...", "failed: ...")
}

ForcedUpdateScreen is the full-screen gate shown when an update is Required (minimum_version marker set). The app cannot proceed until the user either updates or quits.

Wiring:

gate := NewForcedUpdateScreen(result, cfg)
if result.Required {
    program := tea.NewProgram(gate)
    program.Run()
}

func NewForcedUpdateScreen

func NewForcedUpdateScreen(result *UpdateResult, cfg UpdateConfig) *ForcedUpdateScreen

NewForcedUpdateScreen returns a gate for the given update result and config.

func (*ForcedUpdateScreen) Init

func (f *ForcedUpdateScreen) Init() tea.Cmd

Init implements tea.Model.

func (*ForcedUpdateScreen) Update

func (f *ForcedUpdateScreen) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model. Accepts y/u/enter to update, q/esc/ctrl+c to quit.

func (*ForcedUpdateScreen) View

func (f *ForcedUpdateScreen) View() string

View implements tea.Model. Renders a centered dialog box that fills the terminal with a title, release info, and action hint line.

type Form

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

Form is a TUI component that renders a collection of fields with keyboard navigation, inline validation, optional grouping, and a wizard step mode. It implements Component and Themed.

func NewForm

func NewForm(opts FormOpts) *Form

NewForm creates a Form from the given options.

Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	form := blit.NewForm(blit.FormOpts{
		Groups: []blit.FormGroup{
			{
				Title: "Settings",
				Fields: []blit.Field{
					blit.NewTextField("name", "Name"),
					blit.NewSelectField("role", "Role", []string{"admin", "user", "viewer"}),
					blit.NewConfirmField("active", "Active"),
				},
			},
		},
		OnSubmit: func(values map[string]string) {
			fmt.Println("submitted")
		},
	})
	_ = form
}

func (*Form) Focused

func (f *Form) Focused() bool

Focused implements Component.

func (*Form) Init

func (f *Form) Init() tea.Cmd

Init implements Component.

func (*Form) KeyBindings

func (f *Form) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Form) Reset

func (f *Form) Reset()

Reset clears the form submission state and returns focus to the first field.

func (*Form) SetFocused

func (f *Form) SetFocused(focused bool)

SetFocused implements Component.

func (*Form) SetSize

func (f *Form) SetSize(width, height int)

SetSize implements Component.

func (*Form) SetTheme

func (f *Form) SetTheme(th Theme)

SetTheme implements Themed.

func (*Form) Update

func (f *Form) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Form) Values

func (f *Form) Values() map[string]string

Values returns the current values of all fields as a map.

func (*Form) View

func (f *Form) View() string

View implements Component.

type FormGroup

type FormGroup struct {
	Title  string
	Fields []Field
}

FormGroup is a named group of fields with a visual separator.

type FormOpts

type FormOpts struct {
	Groups     []FormGroup
	OnSubmit   func(values map[string]string)
	WizardMode bool
}

FormOpts configures a Form component.

type FormSubmitMsg

type FormSubmitMsg struct {
	Values map[string]string
}

FormSubmitMsg is emitted when the form is submitted successfully.

type Glyphs

type Glyphs struct {
	// List / tree connectors
	TreeBranch string
	TreeLast   string
	TreePipe   string
	TreeEmpty  string

	// Cursor / selection
	CursorMarker     string
	FlashMarker      string
	SelectedBullet   string
	UnselectedBullet string
	CollapsedArrow   string
	ExpandedArrow    string

	// Progress bar
	BarFilled string
	BarEmpty  string

	// Spinner frames (cycled sequentially)
	SpinnerFrames []string

	// Status / feedback
	Check string
	Cross string
	Info  string
	Warn  string
	Star  string
	Dot   string
}

Glyphs defines terminal symbols used by blit components. Two packs are provided: DefaultGlyphs (Unicode) and AsciiGlyphs. Attach a Glyphs instance to a Theme to customise all component symbols at once.

func AsciiGlyphs

func AsciiGlyphs() Glyphs

AsciiGlyphs returns a pure-ASCII glyph set for terminals without Unicode support.

func DefaultGlyphs

func DefaultGlyphs() Glyphs

DefaultGlyphs returns the standard Unicode glyph set.

type Gradient

type Gradient struct {
	Start lipgloss.Color
	End   lipgloss.Color
}

Gradient defines a linear color gradient between two lipgloss colors.

func (Gradient) RenderAt

func (g Gradient) RenderAt(t float64) lipgloss.Color

RenderAt returns the interpolated color at position t (0.0 to 1.0).

func (Gradient) RenderText

func (g Gradient) RenderText(s string) string

RenderText applies the gradient across each character of the string.

type HBox

type HBox struct {
	Gap     int         // Gap in columns between children.
	Align   FlexAlign   // Cross-axis (vertical) alignment.
	Justify FlexJustify // Main-axis (horizontal) distribution.
	Items   []Component // Children — may be plain Component, Sized, or Flex.
	// contains filtered or unexported fields
}

HBox lays out children horizontally (left → right). It implements the full Component interface and can be nested.

func (*HBox) Focused

func (h *HBox) Focused() bool

Focused implements Component.

func (*HBox) Init

func (h *HBox) Init() tea.Cmd

Init implements Component.

func (*HBox) KeyBindings

func (h *HBox) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*HBox) SetFocused

func (h *HBox) SetFocused(focused bool)

SetFocused implements Component.

func (*HBox) SetSize

func (h *HBox) SetSize(width, height int)

SetSize implements Component.

func (*HBox) SetTheme added in v0.1.3

func (h *HBox) SetTheme(th Theme)

SetTheme implements Themed by propagating to all children.

func (*HBox) Update

func (h *HBox) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*HBox) View

func (h *HBox) View() string

View implements Component.

type HTTPResource added in v0.2.24

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

HTTPResource manages API polling with ETag caching, rate-limit parsing, and response fallback. It integrates with blit.Poller for timing and StatsCollector for observability.

Create one with NewHTTPResource, then call PollCmd to get a tea.Cmd suitable for use with Poller.

func NewHTTPResource added in v0.2.24

func NewHTTPResource(opts HTTPResourceOpts) *HTTPResource

NewHTTPResource creates a new HTTPResource with the given options.

func (*HTTPResource) DebugProvider added in v0.2.24

func (r *HTTPResource) DebugProvider() DebugDataProvider

DebugProvider returns a DebugDataProvider for this HTTPResource.

func (*HTTPResource) PollCmd added in v0.2.24

func (r *HTTPResource) PollCmd() Cmd

PollCmd returns a tea.Cmd that fetches all configured pages and returns an HTTPResultMsg. Use this as the Poller's fetch function.

func (*HTTPResource) SetStatsCollector added in v0.2.24

func (r *HTTPResource) SetStatsCollector(sc *StatsCollector)

SetStatsCollector wires a StatsCollector so that fetch results are automatically tracked. Optional but recommended.

func (*HTTPResource) Stats added in v0.2.24

func (r *HTTPResource) Stats() StatsSnapshot

HTTPResourceStats returns the stats snapshot for this resource.

type HTTPResourceOpts added in v0.2.24

type HTTPResourceOpts struct {
	// Name identifies this resource in DevConsole and log messages.
	Name string

	// BuildURL returns the URL to fetch for the given page number (1-indexed).
	BuildURL func(page int) string

	// Parse decodes the response body into an arbitrary result.
	// The returned value is typically wrapped in a tea.Msg by the caller.
	Parse func(body []byte) (any, error)

	// ExtraHeaders returns additional HTTP headers for each request.
	// Use this for authentication tokens.
	ExtraHeaders func() map[string]string

	// Pages is the number of pages to fetch per poll cycle. Default: 1.
	Pages int

	// PageSize is the per_page query parameter. Default: 30.
	PageSize int

	// Parallel fetches pages concurrently when Pages > 1. Default: true.
	Parallel bool

	// CacheResponses enables caching the last successful response per URL
	// and falling back to it on failure. Default: true.
	CacheResponses bool

	// OnRateLimit is called when rate limit info is parsed from response
	// headers. Optional.
	OnRateLimit func(remaining, limit int)
}

HTTPResourceOpts configures an HTTPResource for API polling with ETag caching, rate-limit awareness, and fallback.

type HTTPResultMsg added in v0.2.24

type HTTPResultMsg struct {
	Name             string
	Results          []any
	Errors           []string
	NotModifiedCount int
	RateRemaining    int
	RateLimit        int
}

HTTPResultMsg is the tea.Msg returned by HTTPResource.PollCmd.

func (HTTPResultMsg) HasData added in v0.2.24

func (m HTTPResultMsg) HasData() bool

HasData reports whether any page returned fresh data (not all 304s).

func (HTTPResultMsg) IsAllNotModified added in v0.2.24

func (m HTTPResultMsg) IsAllNotModified() bool

IsAllNotModified reports whether all pages returned 304 Not Modified.

type HeaderStatusPart added in v0.2.24

type HeaderStatusPart struct {
	Text  string
	Color Color // zero value = use Muted text
}

HeaderStatusPart is a single segment in the status line.

func StatusPaused added in v0.2.24

func StatusPaused(theme Theme) HeaderStatusPart

StatusPaused renders a "[PAUSED]" indicator in the warn color.

func StatusPollAgo added in v0.2.24

func StatusPollAgo(ago string) HeaderStatusPart

StatusPollAgo renders a "Poll X ago" indicator in muted color.

func StatusRateLimit added in v0.2.24

func StatusRateLimit(remaining, limit int, theme Theme) HeaderStatusPart

StatusRateLimit renders a rate limit indicator with color based on remaining percentage.

type Help

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

Help is an overlay that auto-generates a keybinding reference from the registry. It requires zero configuration — just call NewHelp() and register it with the App.

func NewHelp

func NewHelp() *Help

NewHelp creates a new Help overlay.

func (*Help) Close

func (h *Help) Close()

Close deactivates the Help and resets its state.

func (*Help) Focused

func (h *Help) Focused() bool

Focused reports whether the Help is focused.

func (*Help) Init

func (h *Help) Init() tea.Cmd

Init initializes the Help component.

func (*Help) IsActive

func (h *Help) IsActive() bool

IsActive reports whether the Help overlay is currently visible.

func (*Help) KeyBindings

func (h *Help) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Help.

func (*Help) SetFocused

func (h *Help) SetFocused(f bool)

SetFocused sets the focus state of the Help.

func (*Help) SetSize

func (h *Help) SetSize(w, ht int)

SetSize sets the width and height of the Help.

func (*Help) SetTheme

func (h *Help) SetTheme(t Theme)

SetTheme implements the Themed interface.

func (*Help) Update

func (h *Help) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Help state.

func (*Help) View

func (h *Help) View() string

View renders the Help as a string.

type InlineOverlay

type InlineOverlay interface {
	Overlay
	Inline() bool
}

InlineOverlay is an overlay that renders as a single line at the bottom of the screen instead of replacing all content. The App renders the normal content behind it with the overlay's View appended at the bottom.

type InputCapture

type InputCapture interface {
	CapturesInput() bool
}

InputCapture is implemented by components that can enter text-input mode (e.g., search, filter). When CapturesInput returns true, the App skips global keybindings and sends keys directly to the component.

type InstallMethod

type InstallMethod int

InstallMethod describes how the binary was installed.

const (
	// InstallManual means the binary was installed manually or via go install.
	InstallManual InstallMethod = iota
	// InstallHomebrew means the binary was installed via Homebrew.
	InstallHomebrew
	// InstallScoop means the binary was installed via Scoop.
	InstallScoop
)

func DetectInstallMethod

func DetectInstallMethod(path string) InstallMethod

DetectInstallMethod inspects a binary path to determine how it was installed.

type Kanban added in v0.2.12

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

Kanban is a multi-column board component for organizing cards. Implements Component and Themed.

func NewKanban added in v0.2.12

func NewKanban(columns []KanbanColumn, opts KanbanOpts) *Kanban

NewKanban creates a Kanban board with the given columns and options.

func (*Kanban) ActiveCard added in v0.2.12

func (k *Kanban) ActiveCard() int

ActiveCard returns the index of the focused card within the active column.

func (*Kanban) ActiveColumn added in v0.2.12

func (k *Kanban) ActiveColumn() int

ActiveColumn returns the index of the focused column.

func (*Kanban) Columns added in v0.2.12

func (k *Kanban) Columns() []KanbanColumn

Columns returns the current columns.

func (*Kanban) Focused added in v0.2.12

func (k *Kanban) Focused() bool

Focused implements Component.

func (*Kanban) Init added in v0.2.12

func (k *Kanban) Init() tea.Cmd

Init implements Component.

func (*Kanban) KeyBindings added in v0.2.12

func (k *Kanban) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Kanban) SetFocused added in v0.2.12

func (k *Kanban) SetFocused(f bool)

SetFocused implements Component.

func (*Kanban) SetSize added in v0.2.12

func (k *Kanban) SetSize(w, h int)

SetSize implements Component.

func (*Kanban) SetTheme added in v0.2.12

func (k *Kanban) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Kanban) Update added in v0.2.12

func (k *Kanban) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Kanban) View added in v0.2.12

func (k *Kanban) View() string

View implements Component.

type KanbanCard added in v0.2.12

type KanbanCard struct {
	// ID is a unique identifier for the card.
	ID string
	// Title is the display text.
	Title string
	// Description is optional secondary text.
	Description string
	// Tag is an optional label shown as a badge (e.g. "bug", "feat").
	Tag string
}

KanbanCard is a single card in a Kanban column.

type KanbanColumn added in v0.2.12

type KanbanColumn struct {
	// Title is the column header.
	Title string
	// Cards are the items in this column.
	Cards []KanbanCard
}

KanbanColumn is a named column containing cards.

type KanbanOpts added in v0.2.12

type KanbanOpts struct {
	// OnMove is called when a card is moved between columns.
	// It receives the card, source column index, and destination column index.
	OnMove func(card KanbanCard, from, to int)

	// OnSelect is called when enter is pressed on a card.
	OnSelect func(card KanbanCard, col int)
}

KanbanOpts configures a Kanban board.

type Key added in v0.2.24

type Key = tea.Key

Key is an alias for tea.Key, the underlying key data structure.

type KeyBind

type KeyBind struct {
	Key        string         // Key name: "q", "ctrl+c", "?", "/", "up", "down"
	Label      string         // Human-readable label: "Quit", "Search", "Help"
	Group      string         // Grouping for help screen: "NAVIGATION", "DATA", "OTHER"
	Handler    func()         // Optional handler for app-level keybindings (nil for component bindings)
	HandlerCmd func() tea.Cmd // Optional handler that returns a tea.Cmd
}

KeyBind defines a keyboard shortcut with its label and group. Components return slices of KeyBind from their KeyBindings() method. The App collects these for dispatch and auto-generates the help screen.

type KeyGroup

type KeyGroup struct {
	Name     string
	Bindings []KeyBind
}

KeyGroup is a named group of keybindings for help screen rendering.

type KeyMsg added in v0.2.24

type KeyMsg = tea.KeyMsg

KeyMsg is an alias for tea.KeyMsg, sent on key presses.

type KeyType added in v0.2.24

type KeyType = tea.KeyType

KeyType is an alias for tea.KeyType, the type of a key event.

type Layout

type Layout interface {
	// contains filtered or unexported methods
}

Layout defines how components are arranged within the terminal.

type ListView

type ListView[T any] struct {
	// contains filtered or unexported fields
}

ListView is a generic scrollable list with cursor navigation, header, detail bar, and flash highlighting. It implements Component and Themed.

Use it standalone as a registered component, or embed it inside a custom component and delegate via HandleKey and View.

func NewListView

func NewListView[T any](opts ListViewOpts[T]) *ListView[T]

NewListView creates a new ListView with the given options.

func (*ListView[T]) CursorIndex

func (l *ListView[T]) CursorIndex() int

CursorIndex returns the current cursor position.

func (*ListView[T]) CursorItem

func (l *ListView[T]) CursorItem() *T

CursorItem returns a pointer to the item at the cursor, or nil if empty.

func (*ListView[T]) Focused

func (l *ListView[T]) Focused() bool

Focused reports whether the ListView is focused.

func (*ListView[T]) HandleKey

func (l *ListView[T]) HandleKey(msg tea.KeyMsg) tea.Cmd

HandleKey processes navigation keys. Use this when embedding ListView in another component. Returns Consumed() if handled, nil otherwise.

func (*ListView[T]) Init

func (l *ListView[T]) Init() tea.Cmd

Init initializes the ListView component.

func (*ListView[T]) IsAtBottom

func (l *ListView[T]) IsAtBottom() bool

IsAtBottom returns true if the viewport is scrolled to the bottom.

func (*ListView[T]) IsAtTop

func (l *ListView[T]) IsAtTop() bool

IsAtTop returns true if the viewport is scrolled to the top.

func (*ListView[T]) ItemCount

func (l *ListView[T]) ItemCount() int

ItemCount returns the number of items in the list.

func (*ListView[T]) Items

func (l *ListView[T]) Items() []T

Items returns the current items.

func (*ListView[T]) KeyBindings

func (l *ListView[T]) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the ListView.

func (*ListView[T]) Refresh

func (l *ListView[T]) Refresh()

Refresh re-renders the list content without changing items. Use this to update flash effects or dynamic rendering.

func (*ListView[T]) ScrollToBottom

func (l *ListView[T]) ScrollToBottom()

ScrollToBottom moves the cursor and viewport to the bottom.

func (*ListView[T]) ScrollToTop

func (l *ListView[T]) ScrollToTop()

ScrollToTop moves the cursor and viewport to the top.

func (*ListView[T]) SetCursor

func (l *ListView[T]) SetCursor(idx int)

SetCursor moves the cursor to the given index.

func (*ListView[T]) SetFocused

func (l *ListView[T]) SetFocused(f bool)

SetFocused sets the focus state of the ListView.

func (*ListView[T]) SetItems

func (l *ListView[T]) SetItems(items []T)

SetItems replaces the list data and rebuilds the view.

func (*ListView[T]) SetSize

func (l *ListView[T]) SetSize(w, h int)

SetSize sets the width and height of the ListView.

func (*ListView[T]) SetTheme

func (l *ListView[T]) SetTheme(th Theme)

SetTheme updates the theme used by the ListView.

func (*ListView[T]) Update

func (l *ListView[T]) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates ListView state.

func (*ListView[T]) View

func (l *ListView[T]) View() string

View renders the ListView as a string.

type ListViewOpts

type ListViewOpts[T any] struct {
	// RenderItem renders a single item to a string.
	// Parameters: item, index in the list, whether this item has cursor, theme.
	RenderItem func(item T, idx int, isCursor bool, theme Theme) string

	// HeaderFunc renders a header above the list content. Optional.
	// The returned string can be multi-line. ListView accounts for its height.
	HeaderFunc func(theme Theme) string

	// DetailFunc renders a detail bar below the list for the selected item. Optional.
	// Only shown when the list is focused and there is a cursor item.
	// The returned string can be multi-line. ListView accounts for its height.
	DetailFunc func(item T, theme Theme) string

	// FlashFunc returns true if an item should show the flash marker. Optional.
	// Called during render with the current time for duration-based flash effects.
	FlashFunc func(item T, now time.Time) bool

	// OnSelect is called when Enter is pressed on an item. Optional.
	OnSelect func(item T, idx int)

	// DetailHeight is the number of lines to reserve for the detail bar.
	// When DetailFunc is set, this space is always reserved (blank when unfocused)
	// to prevent viewport jitter on focus change. Default: 3.
	DetailHeight int

	// EmptyText is displayed when the list has no items. If empty, the list
	// renders blank when there are no items (preserving existing behavior).
	EmptyText string
}

ListViewOpts configures a ListView component.

type LogAppendMsg

type LogAppendMsg struct{ Line LogLine }

LogAppendMsg is a Bubble Tea message that appends a line to the LogViewer. Use LogAppendCmd to produce this from a tea.Cmd.

type LogLevel

type LogLevel int

LogLevel represents the severity of a log line.

const (
	// LogDebug is the lowest severity level.
	LogDebug LogLevel = iota
	// LogInfo is the informational severity level.
	LogInfo
	// LogWarn is the warning severity level.
	LogWarn
	// LogError is the highest severity level.
	LogError
)

type LogLine

type LogLine struct {
	Level     LogLevel
	Timestamp time.Time
	Message   string
	Source    string
}

LogLine is a single entry in the LogViewer.

type LogViewer

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

LogViewer is an append-only, auto-scrolling log display with level filtering, substring search, pause/resume, and goroutine-safe Append.

It implements Component and Themed.

func NewLogViewer

func NewLogViewer() *LogViewer

NewLogViewer creates a new LogViewer with default settings.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	lv := blit.NewLogViewer()
	lv.Append(blit.LogLine{Level: blit.LogInfo, Message: "Application started"})
	lv.Append(blit.LogLine{Level: blit.LogInfo, Message: "Connected to database"})
	_ = lv
}

func (*LogViewer) Append

func (lv *LogViewer) Append(line LogLine)

Append adds a LogLine to the viewer. Safe to call from any goroutine.

func (*LogViewer) Clear

func (lv *LogViewer) Clear()

Clear removes all log lines.

func (*LogViewer) Focused

func (lv *LogViewer) Focused() bool

Focused implements Component.

func (*LogViewer) Init

func (lv *LogViewer) Init() tea.Cmd

Init implements Component.

func (*LogViewer) KeyBindings

func (lv *LogViewer) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*LogViewer) Lines

func (lv *LogViewer) Lines() []LogLine

Lines returns a snapshot of all lines currently stored.

func (*LogViewer) SetFocused

func (lv *LogViewer) SetFocused(f bool)

SetFocused implements Component.

func (*LogViewer) SetSize

func (lv *LogViewer) SetSize(w, h int)

SetSize implements Component.

func (*LogViewer) SetTheme

func (lv *LogViewer) SetTheme(th Theme)

SetTheme implements Themed.

func (*LogViewer) Update

func (lv *LogViewer) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*LogViewer) View

func (lv *LogViewer) View() string

View implements Component.

type LoggingMetrics added in v0.2.24

type LoggingMetrics struct {
	Logger *slog.Logger
}

LoggingMetrics is a MetricsCollector that emits structured log entries for each event. Useful for development and debugging without an external metrics backend.

func (*LoggingMetrics) OnDispatch added in v0.2.24

func (m *LoggingMetrics) OnDispatch(component string, duration time.Duration)

OnDispatch logs the dispatch duration at debug level.

func (*LoggingMetrics) OnPanic added in v0.2.24

func (m *LoggingMetrics) OnPanic(component string, recovered any)

OnPanic logs a recovered panic at error level.

func (*LoggingMetrics) OnRender added in v0.2.24

func (m *LoggingMetrics) OnRender(duration time.Duration)

OnRender logs the render duration at debug level.

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

Menu is a popup overlay that displays a list of selectable items. It implements the Overlay interface.

func NewMenu added in v0.2.12

func NewMenu(opts MenuOpts) *Menu

NewMenu creates and opens a Menu with the given options.

func (m *Menu) Close()

Close implements Overlay.

func (m *Menu) CursorIndex() int

CursorIndex returns the currently highlighted item index.

func (m *Menu) Focused() bool

Focused implements Component.

func (m *Menu) Init() tea.Cmd

Init implements Component.

func (m *Menu) IsActive() bool

IsActive implements Overlay.

func (m *Menu) KeyBindings() []KeyBind

KeyBindings implements Component.

func (m *Menu) SetFocused(f bool)

SetFocused implements Component.

func (m *Menu) SetSize(w, h int)

SetSize implements Component.

func (m *Menu) SetTheme(theme Theme)

SetTheme implements Themed.

func (m *Menu) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (m *Menu) View() string

View implements Component.

type MenuItem struct {
	// Label is the display text.
	Label string

	// Shortcut is an optional key hint shown right-aligned (e.g. "ctrl+s").
	Shortcut string

	// Action is called when the item is activated. Optional.
	Action func()

	// Disabled greys out the item and prevents activation.
	Disabled bool

	// Separator, when true, renders this item as a horizontal divider.
	// Label, Shortcut, Action, and Disabled are ignored.
	Separator bool
}

MenuItem is a single entry in a Menu.

type MenuOpts struct {
	// Items are the menu entries.
	Items []MenuItem

	// OnClose is called when the menu is dismissed.
	OnClose func()

	// MinWidth sets a minimum width for the menu. 0 means auto.
	MinWidth int
}

MenuOpts configures a Menu.

type MetricsCollector added in v0.2.24

type MetricsCollector interface {
	// OnRender is called after each frame render with the time it took
	// to produce the View output for all visible components.
	OnRender(duration time.Duration)

	// OnDispatch is called after a tea.Msg is dispatched to a component,
	// with the component name and the time taken by its Update method.
	OnDispatch(component string, duration time.Duration)

	// OnPanic is called when a component panics during Update or View
	// and is recovered by the App's error boundary.
	OnPanic(component string, recovered any)
}

MetricsCollector receives timing and event data from the App's internal lifecycle. Implement this interface to integrate with Prometheus, Datadog, OpenTelemetry, or any custom metrics backend.

All methods are optional — nil receivers are safe. The App never blocks on metric emission; collectors should offload work if needed.

type Module added in v0.1.3

type Module interface {
	// Name returns a unique identifier for this module (e.g., "devConsole", "poller").
	Name() string

	// Init is called once before the first frame, after all modules are registered.
	// Return a tea.Cmd for background initialization work (or nil).
	Init() tea.Cmd

	// Update receives every message the App processes. Return the updated module
	// and an optional command. Modules see messages after overlays but before
	// components in the dispatch order.
	Update(msg tea.Msg, ctx Context) (Module, tea.Cmd)
}

Module is the interface for pluggable app extensions that participate in the App lifecycle. Modules receive messages, can emit commands, and optionally provide debug information and keybindings.

type ModuleWithKeybinds added in v0.1.3

type ModuleWithKeybinds interface {
	Module
	// Keybinds returns the keybindings this module contributes.
	Keybinds() []KeyBind
}

ModuleWithKeybinds is an optional extension of Module that contributes keybindings to the app's registry.

type ModuleWithProviders added in v0.1.3

type ModuleWithProviders interface {
	Module
	// Providers returns the debug providers this module contributes.
	Providers() []DebugProvider
}

ModuleWithProviders is an optional extension of Module that contributes debug providers to the DevConsole.

type MouseMsg added in v0.2.24

type MouseMsg = tea.MouseMsg

MouseMsg is an alias for tea.MouseMsg, sent on mouse events.

type Msg added in v0.2.24

type Msg = tea.Msg

Msg is an alias for tea.Msg, the universal message interface.

type MultiSelectField

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

MultiSelectField is a multi-choice field where users toggle options with space.

func NewMultiSelectField

func NewMultiSelectField(id, label string, options []string) *MultiSelectField

NewMultiSelectField creates a new multi-select field.

func (*MultiSelectField) FieldID

func (f *MultiSelectField) FieldID() string

func (*MultiSelectField) Init

func (f *MultiSelectField) Init() tea.Cmd

Init initializes the MultiSelectField component.

func (*MultiSelectField) Label

func (f *MultiSelectField) Label() string

func (*MultiSelectField) SetFocused

func (f *MultiSelectField) SetFocused(_ bool)

SetFocused sets the focus state of the MultiSelectField.

func (*MultiSelectField) SetValue

func (f *MultiSelectField) SetValue(v string)

SetValue sets the current value of the MultiSelectField.

func (*MultiSelectField) Update

func (f *MultiSelectField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates MultiSelectField state.

func (*MultiSelectField) Validate

func (f *MultiSelectField) Validate() error

Validate checks the current value against the field's validation rules.

func (*MultiSelectField) Value

func (f *MultiSelectField) Value() string

Value returns the current value of the MultiSelectField.

func (*MultiSelectField) View

func (f *MultiSelectField) View(focused bool, theme Theme, _ int) string

View renders the MultiSelectField as a string.

func (*MultiSelectField) WithHint

func (f *MultiSelectField) WithHint(hint string) *MultiSelectField

WithHint sets the hint text.

func (*MultiSelectField) WithRequired

func (f *MultiSelectField) WithRequired() *MultiSelectField

WithRequired marks the field as required (at least one option must be selected).

type Node

type Node struct {
	// Title is the display label for this node.
	Title string

	// Glyph is an optional icon prefix shown before the title.
	Glyph string

	// Detail is optional secondary text rendered after the title.
	Detail string

	// Children are the child nodes. Non-nil means this node is expandable.
	Children []*Node

	// Data is an arbitrary payload the caller can attach.
	Data any

	// Expanded controls whether children are visible.
	Expanded bool

	// Selected marks this node as selected (used in Single/Multi selection modes).
	Selected bool
}

Node is a single node in a Tree.

type NodeRenderFunc added in v0.2.12

type NodeRenderFunc func(node *Node, isCursor bool) string

NodeRenderFunc customises how a single node is rendered. It receives the node and whether it is currently highlighted by the cursor. Return the string that should appear in the tree line (connectors and selection indicators are still drawn by the Tree itself).

type NotifyMsg

type NotifyMsg struct {
	Text     string
	Duration time.Duration
}

NotifyMsg triggers a timed notification in the App.

type NumberField

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

NumberField is a text field that validates numeric input.

func NewNumberField

func NewNumberField(id, label string) *NumberField

NewNumberField creates a new numeric input field.

func (*NumberField) FieldID

func (f *NumberField) FieldID() string

func (*NumberField) Init

func (f *NumberField) Init() tea.Cmd

Init initializes the NumberField component.

func (*NumberField) Label

func (f *NumberField) Label() string

func (*NumberField) SetFocused

func (f *NumberField) SetFocused(focused bool)

SetFocused sets the focus state of the NumberField.

func (*NumberField) SetValue

func (f *NumberField) SetValue(v string)

SetValue sets the current value of the NumberField.

func (*NumberField) Update

func (f *NumberField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates NumberField state.

func (*NumberField) Validate

func (f *NumberField) Validate() error

Validate checks the current value against the field's validation rules.

func (*NumberField) Value

func (f *NumberField) Value() string

Value returns the current value of the NumberField.

func (*NumberField) View

func (f *NumberField) View(focused bool, theme Theme, width int) string

View renders the NumberField as a string.

func (*NumberField) WithDefault

func (f *NumberField) WithDefault(v float64) *NumberField

WithDefault sets the initial numeric value.

func (*NumberField) WithHint

func (f *NumberField) WithHint(hint string) *NumberField

WithHint sets the hint text.

func (*NumberField) WithMax

func (f *NumberField) WithMax(max float64) *NumberField

WithMax sets the maximum numeric value.

func (*NumberField) WithMin

func (f *NumberField) WithMin(min float64) *NumberField

WithMin sets the minimum numeric value.

func (*NumberField) WithPlaceholder

func (f *NumberField) WithPlaceholder(p string) *NumberField

WithPlaceholder sets the placeholder text.

func (*NumberField) WithRequired

func (f *NumberField) WithRequired() *NumberField

WithRequired marks the field as required.

type Option

type Option func(*appModel)

Option configures an App.

func WithAnimations

func WithAnimations(enabled bool) Option

WithAnimations enables or disables the internal animation tick bus (~60fps). Setting BLIT_NO_ANIM=1 in the environment overrides this to false.

func WithAutoUpdate

func WithAutoUpdate(cfg UpdateConfig) Option

WithAutoUpdate enables automatic update checking on app startup. In UpdateNotify mode, a notification is shown if an update is available. In UpdateBlocking mode, the user is prompted in stdout before the TUI starts.

func WithClock added in v0.2.24

func WithClock(c Clock) Option

WithClock sets the Clock implementation available to all components via Context.Clock. Useful for testing with a FakeClock. If not set, components should fall back to time.Now directly.

func WithComponent

func WithComponent(name string, c Component) Option

WithComponent registers a named component with the App.

Slot mapping: the first call populates SlotMain; subsequent calls stack additional components that share focus cycling with Main.

func WithDebugProvider added in v0.1.3

func WithDebugProvider(p DebugProvider) Option

WithDebugProvider registers a standalone debug provider with the DevConsole. For providers that are part of a module, implement ModuleWithProviders instead.

func WithDevConsole

func WithDevConsole() Option

WithDevConsole enables the dev console overlay on an App. The console is also auto-enabled when BLIT_DEVCONSOLE=1 is set in the environment. When this option is not provided and the env var is not set, the console costs nothing at runtime.

func WithFeatureFlags added in v0.2.24

func WithFeatureFlags(ff *FeatureFlag) Option

WithFeatureFlags registers a FeatureFlag registry with the App. Components can check flags via Context.Flags to conditionally enable or disable behavior at runtime.

func WithFocusCycleKey

func WithFocusCycleKey(key string) Option

WithFocusCycleKey changes the key used to cycle focus between panes. Default is "tab". Set to "" to disable focus cycling entirely.

func WithHelp

func WithHelp() Option

WithHelp enables the auto-generated help overlay (toggle with '?').

func WithKeyBind

func WithKeyBind(kb KeyBind) Option

WithKeyBind adds a global keybinding with an optional handler. If Handler is set, it's called when the key is pressed. The binding also appears in the auto-generated help screen.

func WithLayout

func WithLayout(l *DualPane) Option

WithLayout sets a dual-pane layout.

Slot mapping: DualPane.Main -> SlotMain, DualPane.Side -> SlotSidebar.

func WithLogger added in v0.2.24

func WithLogger(l *slog.Logger) Option

WithLogger sets a structured logger that is available to all components via Context.Logger. If not set, Context.Logger is nil (components should treat nil as "logging disabled").

func WithMetrics added in v0.2.24

func WithMetrics(collector MetricsCollector) Option

WithMetrics attaches a MetricsCollector that receives timing and event data from the App's internal lifecycle. Use it to integrate with Prometheus, Datadog, OpenTelemetry, or the built-in LoggingMetrics.

func WithModule added in v0.1.3

func WithModule(m Module) Option

WithModule registers a module with the App. Modules are initialized in registration order during Init and receive all messages during Update.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	// Modules extend the App with custom lifecycle behavior.
	// Built-in modules include the DevConsole and Poller.
	app := blit.NewApp(
		blit.WithTheme(blit.DefaultTheme()),
		blit.WithDevConsole(),
	)
	_ = app
}

func WithMouseSupport

func WithMouseSupport() Option

WithMouseSupport enables mouse event tracking.

func WithOnError added in v0.2.24

func WithOnError(fn func(component string, recovered any)) Option

WithOnError registers a callback invoked when a component panics during Update or View and is recovered by the App's error boundary. The hook receives the component name and the recovered panic value. Use it to integrate with Sentry, Bugsnag, Rollbar, or any error tracking backend.

func WithOverlay

func WithOverlay(name string, triggerKey string, o Overlay) Option

WithOverlay registers a named overlay with an explicit trigger key. Press triggerKey to open the overlay; Esc closes it.

Slot mapping: the overlay is pushed onto SlotOverlay.

func WithSlot

func WithSlot(name SlotName, c Component) Option

WithSlot binds a component to a named slot. This is the canonical way to compose an App shell in v0.10+.

Behaviour per slot:

  • SlotMain, SlotSidebar, SlotHeader, SlotFooter, SlotToast — single occupant; calling WithSlot twice replaces the previous value.
  • SlotOverlay — stacks; each WithSlot call pushes another overlay. Use WithSlotOverlay to attach a trigger key.

When both SlotMain and SlotSidebar are populated, the App implicitly wires them into a DualPane. Use WithLayout directly if you need to customise widths, toggle keys, or side placement.

func WithSlotOverlay

func WithSlotOverlay(name, triggerKey string, o Overlay) Option

WithSlotOverlay pushes an overlay into SlotOverlay with an associated trigger key and display name. It is the slot-native equivalent of WithOverlay.

func WithStatusBar

func WithStatusBar(left, right func() string) Option

WithStatusBar adds a status bar at the bottom of the screen.

left and right are legacy `func() string` closures. For reactive status bar content driven by signals, use WithStatusBarSignal.

Slot mapping: the resulting StatusBar is bound to SlotFooter.

func WithStatusBarSignal

func WithStatusBarSignal(left, right *Signal[string]) Option

WithStatusBarSignal adds a status bar whose left and right content are driven by *Signal[string]. Either may be nil. Prefer this over WithStatusBar when the values change asynchronously (background polling, websocket streams, etc.) — updates collapse into one notification per frame thanks to Signal's dirty-bit coalescing.

func WithTheme

func WithTheme(t Theme) Option

WithTheme sets the theme for all components.

func WithThemeHotReload

func WithThemeHotReload(path string) Option

WithThemeHotReload returns an AppOption that watches the YAML file at path and live-reloads the theme whenever the file changes. The reload is debounced by 200 ms. If the file cannot be parsed the current theme is kept and an error toast is shown.

func WithTickInterval

func WithTickInterval(d time.Duration) Option

WithTickInterval enables periodic tick messages at the given interval. Components receive TickMsg in their Update method.

type Orientation

type Orientation int

Orientation controls whether Split divides the space horizontally or vertically.

const (
	// Horizontal splits left/right (A on left, B on right).
	Horizontal Orientation = iota
	// Vertical splits top/bottom (A on top, B on bottom).
	Vertical
)

type Overlay

type Overlay interface {
	Component

	// IsActive returns whether this overlay is currently visible.
	IsActive() bool

	// Close hides this overlay.
	Close()
}

Overlay is a modal view that stacks on top of the main UI. The App manages an overlay stack — Esc pops the top overlay.

type PasswordField

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

PasswordField is a single-line text input that masks its value.

func NewPasswordField

func NewPasswordField(id, label string) *PasswordField

NewPasswordField creates a new password input field.

func (*PasswordField) FieldID

func (f *PasswordField) FieldID() string

func (*PasswordField) Init

func (f *PasswordField) Init() tea.Cmd

Init initializes the PasswordField component.

func (*PasswordField) Label

func (f *PasswordField) Label() string

func (*PasswordField) SetFocused

func (f *PasswordField) SetFocused(focused bool)

SetFocused sets the focus state of the PasswordField.

func (*PasswordField) SetValue

func (f *PasswordField) SetValue(v string)

SetValue sets the current value of the PasswordField.

func (*PasswordField) Update

func (f *PasswordField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates PasswordField state.

func (*PasswordField) Validate

func (f *PasswordField) Validate() error

Validate checks the current value against the field's validation rules.

func (*PasswordField) Value

func (f *PasswordField) Value() string

Value returns the current value of the PasswordField.

func (*PasswordField) View

func (f *PasswordField) View(focused bool, theme Theme, width int) string

View renders the PasswordField as a string.

func (*PasswordField) WithHint

func (f *PasswordField) WithHint(hint string) *PasswordField

WithHint sets the hint text.

func (*PasswordField) WithPlaceholder

func (f *PasswordField) WithPlaceholder(p string) *PasswordField

WithPlaceholder sets the placeholder text.

func (*PasswordField) WithRequired

func (f *PasswordField) WithRequired() *PasswordField

WithRequired marks the field as required.

func (*PasswordField) WithValidator

func (f *PasswordField) WithValidator(v Validator) *PasswordField

WithValidator attaches a validator function.

type Picker

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

Picker is a fuzzy-searchable command palette that can be used as either a full-screen Overlay (Cmd-K style) or as an embedded Component.

func NewPicker

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

NewPicker creates a Picker with the given items and options.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	items := []blit.PickerItem{
		{Title: "Dark", Value: "dark"},
		{Title: "Light", Value: "light"},
		{Title: "Retro", Value: "retro"},
	}
	picker := blit.NewPicker(items, blit.PickerOpts{
		Placeholder: "Choose a theme...",
	})
	_ = picker
}

func (*Picker) Close

func (p *Picker) Close()

Close implements Overlay.

func (*Picker) CursorItem

func (p *Picker) CursorItem() *PickerItem

CursorItem returns the currently highlighted item, or nil if there are none.

func (*Picker) Focused

func (p *Picker) Focused() bool

Focused implements Component.

func (*Picker) Init

func (p *Picker) Init() tea.Cmd

Init implements Component.

func (*Picker) IsActive

func (p *Picker) IsActive() bool

IsActive implements Overlay.

func (*Picker) Items

func (p *Picker) Items() []PickerItem

Items returns the full (unfiltered) item list.

func (*Picker) KeyBindings

func (p *Picker) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Picker) Open

func (p *Picker) Open()

Open activates the picker and focuses the input.

func (*Picker) SetFocused

func (p *Picker) SetFocused(f bool)

SetFocused implements Component.

func (*Picker) SetItems

func (p *Picker) SetItems(items []PickerItem)

SetItems replaces the item list and re-runs the filter.

func (*Picker) SetSize

func (p *Picker) SetSize(w, h int)

SetSize implements Component.

func (*Picker) SetTheme

func (p *Picker) SetTheme(t Theme)

SetTheme implements Themed.

func (*Picker) Update

func (p *Picker) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Picker) View

func (p *Picker) View() string

View implements Component.

type PickerItem

type PickerItem struct {
	// Title is the primary display label.
	Title string

	// Subtitle is secondary text shown below the title. Optional.
	Subtitle string

	// Glyph is an optional icon/glyph prefix.
	Glyph string

	// Preview returns content shown in the preview pane when this item is
	// highlighted. Called lazily on cursor change. Optional.
	Preview func() string

	// Value is an arbitrary payload the caller can attach.
	Value any
}

PickerItem is a single entry in a Picker.

type PickerOpts

type PickerOpts struct {
	// Placeholder text shown in the filter input when empty.
	Placeholder string

	// Preview enables the right-side preview pane (40% width).
	Preview bool

	// OnConfirm is called when the user presses Enter on an item. Optional.
	OnConfirm func(item PickerItem)

	// OnCancel is called when the user closes the picker without confirming.
	OnCancel func()
}

PickerOpts configures Picker behaviour.

type Poller

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

Poller manages periodic command execution on top of blit's TickMsg. Create one with NewPoller, then call Check from your component's Update when it receives a TickMsg. The Poller handles interval timing, pause/resume, and force-refresh.

For enhanced features (rate limiting, backoff, DevConsole integration), use NewPollerWithOpts.

func NewPoller

func NewPoller(interval time.Duration, cmd func() tea.Cmd) *Poller

NewPoller creates a Poller that runs cmd at the given interval using the real system clock. For deterministic tests, use NewPollerWithClock.

Example
package main

import (
	"time"

	tea "github.com/charmbracelet/bubbletea"

	blit "github.com/blitui/blit"
)

func main() {
	fetchData := func() tea.Cmd {
		return func() tea.Msg {
			return "fetched"
		}
	}
	poller := blit.NewPoller(30*time.Second, fetchData)

	// In your component's Update:
	//   case blit.TickMsg:
	//       return m, poller.Check(msg.(blit.TickMsg))
	_ = poller
}

func NewPollerWithClock

func NewPollerWithClock(interval time.Duration, cmd func() tea.Cmd, clock Clock) *Poller

NewPollerWithClock creates a Poller that uses the supplied Clock for all timing decisions. Pass a FakeClock in tests to advance time deterministically. A nil clock is treated as the real clock.

func NewPollerWithOpts added in v0.1.3

func NewPollerWithOpts(opts PollerOpts) *Poller

NewPollerWithOpts creates an enhanced Poller configured via PollerOpts. The enhanced Poller supports rate limiting, backoff strategies, error tracking, and DevConsole integration. The returned Poller is fully compatible with the existing Check/Pause/Resume API.

Example
package main

import (
	"time"

	tea "github.com/charmbracelet/bubbletea"

	blit "github.com/blitui/blit"
)

func main() {
	poller := blit.NewPollerWithOpts(blit.PollerOpts{
		Name:     "api-events",
		Interval: 30 * time.Second,
		Fetch: func() (tea.Msg, error) {
			return "events fetched", nil
		},
		Backoff:    blit.ExponentialBackoff(time.Second, 5*time.Minute),
		MaxRetries: 3,
	})
	_ = poller
}
Example (FetchCtx)
package main

import (
	"context"
	"time"

	tea "github.com/charmbracelet/bubbletea"

	blit "github.com/blitui/blit"
)

func main() {
	poller := blit.NewPollerWithOpts(blit.PollerOpts{
		Name:     "api-events",
		Interval: 30 * time.Second,
		FetchCtx: func(ctx context.Context) (tea.Msg, error) {
			// Use ctx for HTTP request cancellation, timeouts, etc.
			return "events fetched", nil
		},
		Backoff:    blit.ExponentialBackoff(time.Second, 5*time.Minute),
		MaxRetries: 3,
	})
	_ = poller
}

func (*Poller) Check

func (p *Poller) Check(msg TickMsg) tea.Cmd

Check should be called from your component's Update when receiving a TickMsg. Returns a tea.Cmd if it's time to poll, nil otherwise. ForceRefresh takes priority and works even when paused. For enhanced pollers, rate limiting is respected (except on ForceRefresh). Enhanced pollers emit a PollerStartMsg before the fetch begins.

func (*Poller) ClearRateLimit added in v0.1.3

func (p *Poller) ClearRateLimit()

ClearRateLimit removes the rate limit flag.

func (*Poller) DebugProvider added in v0.1.3

func (p *Poller) DebugProvider() DebugDataProvider

DebugProvider returns a DebugDataProvider for this Poller suitable for registration with the DevConsole. Returns nil for non-enhanced pollers.

func (*Poller) ForceRefresh

func (p *Poller) ForceRefresh()

ForceRefresh triggers a poll on the next Check call, even if paused.

func (*Poller) IsPaused

func (p *Poller) IsPaused() bool

IsPaused returns whether polling is paused.

func (*Poller) LastPoll

func (p *Poller) LastPoll() time.Time

LastPoll returns the time of the last successful poll.

func (*Poller) NextPoll added in v0.1.3

func (p *Poller) NextPoll() time.Time

NextPoll returns the estimated time of the next poll. Returns the zero value if the poller is paused or has never polled.

func (*Poller) Pause

func (p *Poller) Pause()

Pause stops periodic polling. ForceRefresh still works when paused.

func (*Poller) Resume

func (p *Poller) Resume()

Resume resumes periodic polling.

func (*Poller) SetInterval

func (p *Poller) SetInterval(d time.Duration)

SetInterval changes the polling interval.

func (*Poller) SetRateLimited added in v0.1.3

func (p *Poller) SetRateLimited(resetAt time.Time)

SetRateLimited marks this poller as rate limited until resetAt. While rate limited, Check will not fire. The OnRateLimit callback is invoked if set.

func (*Poller) Stats added in v0.1.3

func (p *Poller) Stats() PollerStats

Stats returns the current state of this Poller for DevConsole display. For pollers created with NewPoller (non-enhanced), Stats returns a minimal PollerStats with interval and pause state.

func (*Poller) Stop added in v0.2.24

func (p *Poller) Stop()

Stop cancels any in-flight context-aware fetch and prevents further retries. It is safe to call Stop multiple times.

func (*Poller) TogglePause

func (p *Poller) TogglePause()

TogglePause toggles between paused and active.

type PollerErrorMsg added in v0.1.3

type PollerErrorMsg struct {
	Name     string
	Err      error
	Attempts int
	Toast    *ToastMsg
}

PollerErrorMsg is sent when all retries are exhausted. When AutoToast is enabled, Toast is populated with a pre-built ToastMsg that the consumer can return as a Cmd for automatic toast display.

type PollerOpts added in v0.1.3

type PollerOpts struct {
	// Name identifies this poller in DevConsole and log messages.
	Name string

	// Interval between poll attempts. Must be >= 100ms. Default: 30s.
	Interval time.Duration

	// Fetch is called on each poll. Returns a tea.Msg on success or error.
	Fetch func() (tea.Msg, error)

	// FetchCtx is an optional context-aware fetch function. When set, it takes
	// priority over Fetch. The context is cancelled when the Poller is stopped
	// or the App quits. Use this when your fetch logic needs cancellation
	// support (e.g., HTTP requests with timeouts).
	FetchCtx func(ctx context.Context) (tea.Msg, error)

	// OnRateLimit is called when rate limiting is detected. Optional.
	OnRateLimit func(resetAt time.Time)

	// OnError is called when a fetch fails after all retries. Optional.
	OnError func(err error)

	// Backoff configures retry behavior. Default: ExponentialBackoff(1s, 5m).
	Backoff BackoffStrategy

	// MaxRetries is the maximum number of retry attempts. Default: 3.
	MaxRetries int

	// AutoToast enables automatic toast notifications on fetch errors and
	// rate limiting. When true, PollerErrorMsg and PollerRateLimitedMsg
	// include a pre-built Toast field that can be returned as a Cmd.
	AutoToast bool

	// Clock for testing. Default: real clock.
	Clock Clock
}

PollerOpts configures an enhanced Poller with rate limiting and backoff.

type PollerRateLimitedMsg added in v0.1.3

type PollerRateLimitedMsg struct {
	Name    string
	ResetAt time.Time
	Toast   *ToastMsg
}

PollerRateLimitedMsg is sent on rate limit detection. When AutoToast is enabled, Toast is populated with a pre-built ToastMsg that the consumer can return as a Cmd for automatic toast display.

type PollerStartMsg added in v0.1.3

type PollerStartMsg struct{ Name string }

PollerStartMsg is sent when a fetch begins.

type PollerStats added in v0.1.3

type PollerStats struct {
	Name              string
	LastPoll          time.Time
	NextPoll          time.Time
	Interval          time.Duration
	IsPaused          bool
	ErrorCount        int
	ConsecutiveErrors int
	LastError         error
	IsRateLimited     bool
	RateLimitReset    time.Time
}

PollerStats contains the current state of a Poller for DevConsole display.

type PollerSuccessMsg added in v0.1.3

type PollerSuccessMsg struct {
	Name string
	Msg  tea.Msg
}

PollerSuccessMsg wraps the successful fetch result.

type Position added in v0.2.24

type Position = lipgloss.Position

Position is an alias for lipgloss.Position, used for layout placement.

type ProgressBar added in v0.2.12

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

ProgressBar is a horizontal bar that fills proportionally to a value in [0,1]. It implements Component and Themed.

func NewProgressBar added in v0.2.12

func NewProgressBar(opts ProgressBarOpts, value float64) *ProgressBar

NewProgressBar creates a ProgressBar with the given options and initial value. The value is clamped to [0, 1].

func (*ProgressBar) Focused added in v0.2.12

func (p *ProgressBar) Focused() bool

Focused implements Component.

func (*ProgressBar) Increment added in v0.2.12

func (p *ProgressBar) Increment(delta float64)

Increment adds delta to the current value (clamped to [0, 1]).

func (*ProgressBar) Init added in v0.2.12

func (p *ProgressBar) Init() tea.Cmd

Init implements Component.

func (*ProgressBar) KeyBindings added in v0.2.12

func (p *ProgressBar) KeyBindings() []KeyBind

KeyBindings implements Component. ProgressBar has no key bindings.

func (*ProgressBar) SetFocused added in v0.2.12

func (p *ProgressBar) SetFocused(f bool)

SetFocused implements Component.

func (*ProgressBar) SetSize added in v0.2.12

func (p *ProgressBar) SetSize(w, h int)

SetSize implements Component.

func (*ProgressBar) SetTheme added in v0.2.12

func (p *ProgressBar) SetTheme(theme Theme)

SetTheme implements Themed.

func (*ProgressBar) SetValue added in v0.2.12

func (p *ProgressBar) SetValue(v float64)

SetValue updates the progress. The value is clamped to [0, 1].

func (*ProgressBar) Update added in v0.2.12

func (p *ProgressBar) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component. ProgressBar is display-only and does not consume any messages.

func (*ProgressBar) Value added in v0.2.12

func (p *ProgressBar) Value() float64

Value returns the current progress value in [0, 1].

func (*ProgressBar) View added in v0.2.12

func (p *ProgressBar) View() string

View implements Component.

type ProgressBarOpts added in v0.2.12

type ProgressBarOpts struct {
	// Label is optional text shown to the left of the bar.
	Label string

	// ShowPercent displays the percentage to the right of the bar.
	ShowPercent bool

	// Width overrides the bar width. If 0, the component uses its SetSize width.
	Width int
}

ProgressBarOpts configures a ProgressBar.

type ProgressFunc

type ProgressFunc func(received, total int64)

ProgressFunc is called during download with bytes received and total bytes. If total is -1, the content length is unknown.

type RateLimitError

type RateLimitError struct {
	StatusCode int
	ResetAt    time.Time
	Body       string
}

RateLimitError is returned when GitHub's rate limiter rejects a request. ResetAt is the wall-clock time at which the rate limit window resets (parsed from the X-RateLimit-Reset header); zero if unknown.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

Error returns the error message.

type RateLimitInfo added in v0.2.24

type RateLimitInfo struct {
	Remaining int
	Limit     int
}

RateLimitInfo holds rate limit status for an API.

type Registry

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

Registry collects keybindings from all components and provides grouped access for the help screen and conflict detection.

type Release

type Release struct {
	TagName    string         `json:"tag_name"`
	HTMLURL    string         `json:"html_url"`
	Body       string         `json:"body"`
	Assets     []ReleaseAsset `json:"assets"`
	Prerelease bool           `json:"prerelease"`
}

Release represents a GitHub release.

func FetchLatestRelease

func FetchLatestRelease(baseURL, owner, repo string) (*Release, error)

FetchLatestRelease fetches the latest release from GitHub. baseURL is the API base (e.g. "https://api.github.com" or a test server URL).

func FetchLatestReleaseForChannel

func FetchLatestReleaseForChannel(baseURL, owner, repo, channel string) (*Release, error)

FetchLatestReleaseForChannel selects the appropriate release for the configured channel. Stable falls through to FetchLatestRelease for backward compatibility; non-stable channels walk /releases.

func FetchReleases

func FetchReleases(baseURL, owner, repo string) ([]Release, error)

FetchReleases returns the full list of releases for the repo, newest first, using the rate-limited fetcher.

func PickReleaseForChannel

func PickReleaseForChannel(releases []Release, channel string) *Release

PickReleaseForChannel filters releases according to the update channel:

  • stable: first non-prerelease release (tag without a pre-release suffix)
  • beta: first release whose tag contains "-beta"
  • prerelease: first release marked Prerelease=true or tag containing "-"

Returns nil if no matching release is found.

type ReleaseAsset

type ReleaseAsset struct {
	Name        string `json:"name"`
	DownloadURL string `json:"browser_download_url"`
}

ReleaseAsset represents a single asset in a GitHub release.

func MatchAsset

func MatchAsset(assets []ReleaseAsset, binaryName, goos, goarch string) (ReleaseAsset, error)

MatchAsset finds the release asset matching the given binary name, OS, and architecture.

func MatchChecksumAsset

func MatchChecksumAsset(assets []ReleaseAsset) (ReleaseAsset, error)

MatchChecksumAsset finds the checksums.txt asset in a release.

func MatchDeltaAsset

func MatchDeltaAsset(assets []ReleaseAsset, binaryName, fromVersion, toVersion, goos, goarch string) (ReleaseAsset, error)

MatchDeltaAsset looks for a delta patch asset that upgrades fromVersion to toVersion for the given binary, OS, and architecture. Both version strings are normalized by stripping a leading "v" so callers can pass either form. Returns an error if no matching asset exists.

func MatchSigAsset

func MatchSigAsset(assets []ReleaseAsset, assetName string) (ReleaseAsset, error)

MatchSigAsset finds the detached signature asset for the given asset name. GoReleaser cosign integration appends ".sig" to each asset name.

type ReleaseNotesOverlay

type ReleaseNotesOverlay struct {
	Title   string
	Version string
	Lines   []string
	Offset  int
	Width   int
	Height  int
	Closed  bool
	// contains filtered or unexported fields
}

ReleaseNotesOverlay is a scrollable overlay that displays release notes text from an UpdateResult. It is meant to be opened from the notify banner or the forced update screen via a keybind ("n" by convention).

The overlay is self-contained: it tracks scroll offset, renders a bordered box, and closes itself when the user presses q/esc.

When a Theme has been set via SetTheme, release notes are rendered through Markdown() so that headings, code spans, and lists are styled. BREAKING and SECURITY section headings are additionally highlighted using the theme's Negative and Flash color tokens.

func NewReleaseNotesOverlay

func NewReleaseNotesOverlay(version, notes string) *ReleaseNotesOverlay

NewReleaseNotesOverlay constructs an overlay for the given release notes text. Width/height default to 80x24.

func NewReleaseNotesOverlayThemed

func NewReleaseNotesOverlayThemed(version, notes string, t Theme) *ReleaseNotesOverlay

NewReleaseNotesOverlayThemed is like NewReleaseNotesOverlay but immediately applies a theme so the notes are rendered through Markdown from the start.

func (*ReleaseNotesOverlay) Init

func (o *ReleaseNotesOverlay) Init() tea.Cmd

Init implements tea.Model.

func (*ReleaseNotesOverlay) MaxOffset

func (o *ReleaseNotesOverlay) MaxOffset() int

MaxOffset clamps scroll position to the last full page.

func (*ReleaseNotesOverlay) SetTheme

func (o *ReleaseNotesOverlay) SetTheme(t Theme)

SetTheme implements the Themed interface. When set, release notes are rendered through Markdown() with BREAKING/SECURITY section highlighting.

func (*ReleaseNotesOverlay) Update

func (o *ReleaseNotesOverlay) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model.

func (*ReleaseNotesOverlay) View

func (o *ReleaseNotesOverlay) View() string

View implements tea.Model.

func (*ReleaseNotesOverlay) VisibleLines

func (o *ReleaseNotesOverlay) VisibleLines() int

VisibleLines returns the number of content rows rendered per frame. Two lines are reserved for the header and one for the footer, plus the border/padding (4). Minimum of 1.

type RetryErrorMsg added in v0.1.1

type RetryErrorMsg struct {
	Err      error
	Attempts int
}

RetryErrorMsg is returned when all retry attempts are exhausted.

type RetryOpts added in v0.1.1

type RetryOpts struct {
	// MaxAttempts is the total number of attempts (including the first).
	// Must be >= 1. Default: 3.
	MaxAttempts int

	// Backoff is the initial delay between retries. Each subsequent retry
	// doubles the delay (exponential backoff). Default: 500ms.
	Backoff time.Duration
}

RetryOpts configures retry behavior for RetryCmd.

type Row

type Row []string

Row is a slice of cell values, one per column.

type RowClickHandler

type RowClickHandler func(row Row, rowIdx int)

RowClickHandler is called when a row is clicked or Enter is pressed.

type RowStyler

type RowStyler func(row Row, idx int, isCursor bool, theme Theme) *lipgloss.Style

RowStyler returns an optional lipgloss.Style to apply to an entire row. Use this for full-row highlights (cursor, flash effects, alerts) when a CellRenderer is also in use. Return nil for no row-level styling.

type SelectField

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

SelectField is a single-choice field rendered as a cycling selector.

func NewSelectField

func NewSelectField(id, label string, options []string) *SelectField

NewSelectField creates a new select field with the given options.

func (*SelectField) FieldID

func (f *SelectField) FieldID() string

func (*SelectField) Init

func (f *SelectField) Init() tea.Cmd

Init initializes the SelectField component.

func (*SelectField) Label

func (f *SelectField) Label() string

func (*SelectField) SetFocused

func (f *SelectField) SetFocused(_ bool)

SetFocused sets the focus state of the SelectField.

func (*SelectField) SetValue

func (f *SelectField) SetValue(v string)

SetValue sets the current value of the SelectField.

func (*SelectField) Update

func (f *SelectField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates SelectField state.

func (*SelectField) Validate

func (f *SelectField) Validate() error

Validate checks the current value against the field's validation rules.

func (*SelectField) Value

func (f *SelectField) Value() string

Value returns the current value of the SelectField.

func (*SelectField) View

func (f *SelectField) View(focused bool, theme Theme, _ int) string

View renders the SelectField as a string.

func (*SelectField) WithDefault

func (f *SelectField) WithDefault(v string) *SelectField

WithDefault sets the initially-selected option by value.

func (*SelectField) WithHint

func (f *SelectField) WithHint(hint string) *SelectField

WithHint sets the hint text.

func (*SelectField) WithRequired

func (f *SelectField) WithRequired() *SelectField

WithRequired marks the field as required.

func (*SelectField) WithValidator

func (f *SelectField) WithValidator(v Validator) *SelectField

WithValidator attaches a validator.

type SelectionMode added in v0.2.12

type SelectionMode int

SelectionMode controls how node selection behaves in a Tree.

const (
	// SelectionNone disables selection state tracking. Enter triggers OnSelect only.
	SelectionNone SelectionMode = iota
	// SelectionSingle allows at most one selected node at a time.
	SelectionSingle
	// SelectionMulti allows any number of selected nodes (checkbox style).
	SelectionMulti
)

type ServeConfig

type ServeConfig struct {
	// Addr is the host:port to listen on. Defaults to ":2222".
	Addr string

	// HostKeyPath is the path to the ED25519 host key file.
	// If empty, defaults to ~/.ssh/blit_host_ed25519 and is auto-generated
	// with 0600 permissions on first run.
	HostKeyPath string

	// Middleware is a list of additional Wish middleware to apply after the
	// built-in bubbletea and activeterm middlewares.
	Middleware []wish.Middleware

	// AuthorizedKeys is the path to an SSH authorized_keys file used to
	// restrict access. If empty, all connections are accepted (use only in
	// trusted networks).
	AuthorizedKeys string

	// Factory is called once per incoming SSH session to produce a fresh *App.
	// Each connection gets its own App instance so state is per-connection.
	Factory func() *App
}

ServeConfig configures the SSH server started by Serve.

type SetThemeMsg

type SetThemeMsg struct {
	Theme Theme
}

SetThemeMsg is a Bubble Tea message that asks the App to swap its theme.

type Signal

type Signal[T any] struct {
	// contains filtered or unexported fields
}

Signal is a reactive, race-safe container for a value of type T.

Writers call Set from any goroutine; Subscribers are always invoked on the UI goroutine (inside the App's tea.Msg dispatch). Multiple Set calls that land within the same frame collapse into a single notification per subscriber thanks to a dirty-bit + generation counter that coalesces pending flushes.

Signals are typically created at App construction time and passed to components that accept a *Signal[T]. Components re-read Get() in their View() method; the App schedules a re-render whenever a signal flush is processed.

Example:

status := blit.NewSignal("starting...")
app := blit.NewApp(
    blit.WithStatusBarSignal(status, nil),
)
go func() {
    time.Sleep(time.Second)
    status.Set("ready") // safe from any goroutine
}()

func Computed

func Computed[T any](deps []AnySignal, calc func() T) *Signal[T]

Computed derives a new signal from deps. calc is re-run on the UI goroutine whenever any dep flushes; the derived signal then notifies its own subscribers.

func NewSignal

func NewSignal[T any](initial T) *Signal[T]

NewSignal creates a signal with the given initial value.

Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	status := blit.NewSignal("starting...")

	// Read from any goroutine.
	fmt.Println(status.Get())

	// Write from any goroutine; subscribers fire on the UI goroutine.
	status.Set("ready")
	fmt.Println(status.Get())
}
Output:
starting...
ready

func (*Signal[T]) Get

func (s *Signal[T]) Get() T

Get returns the current value. Safe to call from any goroutine.

func (*Signal[T]) Set

func (s *Signal[T]) Set(v T)

Set stores v and schedules a single coalesced notification on the next flush. Safe to call from any goroutine; subscribers still run on the UI goroutine.

func (*Signal[T]) Subscribe

func (s *Signal[T]) Subscribe(fn func(T)) Unsubscribe

Subscribe registers fn to receive the signal's value on every flush after Set. The callback is always invoked on the UI goroutine. The returned Unsubscribe removes the registration.

Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	count := blit.NewSignal(0)

	unsub := count.Subscribe(func(v int) {
		fmt.Println("count is now", v)
	})
	defer unsub()

	// Set triggers the subscriber on the next signal flush.
	count.Set(42)
	_ = count
}

type Size

type Size struct {
	Width  int
	Height int
}

Size is the width and height available to a component.

type Sized

type Sized struct {
	W int       // Fixed width (HBox) or height (VBox) in columns/rows.
	C Component // The wrapped component.
}

Sized wraps a Component with a fixed size on the main axis. In HBox the size is a fixed width; in VBox it is a fixed height.

func (Sized) Focused

func (s Sized) Focused() bool

Focused reports whether the Sized is focused.

func (Sized) Init

func (s Sized) Init() tea.Cmd

Init initializes the Sized component.

func (Sized) KeyBindings

func (s Sized) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Sized.

func (Sized) SetFocused

func (s Sized) SetFocused(f bool)

SetFocused sets the focus state of the Sized.

func (Sized) SetSize

func (s Sized) SetSize(w, h int)

SetSize sets the width and height of the Sized.

func (Sized) SetTheme added in v0.2.24

func (s Sized) SetTheme(t Theme)

SetTheme delegates theme propagation to the inner component if it implements Themed. This ensures runtime theme switching reaches children inside HBox/VBox layouts.

func (Sized) Update

func (s Sized) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Sized state.

func (Sized) View

func (s Sized) View() string

View renders the Sized as a string.

type SlotName

type SlotName string

SlotName identifies a named region in the App shell.

Slots are the canonical way to assemble an App as of v0.10. Instead of juggling separate options for components, layouts, status bars, and overlays, you declare each region by name:

app := blit.NewApp(
    blit.WithSlot(blit.SlotMain, table),
    blit.WithSlot(blit.SlotSidebar, panel),
    blit.WithSlot(blit.SlotFooter, statusBar),
    blit.WithSlot(blit.SlotOverlay, configEditor),
)

The legacy options (WithComponent, WithLayout, WithStatusBar, WithOverlay) continue to work and are routed through the slot registry internally, so both styles can be mixed freely during migration. Legacy mapping:

WithComponent(name, c)              -> SlotMain (first call) or stacked component list
WithLayout(&DualPane{Main:m,Side:s}) -> SlotMain = m, SlotSidebar = s
WithStatusBar(l, r)                 -> SlotFooter = StatusBar
WithStatusBarSignal(l, r)           -> SlotFooter = StatusBar
WithOverlay(name, key, o)           -> SlotOverlay (keyed by name)

Slot names are stable identifiers. Use the SlotXxx constants below rather than hard-coding strings so a typo surfaces at compile time.

const (
	// SlotHeader renders above the main content area.
	SlotHeader SlotName = "header"

	// SlotMain holds the primary component. When combined with SlotSidebar,
	// the two form a DualPane automatically.
	SlotMain SlotName = "main"

	// SlotSidebar holds the side panel, paired with SlotMain in a DualPane.
	SlotSidebar SlotName = "sidebar"

	// SlotFooter renders below the main content, above the toast/overlay
	// areas. The built-in StatusBar is placed here by WithStatusBar.
	SlotFooter SlotName = "footer"

	// SlotOverlay holds stacked modal overlays. Multiple WithSlot calls to
	// SlotOverlay push additional overlays onto the stack in order.
	SlotOverlay SlotName = "overlay"

	// SlotToast is the toast stack region. Currently drives the existing
	// toastManager; adding a custom component here is reserved for a
	// future release.
	SlotToast SlotName = "toast"
)

type SortFunc

type SortFunc func(a, b Row, sortCol int, sortAsc bool) bool

SortFunc compares two rows for custom sorting. sortCol is the current sort column index, sortAsc is the sort direction. Return true if row a should come before row b.

type SourceHealth added in v0.2.24

type SourceHealth struct {
	LastSuccess bool
	FailStreak  int
	UsingCache  bool
	LastFetchAt time.Time
	ItemCount   int
}

SourceHealth tracks the health of a single data source.

type SparklineOpts

type SparklineOpts struct {
	// UpStyle styles bars that are higher than the previous bar.
	// If zero value, defaults to green (#00ff88).
	UpStyle lipgloss.Style
	// DownStyle styles bars that are lower than the previous bar.
	// If zero value, defaults to red (#ff4444).
	DownStyle lipgloss.Style
	// NeutralStyle styles bars with no change from the previous bar.
	// If zero value, defaults to dim gray (#666666).
	NeutralStyle lipgloss.Style
	// Mono renders all bars in a single style (NeutralStyle) instead of
	// coloring by direction. Useful for detail views.
	Mono bool
}

SparklineOpts configures sparkline rendering.

type Spinner added in v0.2.12

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

Spinner is an animated loading indicator that cycles through glyph frames. Implements Component and Themed.

func NewSpinner added in v0.2.12

func NewSpinner(opts SpinnerOpts) *Spinner

NewSpinner creates a Spinner with the given options.

func (*Spinner) Active added in v0.2.12

func (s *Spinner) Active() bool

Active returns whether the spinner is animating.

func (*Spinner) Focused added in v0.2.12

func (s *Spinner) Focused() bool

Focused implements Component.

func (*Spinner) Frame added in v0.2.12

func (s *Spinner) Frame() int

Frame returns the current frame index.

func (*Spinner) Init added in v0.2.12

func (s *Spinner) Init() tea.Cmd

Init implements Component. It schedules the first tick.

func (*Spinner) KeyBindings added in v0.2.12

func (s *Spinner) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Spinner) Label added in v0.2.12

func (s *Spinner) Label() string

Label returns the current label.

func (*Spinner) SetActive added in v0.2.12

func (s *Spinner) SetActive(active bool)

SetActive starts or stops the animation. When restarted, call Init() again to schedule the next tick.

func (*Spinner) SetFocused added in v0.2.12

func (s *Spinner) SetFocused(f bool)

SetFocused implements Component.

func (*Spinner) SetLabel added in v0.2.12

func (s *Spinner) SetLabel(label string)

SetLabel updates the spinner label.

func (*Spinner) SetSize added in v0.2.12

func (s *Spinner) SetSize(w, h int)

SetSize implements Component.

func (*Spinner) SetTheme added in v0.2.12

func (s *Spinner) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Spinner) Update added in v0.2.12

func (s *Spinner) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Spinner) View added in v0.2.12

func (s *Spinner) View() string

View implements Component.

type SpinnerOpts added in v0.2.12

type SpinnerOpts struct {
	// Label is displayed next to the spinner animation.
	Label string

	// Interval is the time between frame advances. Defaults to 80ms.
	Interval time.Duration
}

SpinnerOpts configures a Spinner.

type Split

type Split struct {
	// Orientation controls whether the split is left/right or top/bottom.
	Orientation Orientation

	// Ratio is the fraction of space given to pane A (0.0–1.0, default 0.5).
	Ratio float64

	// Resizable enables alt+arrow key (and mouse drag) divider movement.
	Resizable bool

	// A is the first child component (left or top).
	A Component

	// B is the second child component (right or bottom).
	B Component
	// contains filtered or unexported fields
}

Split is a Component that divides its space between two child components with a visible divider. When Resizable is true the divider can be moved with alt+arrow keys (or mouse drag when mouse support is enabled).

func NewSplit

func NewSplit(o Orientation, ratio float64, a, b Component) *Split

NewSplit creates a Split with the given orientation, ratio, and children.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	// Create a vertical split with 30/70 ratio.
	left := blit.NewLogViewer()
	right := blit.NewLogViewer()
	split := blit.NewSplit(blit.Vertical, 0.3, left, right)
	_ = split
}

func (*Split) Focused

func (s *Split) Focused() bool

Focused reports whether the Split is focused.

func (*Split) Init

func (s *Split) Init() tea.Cmd

Init initializes both child components and returns their combined commands.

func (*Split) KeyBindings

func (s *Split) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Split.

func (*Split) SetFocused

func (s *Split) SetFocused(f bool)

SetFocused sets the focus state of the Split.

func (*Split) SetSize

func (s *Split) SetSize(w, h int)

SetSize sets the width and height of the Split.

func (*Split) SetTheme

func (s *Split) SetTheme(th Theme)

SetTheme updates the theme used by the Split.

func (*Split) Update

func (s *Split) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Split state.

func (*Split) View

func (s *Split) View() string

View renders the Split as a string.

type StatsCollector added in v0.2.24

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

StatsCollector is a thread-safe structured stats accumulator for API-backed TUIs. It tracks per-source success/failure counts, rate limits, and cache status, and can auto-wire into the DevConsole as a DebugDataProvider.

func NewStatsCollector added in v0.2.24

func NewStatsCollector() *StatsCollector

NewStatsCollector creates a new StatsCollector ready for use.

func (*StatsCollector) Data added in v0.2.24

func (s *StatsCollector) Data() map[string]any

Data implements DebugDataProvider.

func (*StatsCollector) DebugProvider added in v0.2.24

func (s *StatsCollector) DebugProvider() DebugDataProvider

DebugProvider returns this StatsCollector as a DebugDataProvider suitable for registration with the DevConsole.

func (*StatsCollector) Name added in v0.2.24

func (s *StatsCollector) Name() string

Name implements DebugProvider.

func (*StatsCollector) RecordCached added in v0.2.24

func (s *StatsCollector) RecordCached(source string, count int)

RecordCached records that cached data was returned for source.

func (*StatsCollector) RecordFailure added in v0.2.24

func (s *StatsCollector) RecordFailure(source string, _ error)

RecordFailure records a failed fetch from source.

func (*StatsCollector) RecordSuccess added in v0.2.24

func (s *StatsCollector) RecordSuccess(source string, count int)

RecordSuccess records a successful fetch from source with the given item count.

func (*StatsCollector) SetRateLimit added in v0.2.24

func (s *StatsCollector) SetRateLimit(remaining, limit int)

SetRateLimit updates the current rate limit info.

func (*StatsCollector) Snapshot added in v0.2.24

func (s *StatsCollector) Snapshot() StatsSnapshot

Snapshot returns a copy of the current stats.

func (*StatsCollector) View added in v0.2.24

func (s *StatsCollector) View(width, height int, theme Theme) string

View implements DebugProvider.

type StatsSnapshot added in v0.2.24

type StatsSnapshot struct {
	TotalCalls   int
	SuccessCalls int
	FailedCalls  int
	TotalItems   int
	LastActivity time.Time
	Sources      map[string]*SourceHealth
	RateLimit    RateLimitInfo
}

StatsSnapshot holds a point-in-time view of all collected stats.

type StatusBar

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

StatusBar renders a footer bar with left and right aligned sections.

func NewStatusBar

func NewStatusBar(opts StatusBarOpts) *StatusBar

NewStatusBar creates a new StatusBar with the given options.

Left and Right in opts accept either a `func() string` closure or a `*Signal[string]`. See StatusBarOpts for details.

func (*StatusBar) Focused

func (s *StatusBar) Focused() bool

Focused reports whether the StatusBar is focused.

func (*StatusBar) Init

func (s *StatusBar) Init() tea.Cmd

Init initializes the StatusBar component.

func (*StatusBar) KeyBindings

func (s *StatusBar) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the StatusBar.

func (*StatusBar) SetFocused

func (s *StatusBar) SetFocused(f bool)

SetFocused sets the focus state of the StatusBar.

func (*StatusBar) SetSize

func (s *StatusBar) SetSize(w, h int)

SetSize sets the width and height of the StatusBar.

func (*StatusBar) SetTheme

func (s *StatusBar) SetTheme(t Theme)

SetTheme implements the Themed interface.

func (*StatusBar) Update

func (s *StatusBar) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates StatusBar state.

func (*StatusBar) View

func (s *StatusBar) View() string

View renders the StatusBar as a string.

type StatusBarOpts

type StatusBarOpts struct {
	Left  any // func() string, *Signal[string], or StringSource
	Right any
}

StatusBarOpts configures a StatusBar.

Left and Right accept any value that can be converted into a StringSource: a plain `func() string` closure (legacy), a `*Signal[string]` (reactive, v0.10+), or an explicit StringSource. Nil means "empty". The overload is intentional so existing call sites keep working while new code can hand in a signal for per-frame reactivity without plumbing a getter closure that captures the signal.

type Step added in v0.2.12

type Step struct {
	// Title is the step label.
	Title string
	// Description is optional detail text.
	Description string
}

Step is a single stage in a Stepper.

type StepStatus added in v0.2.12

type StepStatus int

StepStatus describes the state of a step.

const (
	// StepPending is a step that has not yet been reached.
	StepPending StepStatus = iota
	// StepActive is the step currently in progress.
	StepActive
	// StepDone is a completed step.
	StepDone
)

type Stepper added in v0.2.12

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

Stepper is a multi-step progress indicator with forward/back navigation. Implements Component and Themed.

func NewStepper added in v0.2.12

func NewStepper(steps []Step, opts StepperOpts) *Stepper

NewStepper creates a Stepper with the given steps and options.

func (*Stepper) Current added in v0.2.12

func (s *Stepper) Current() int

Current returns the index of the active step.

func (*Stepper) Focused added in v0.2.12

func (s *Stepper) Focused() bool

Focused implements Component.

func (*Stepper) Init added in v0.2.12

func (s *Stepper) Init() tea.Cmd

Init implements Component.

func (*Stepper) KeyBindings added in v0.2.12

func (s *Stepper) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Stepper) Next added in v0.2.12

func (s *Stepper) Next()

Next advances to the next step. If already at the last step, calls OnComplete.

func (*Stepper) Prev added in v0.2.12

func (s *Stepper) Prev()

Prev moves back to the previous step.

func (*Stepper) SetCurrent added in v0.2.12

func (s *Stepper) SetCurrent(idx int)

SetCurrent sets the active step index, clamped to valid range.

func (*Stepper) SetFocused added in v0.2.12

func (s *Stepper) SetFocused(f bool)

SetFocused implements Component.

func (*Stepper) SetSize added in v0.2.12

func (s *Stepper) SetSize(w, h int)

SetSize implements Component.

func (*Stepper) SetTheme added in v0.2.12

func (s *Stepper) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Stepper) Status added in v0.2.12

func (s *Stepper) Status(idx int) StepStatus

Status returns the status of a step at the given index.

func (*Stepper) Steps added in v0.2.12

func (s *Stepper) Steps() []Step

Steps returns the current steps.

func (*Stepper) Update added in v0.2.12

func (s *Stepper) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Stepper) View added in v0.2.12

func (s *Stepper) View() string

View implements Component.

type StepperOpts added in v0.2.12

type StepperOpts struct {
	// OnComplete is called when the user advances past the last step.
	OnComplete func()

	// OnChange is called when the current step changes.
	OnChange func(step int)
}

StepperOpts configures a Stepper.

type StringSource

type StringSource interface {
	Value() string
}

StringSource is a read-only source of a string value. Both plain `func() string` closures and `*Signal[string]` satisfy this contract via the adapters below, letting components like StatusBar and ConfigEditor accept either style without a breaking API change.

Use SignalString to wrap a *Signal[string] as a StringSource, or call FuncString for an explicit adapter around a closure (usually unnecessary since raw closures already satisfy the contract via toStringSource).

func FuncString

func FuncString(fn func() string) StringSource

FuncString adapts a func() string closure into a StringSource.

func SignalString

func SignalString(s *Signal[string]) StringSource

SignalString adapts a *Signal[string] into a StringSource so it can be passed anywhere a func() string is accepted.

type Style added in v0.2.24

type Style = lipgloss.Style

Style is an alias for lipgloss.Style, a terminal styling primitive.

type StyleSet

type StyleSet struct {
	Base     lipgloss.Style
	Hover    lipgloss.Style
	Focus    lipgloss.Style
	Disabled lipgloss.Style
	Active   lipgloss.Style
}

StyleSet groups the visual variants of a named component style. Components select the appropriate variant based on their current interaction state.

type Styles added in v0.2.24

type Styles struct {
	// Text variants
	Text       Style // primary text
	TextBold   Style // bold primary text
	Muted      Style // secondary/dimmed text
	Accent     Style // highlighted/active text
	AccentBold Style // bold accent text

	// Semantic
	Positive Style // green: success, online, gains
	Negative Style // red: errors, offline, losses
	Warn     Style // yellow: warnings, caution
	Info     Style // blue/cyan: informational

	// Structural
	Title    Style // bold text, left-padded
	Subtitle Style // muted text, left-padded
	Label    Style // muted label prefix (e.g. "Type:    ")
	Detail   Style // detail content
	Hint     Style // keyboard hints, dimmed

	// Interactive
	Cursor   Style // cursor highlight row (bg)
	Selected Style // selected row (bg)
	Flash    Style // flash background row (bg)
	Border   Style // border foreground
	Header   Style // section header, accent+bold

	// Badge presets (foreground-only)
	BadgePositive Style // positive badge
	BadgeNegative Style // negative badge
	BadgeWarn     Style // warn badge
	BadgeAccent   Style // accent badge
	BadgeMuted    Style // muted badge
}

Styles holds a curated set of pre-built styles derived from a Theme. Consumers should call ThemeStyles(theme) to construct one and replace it on SetTheme.

func ThemeStyles added in v0.2.24

func ThemeStyles(t Theme) Styles

ThemeStyles returns a curated set of commonly-needed styles derived from the theme's semantic color tokens. Call this once on component init and again whenever the theme changes (in SetTheme).

The returned Styles struct covers the most common rendering patterns: text variants, semantic colors, structural styles, interactive states, and badge presets. Consumers can extend it with domain-specific styles using the Extra map on the Theme.

type Subcommand added in v0.2.24

type Subcommand struct {
	Name    string                    // Primary name: "add", "remove"
	Aliases []string                  // Alternatives: ["rm"] for "remove"
	Usage   string                    // Usage text: "add <owner/repo>"
	Run     func(args []string) error // Handler, receives remaining args
}

Subcommand defines a single CLI subcommand.

type TabItem

type TabItem struct {
	// Title is the label shown in the tab bar.
	Title string
	// Glyph is an optional icon prefix shown before the title.
	Glyph string
	// Content is the component rendered when this tab is active.
	Content Component
}

TabItem is a single tab entry with a title, optional glyph, and content component.

type Table

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

Table is an adaptive table component with sorting, filtering, and responsive columns.

func NewTable

func NewTable(columns []Column, rows []Row, opts TableOpts) *Table

NewTable creates a new Table component.

When opts.Virtual is true and opts.RowProvider is non-nil, the table uses a lazy windowed render path: only rows in the visible viewport are fetched from the provider per frame. The rows argument is ignored in virtual mode.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	columns := []blit.Column{
		{Title: "Name", Width: 20, Sortable: true},
		{Title: "Value", Width: 10, Align: blit.Right},
		{Title: "Status", Width: 10},
	}
	rows := []blit.Row{
		{"Alice", "100", "Active"},
		{"Bob", "200", "Inactive"},
		{"Carol", "300", "Active"},
	}
	table := blit.NewTable(columns, rows, blit.TableOpts{
		Sortable:   true,
		Filterable: true,
	})
	_ = table
}

func (*Table) CapturesInput

func (t *Table) CapturesInput() bool

CapturesInput implements InputCapture. Returns true when the table is in filtering mode so that global keybindings (like q-to-quit) are bypassed and keystrokes are routed directly to the filter input.

func (*Table) CursorIndex

func (t *Table) CursorIndex() int

CursorIndex returns the current cursor position.

func (*Table) CursorRow

func (t *Table) CursorRow() Row

CursorRow returns the row at the current cursor position, or nil if empty.

func (*Table) FilterQuery

func (t *Table) FilterQuery() string

FilterQuery returns the active built-in text search query.

func (*Table) Focused

func (t *Table) Focused() bool

Focused reports whether the Table is focused.

func (*Table) Init

func (t *Table) Init() tea.Cmd

Init initializes the Table component.

func (*Table) KeyBindings

func (t *Table) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Table.

func (*Table) RowCount

func (t *Table) RowCount() int

RowCount returns the total number of rows (before filtering). In virtual mode this is the provider's Len.

func (*Table) SetCursor

func (t *Table) SetCursor(idx int)

SetCursor moves the cursor to the given index and scrolls to keep it visible.

func (*Table) SetFilter

func (t *Table) SetFilter(fn FilterFunc)

SetFilter sets a predicate filter function. Pass nil to clear. This works alongside text search — both must pass for a row to be visible. No-op in virtual mode: filter inside the TableRowProvider instead.

func (*Table) SetFocused

func (t *Table) SetFocused(f bool)

SetFocused sets the focus state of the Table.

func (*Table) SetRows

func (t *Table) SetRows(rows []Row)

SetRows replaces the table data and rebuilds the view. In virtual mode this is a no-op; update the underlying TableRowProvider instead.

func (*Table) SetSize

func (t *Table) SetSize(w, h int)

SetSize sets the width and height of the Table.

func (*Table) SetSort

func (t *Table) SetSort(col int, asc bool)

SetSort sets the sort column and direction, then rebuilds the view. Pass col=-1 to clear sorting.

func (*Table) SetTheme

func (t *Table) SetTheme(th Theme)

SetTheme implements the Themed interface.

func (*Table) SortAsc

func (t *Table) SortAsc() bool

SortAsc returns whether the current sort is ascending.

func (*Table) SortCol

func (t *Table) SortCol() int

SortCol returns the current sort column index (-1 if no sort).

func (*Table) Update

func (t *Table) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Table state.

func (*Table) View

func (t *Table) View() string

View renders the Table as a string.

func (*Table) VisibleRowCount

func (t *Table) VisibleRowCount() int

VisibleRowCount returns the number of rows after filtering. In virtual mode filtering is provider-driven, so this matches RowCount.

type TableOpts

type TableOpts struct {
	Sortable       bool                // Enable sort cycling with 's'
	Filterable     bool                // Enable '/' search mode
	CursorStyle    CursorStyle         // How the cursor is rendered
	HeaderStyle    lipgloss.Style      // Override header style (zero value = use theme)
	CellRenderer   CellRenderer        // Custom cell renderer (nil = plain text)
	RowStyler      RowStyler           // Optional full-row style (applied after cell rendering)
	SortFunc       SortFunc            // Custom sort function (nil = lexicographic)
	OnRowClick     RowClickHandler     // Called on Enter or mouse click on a row
	DetailFunc     DetailRenderer      // Renders inline detail bar for cursor row (nil = no detail bar)
	DetailHeight   int                 // Lines reserved for detail bar (default 3 when DetailFunc set)
	OnCursorChange CursorChangeHandler // Called when cursor moves to a different row

	// Virtual enables the virtualized render path. When true, only the visible
	// slice of rows is materialized per frame and RowProvider supplies data
	// lazily. Default false for backwards compatibility.
	Virtual bool
	// RowProvider supplies rows for the virtualized path. Required when
	// Virtual is true. Sorting is disabled in virtual mode; implement sorting
	// inside the provider if needed.
	RowProvider TableRowProvider
	// OnFilterChange fires whenever the built-in filter query changes. In
	// virtual mode the consumer should use this to re-query the provider or
	// swap in a filtered provider; the table does not filter rows itself
	// when Virtual is true.
	OnFilterChange func(query string)
}

TableOpts configures a Table component.

type TableRowProvider

type TableRowProvider interface {
	Len() int
	Rows(offset, limit int) []Row
}

TableRowProvider lazily supplies rows for a virtualized Table. Implementations must be cheap for windowed access — only the visible slice is ever fetched per frame, enabling tables over millions of rows.

Len returns the total logical row count. Rows returns up to limit rows starting at offset; the returned slice length may be shorter at the end. Implementations should not return nil; an empty slice is acceptable.

A TableRowProvider is used only when TableOpts.Virtual is true and TableOpts.RowProvider is non-nil.

type TableRowProviderFunc

type TableRowProviderFunc struct {
	Total int
	Fetch func(offset, limit int) []Row
}

TableRowProviderFunc adapts a plain function into a TableRowProvider for callers that already hold the total row count separately.

func (TableRowProviderFunc) Len

func (f TableRowProviderFunc) Len() int

Len returns the configured total row count.

func (TableRowProviderFunc) Rows

func (f TableRowProviderFunc) Rows(offset, limit int) []Row

Rows delegates to the underlying Fetch function.

type Tabs

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

Tabs is a Component that shows a row or column of named tabs with switchable content panes. Keybinds: tab/shift+tab to cycle, 1-9 to jump, left-click to select.

func NewTabs

func NewTabs(items []TabItem, opts TabsOpts) *Tabs

NewTabs creates a new Tabs component with the given items and options.

func (*Tabs) ActiveIndex

func (t *Tabs) ActiveIndex() int

ActiveIndex returns the currently active tab index.

func (*Tabs) Focused

func (t *Tabs) Focused() bool

Focused implements Component.

func (*Tabs) Init

func (t *Tabs) Init() tea.Cmd

Init implements Component.

func (*Tabs) KeyBindings

func (t *Tabs) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Tabs) OnChange

func (t *Tabs) OnChange(fn func(int))

OnChange registers a callback invoked when the active tab changes.

func (*Tabs) SetActive

func (t *Tabs) SetActive(i int)

SetActive sets the active tab by index (clamped to valid range).

func (*Tabs) SetFocused

func (t *Tabs) SetFocused(focused bool)

SetFocused implements Component. When focused, the active content is also focused.

func (*Tabs) SetSize

func (t *Tabs) SetSize(w, h int)

SetSize implements Component.

func (*Tabs) SetTheme

func (t *Tabs) SetTheme(th Theme)

SetTheme implements Themed.

func (*Tabs) Update

func (t *Tabs) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Tabs) View

func (t *Tabs) View() string

View implements Component.

type TabsOpts

type TabsOpts struct {
	// Orientation is Horizontal (default) or Vertical.
	Orientation Orientation
	// OnChange is called whenever the active tab changes.
	OnChange func(int)
}

TabsOpts configures a Tabs component.

type TextField

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

TextField is a single-line text input field.

func NewTextField

func NewTextField(id, label string) *TextField

NewTextField creates a new single-line text field.

func (*TextField) FieldID

func (f *TextField) FieldID() string

func (*TextField) Init

func (f *TextField) Init() tea.Cmd

Init initializes the TextField component.

func (*TextField) Label

func (f *TextField) Label() string

func (*TextField) SetFocused

func (f *TextField) SetFocused(focused bool)

SetFocused sets the focus state of the TextField.

func (*TextField) SetValue

func (f *TextField) SetValue(v string)

SetValue sets the current value of the TextField.

func (*TextField) Update

func (f *TextField) Update(msg tea.Msg) tea.Cmd

Update handles incoming messages and updates TextField state.

func (*TextField) Validate

func (f *TextField) Validate() error

Validate checks the current value against the field's validation rules.

func (*TextField) Value

func (f *TextField) Value() string

Value returns the current value of the TextField.

func (*TextField) View

func (f *TextField) View(focused bool, theme Theme, width int) string

View renders the TextField as a string.

func (*TextField) WithDefault

func (f *TextField) WithDefault(v string) *TextField

WithDefault sets the initial value.

func (*TextField) WithHint

func (f *TextField) WithHint(hint string) *TextField

WithHint sets the hint text.

func (*TextField) WithPlaceholder

func (f *TextField) WithPlaceholder(p string) *TextField

WithPlaceholder sets the placeholder text.

func (*TextField) WithRequired

func (f *TextField) WithRequired() *TextField

WithRequired marks the field as required.

func (*TextField) WithValidator

func (f *TextField) WithValidator(v Validator) *TextField

WithValidator attaches a validator function.

type Theme

type Theme struct {
	Positive    lipgloss.Color            // Green: gains, success, online
	Negative    lipgloss.Color            // Red: losses, errors, offline
	Accent      lipgloss.Color            // Highlights, active elements
	Muted       lipgloss.Color            // Dimmed text, secondary info
	Text        lipgloss.Color            // Primary text
	TextInverse lipgloss.Color            // Text on colored backgrounds
	Cursor      lipgloss.Color            // Cursor/selection highlight
	Border      lipgloss.Color            // Borders, separators
	Flash       lipgloss.Color            // Temporary notification background
	Warn        lipgloss.Color            // Warnings, caution states (yellow/amber)
	Extra       map[string]lipgloss.Color // App-specific color tokens
	Glyphs      *Glyphs                   // Optional glyph override; nil uses DefaultGlyphs
	Borders     *BorderSet                // Optional border override; nil uses DefaultBorders
	// contains filtered or unexported fields
}

Theme defines semantic color tokens for consistent styling across components. Components reference these tokens instead of raw colors.

func CatppuccinMochaTheme

func CatppuccinMochaTheme() Theme

CatppuccinMochaTheme returns the Catppuccin Mocha colour theme.

func DefaultTheme

func DefaultTheme() Theme

DefaultTheme returns a dark theme suitable for most terminal backgrounds.

Example
package main

import (
	"fmt"

	blit "github.com/blitui/blit"
)

func main() {
	theme := blit.DefaultTheme()
	fmt.Println("Theme accent:", theme.Accent)
	_ = theme
}

func DraculaTheme

func DraculaTheme() Theme

DraculaTheme returns the Dracula colour theme.

func EverforestTheme added in v0.2.22

func EverforestTheme() Theme

EverforestTheme returns the Everforest Dark colour theme.

func FromAlacritty

func FromAlacritty(data []byte) (Theme, error)

FromAlacritty imports a Theme from an Alacritty TOML config file.

func FromGogh

func FromGogh(data []byte) (Theme, error)

FromGogh imports a Theme from a Gogh terminal theme JSON file.

func FromIterm2

func FromIterm2(data []byte) (Theme, error)

FromIterm2 imports a Theme from an iTerm2 color preset XML (.itermcolors) file.

func GruvboxDarkTheme

func GruvboxDarkTheme() Theme

GruvboxDarkTheme returns the Gruvbox Dark colour theme.

func KanagawaTheme

func KanagawaTheme() Theme

KanagawaTheme returns the Kanagawa colour theme.

func LightTheme

func LightTheme() Theme

LightTheme returns a light theme for light terminal backgrounds.

func NightfoxTheme added in v0.2.22

func NightfoxTheme() Theme

NightfoxTheme returns the Nightfox colour theme.

func NordTheme

func NordTheme() Theme

NordTheme returns the Nord colour theme.

func OneDarkTheme

func OneDarkTheme() Theme

OneDarkTheme returns the One Dark colour theme.

func ParseThemeYAML

func ParseThemeYAML(data []byte) (Theme, error)

ParseThemeYAML reads a YAML-encoded theme definition and returns a Theme. Missing keys fall back to DefaultTheme values. Extra keys are placed in Theme.Extra.

func RosePineTheme

func RosePineTheme() Theme

RosePineTheme returns the Rose Pine colour theme.

func SolarizedDarkTheme added in v0.2.22

func SolarizedDarkTheme() Theme

SolarizedDarkTheme returns the Solarized Dark colour theme.

func ThemeFromMap

func ThemeFromMap(m map[string]string) Theme

ThemeFromMap creates a Theme from a map of color names to hex values. Missing keys fall back to DefaultTheme values. Keys not matching a built-in token are placed in the Extra map.

func TokyoNightTheme

func TokyoNightTheme() Theme

TokyoNightTheme returns the Tokyo Night colour theme.

func (Theme) Color

func (t Theme) Color(key string, fallback lipgloss.Color) lipgloss.Color

Color returns an app-specific color from Extra by key, falling back to the provided default if the key does not exist.

func (*Theme) RegisterStyle

func (t *Theme) RegisterStyle(name string, s StyleSet)

RegisterStyle stores a custom StyleSet override for name on this Theme instance. Subsequent calls to Style(name) will return this override.

func (Theme) SemanticColor added in v0.2.24

func (t Theme) SemanticColor(name string, fallback Color) Color

SemanticColor resolves a well-known semantic color name via the Theme's Extra map, falling back to a sensible default from the base tokens when the name is not present. This lets consumers define domain-specific colors (like "info", "create", "local") in Theme.Extra and have them resolve automatically, while still working with themes that don't define them.

Well-known names and their defaults:

info    → Accent
create  → Positive
delete  → Negative
review  → Cursor
comment → Muted
issue   → Warn
release → Flash
local   → Accent

func (*Theme) Style

func (t *Theme) Style(name string) (StyleSet, bool)

Style returns the StyleSet registered under name. If no override has been registered the built-in default derived from the theme's color tokens is returned. The second return value is false only when name is completely unknown (neither registered nor a built-in).

type ThemeHotReload

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

ThemeHotReload watches a YAML theme file and pushes updates to an App via the Bubble Tea program sender. It debounces rapid filesystem events by 200 ms to avoid flicker on editors that save in multiple steps. Most callers should use WithThemeHotReload; this type is exposed for testing.

func NewThemeHotReload

func NewThemeHotReload(path string, sender func(msg interface{})) (*ThemeHotReload, error)

NewThemeHotReload starts a filesystem watcher on path and calls sender with ThemeHotReloadMsg or ThemeHotReloadErrMsg on every change. Call Stop when done. This is exported so tests and custom runners can use it directly; most callers should use WithThemeHotReload instead.

func (*ThemeHotReload) Stop

func (hr *ThemeHotReload) Stop()

Stop shuts down the watcher and waits for the goroutine to exit.

type ThemeHotReloadErrMsg

type ThemeHotReloadErrMsg struct {
	Err error
}

ThemeHotReloadErrMsg is sent when the YAML file cannot be re-parsed. The App shows it as an error toast so the user sees it inline.

type ThemeHotReloadMsg

type ThemeHotReloadMsg struct {
	Theme Theme
}

ThemeHotReloadMsg is a Bubble Tea message used to deliver a newly parsed theme to the App on the UI goroutine after a successful file reload.

type Themed

type Themed interface {
	SetTheme(Theme)
}

Themed is an optional interface for components that accept a theme. The App automatically calls SetTheme on any Component or Overlay that implements this interface. Built-in components (Table, StatusBar, Help, ConfigEditor) all implement Themed. Custom components should too if they need access to the theme's semantic color tokens.

type TickMsg

type TickMsg struct {
	Time time.Time
}

TickMsg is sent to all components at the configured tick interval. Use it for animations, countdowns, polling, and flash effects.

type Timeline added in v0.2.12

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

Timeline is a vertical or horizontal sequence of events with connectors. Implements Component and Themed.

func NewTimeline added in v0.2.12

func NewTimeline(events []TimelineEvent, opts TimelineOpts) *Timeline

NewTimeline creates a Timeline with the given events and options.

func (*Timeline) CursorIndex added in v0.2.12

func (t *Timeline) CursorIndex() int

CursorIndex returns the currently highlighted event index.

func (*Timeline) Events added in v0.2.12

func (t *Timeline) Events() []TimelineEvent

Events returns the current events.

func (*Timeline) Focused added in v0.2.12

func (t *Timeline) Focused() bool

Focused implements Component.

func (*Timeline) Init added in v0.2.12

func (t *Timeline) Init() tea.Cmd

Init implements Component.

func (*Timeline) KeyBindings added in v0.2.12

func (t *Timeline) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Timeline) SetEvents added in v0.2.12

func (t *Timeline) SetEvents(events []TimelineEvent)

SetEvents replaces the events and resets the cursor.

func (*Timeline) SetFocused added in v0.2.12

func (t *Timeline) SetFocused(f bool)

SetFocused implements Component.

func (*Timeline) SetSize added in v0.2.12

func (t *Timeline) SetSize(w, h int)

SetSize implements Component.

func (*Timeline) SetTheme added in v0.2.12

func (t *Timeline) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Timeline) Update added in v0.2.12

func (t *Timeline) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Timeline) View added in v0.2.12

func (t *Timeline) View() string

View implements Component.

type TimelineEvent added in v0.2.12

type TimelineEvent struct {
	// Time is the display label for the timestamp (e.g. "2024-01-15", "3:00 PM").
	Time string
	// Title is the event headline.
	Title string
	// Description is optional detail text.
	Description string
	// Status controls the icon/color: "done", "active", "pending", or custom.
	Status string
}

TimelineEvent is a single entry in a Timeline.

type TimelineOpts added in v0.2.12

type TimelineOpts struct {
	// OnSelect is called when enter is pressed on an event.
	OnSelect func(event TimelineEvent, index int)

	// Horizontal renders events left-to-right instead of top-to-bottom.
	Horizontal bool
}

TimelineOpts configures a Timeline.

type ToastAction

type ToastAction struct {
	Label   string
	Handler func()
}

ToastAction is a labelled action button on a toast.

type ToastManagerOpts

type ToastManagerOpts struct {
	MaxVisible   int
	AnimDuration time.Duration
}

ToastManagerOpts configures the ToastManager.

type ToastMsg

type ToastMsg struct {
	Severity ToastSeverity
	Title    string
	Body     string
	Duration time.Duration
	Actions  []ToastAction
}

ToastMsg triggers a toast notification via the App ToastManager.

type ToastSeverity

type ToastSeverity int

ToastSeverity classifies a toast notification.

const (
	SeverityInfo ToastSeverity = iota
	SeveritySuccess
	SeverityWarn
	SeverityError
)

type Tooltip added in v0.2.12

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

Tooltip is a floating text hint that composites over background content. Implements FloatingOverlay and Themed.

func NewTooltip added in v0.2.12

func NewTooltip(opts TooltipOpts) *Tooltip

NewTooltip creates a Tooltip with the given options.

func (*Tooltip) Close added in v0.2.12

func (t *Tooltip) Close()

Close implements Overlay.

func (*Tooltip) FloatView added in v0.2.12

func (t *Tooltip) FloatView(background string) string

FloatView implements FloatingOverlay. Composites the tooltip over background.

func (*Tooltip) Focused added in v0.2.12

func (t *Tooltip) Focused() bool

Focused implements Component.

func (*Tooltip) Init added in v0.2.12

func (t *Tooltip) Init() tea.Cmd

Init implements Component.

func (*Tooltip) Inline added in v0.2.12

func (t *Tooltip) Inline() bool

Inline returns false — tooltip is a floating overlay.

func (*Tooltip) IsActive added in v0.2.12

func (t *Tooltip) IsActive() bool

IsActive implements Overlay.

func (*Tooltip) KeyBindings added in v0.2.12

func (t *Tooltip) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Tooltip) SetAnchor added in v0.2.12

func (t *Tooltip) SetAnchor(x, y int)

SetAnchor sets the position where the tooltip should appear.

func (*Tooltip) SetFocused added in v0.2.12

func (t *Tooltip) SetFocused(f bool)

SetFocused implements Component.

func (*Tooltip) SetSize added in v0.2.12

func (t *Tooltip) SetSize(w, h int)

SetSize implements Component.

func (*Tooltip) SetText added in v0.2.12

func (t *Tooltip) SetText(text string)

SetText updates the tooltip content.

func (*Tooltip) SetTheme added in v0.2.12

func (t *Tooltip) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Tooltip) Show added in v0.2.12

func (t *Tooltip) Show()

Show activates the tooltip.

func (*Tooltip) Text added in v0.2.12

func (t *Tooltip) Text() string

Text returns the current tooltip text.

func (*Tooltip) Update added in v0.2.12

func (t *Tooltip) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Tooltip) View added in v0.2.12

func (t *Tooltip) View() string

View implements Component. Returns the tooltip box for standalone use.

type TooltipOpts added in v0.2.12

type TooltipOpts struct {
	// Text is the tooltip content.
	Text string

	// MaxWidth limits the tooltip width. Defaults to 40.
	MaxWidth int
}

TooltipOpts configures a Tooltip.

type Tree

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

Tree is a recursive Component that renders a tree of Nodes with indent connector glyphs pulled from the theme glyph pack.

func NewTree

func NewTree(roots []*Node, opts TreeOpts) *Tree

NewTree creates a Tree with the given root nodes and options.

Example
package main

import (
	blit "github.com/blitui/blit"
)

func main() {
	nodes := []*blit.Node{
		{Title: "src", Children: []*blit.Node{
			{Title: "main.go"},
			{Title: "app.go"},
		}},
		{Title: "go.mod"},
		{Title: "README.md"},
	}
	tree := blit.NewTree(nodes, blit.TreeOpts{})
	_ = tree
}

func (*Tree) ClearFilter added in v0.2.12

func (t *Tree) ClearFilter()

ClearFilter removes the active filter and rebuilds the flat view.

func (*Tree) CursorNode

func (t *Tree) CursorNode() *Node

CursorNode returns the currently highlighted node, or nil if the tree is empty.

func (*Tree) DeselectAll added in v0.2.12

func (t *Tree) DeselectAll()

DeselectAll clears the Selected flag on every node.

func (*Tree) Filter added in v0.2.12

func (t *Tree) Filter() string

Filter returns the current filter query, or "" if no filter is active.

func (*Tree) Focused

func (t *Tree) Focused() bool

Focused implements Component.

func (*Tree) Init

func (t *Tree) Init() tea.Cmd

Init implements Component.

func (*Tree) KeyBindings

func (t *Tree) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*Tree) Roots

func (t *Tree) Roots() []*Node

Roots returns the root nodes.

func (*Tree) SelectAll added in v0.2.12

func (t *Tree) SelectAll()

SelectAll marks every node as Selected. Only meaningful in SelectionMulti mode.

func (*Tree) SelectedNodes added in v0.2.12

func (t *Tree) SelectedNodes() []*Node

SelectedNodes returns all nodes that have Selected == true, in tree order.

func (*Tree) SetFilter added in v0.2.12

func (t *Tree) SetFilter(query string)

SetFilter applies a search filter. Only nodes whose Title contains the query (case-insensitive) are shown, along with their ancestors. An empty query clears the filter.

func (*Tree) SetFocused

func (t *Tree) SetFocused(f bool)

SetFocused implements Component.

func (*Tree) SetRoots

func (t *Tree) SetRoots(roots []*Node)

SetRoots replaces the root nodes and rebuilds the flat view.

func (*Tree) SetSize

func (t *Tree) SetSize(w, h int)

SetSize implements Component.

func (*Tree) SetTheme

func (t *Tree) SetTheme(theme Theme)

SetTheme implements Themed.

func (*Tree) Update

func (t *Tree) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*Tree) View

func (t *Tree) View() string

View implements Component.

type TreeOpts

type TreeOpts struct {
	// OnSelect is called when the user presses Enter on a node. Optional.
	OnSelect func(node *Node)

	// OnToggle is called when the user expands or collapses a node. Optional.
	OnToggle func(node *Node)

	// OnContext is called when the user triggers the context action on a node
	// (default key: "c"). Optional.
	OnContext func(node *Node)

	// LoadChildren, if non-nil, is called the first time a node with nil
	// Children is expanded. It should return the children to attach.
	// This enables lazy loading of deep or dynamic trees.
	LoadChildren func(node *Node) []*Node

	// Selection sets the selection mode. Default is SelectionNone.
	Selection SelectionMode

	// RenderNode, if non-nil, overrides the default node label rendering.
	// The returned string replaces the glyph+title portion of each line.
	RenderNode NodeRenderFunc
}

TreeOpts configures Tree behaviour.

type Tween

type Tween struct {
	Duration time.Duration
	// contains filtered or unexported fields
}

Tween tracks animation progress over a fixed duration. When BLIT_NO_ANIM=1, Start is a no-op and Progress always returns 1.

func (*Tween) Done

func (tw *Tween) Done() bool

Done reports whether the tween has completed.

func (*Tween) Progress

func (tw *Tween) Progress(now time.Time) float64

Progress returns t in [0,1] at the given clock time. Returns 1 when done.

func (*Tween) Running

func (tw *Tween) Running() bool

Running reports whether the tween is currently active.

func (*Tween) Start

func (tw *Tween) Start(now time.Time)

Start begins the tween at the given clock time.

type Unsubscribe

type Unsubscribe func()

Unsubscribe removes a previously registered Subscribe callback.

type UpdateAction added in v0.2.24

type UpdateAction int

UpdateAction represents an action the update system requests the caller to perform. Because a library must never call os.Exit, the update system returns these actions and Run() carries them out in the main function context.

const (
	// UpdateActionNone means no action is required; the app starts normally.
	UpdateActionNone UpdateAction = iota
	// UpdateActionRestart means the binary was replaced and the process
	// should exit so the user can relaunch.
	UpdateActionRestart
	// UpdateActionAbort means the update gate or blocking prompt chose not
	// to update and the app should exit without starting the TUI.
	UpdateActionAbort
)

type UpdateCache

type UpdateCache struct {
	CheckedAt     time.Time `json:"checked_at"`
	LatestVersion string    `json:"latest_version"`
	ReleaseURL    string    `json:"release_url"`
	ReleaseNotes  string    `json:"release_notes"`
}

UpdateCache is the cached result of an update check.

func ReadCache

func ReadCache(path string) (UpdateCache, error)

ReadCache reads the cached update check from disk.

func (UpdateCache) IsFresh

func (c UpdateCache) IsFresh(ttl time.Duration) bool

IsFresh reports whether the cache is still within the TTL.

type UpdateConfig

type UpdateConfig struct {
	Owner      string        // GitHub repo owner
	Repo       string        // GitHub repo name
	BinaryName string        // Binary name in release assets (e.g. "cryptstream")
	Version    string        // Current version (set via ldflags; "dev" or "" skips check)
	Mode       UpdateMode    // UpdateNotify, UpdateBlocking, UpdateSilent, UpdateForced, UpdateDryRun
	CacheTTL   time.Duration // How long to cache the check result (default: 1h)
	CacheDir   string        // Override cache directory (default: os.UserConfigDir()/<BinaryName>)

	// Disabled short-circuits every update call (same effect as the
	// BLIT_UPDATE_DISABLE environment variable). Useful in tests and CI.
	Disabled bool

	// Channel selects which releases to consider. "" or "stable" uses
	// /releases/latest (GitHub's latest stable marker). "beta" and
	// "prerelease" fetch /releases and filter by tag suffix so consumers
	// can opt into pre-release tracks.
	Channel string

	// OnProgress is called during binary asset download with bytes received and total bytes.
	// If nil, no progress reporting occurs.
	OnProgress ProgressFunc

	// OnBeforeUpdate is called immediately before SelfUpdate performs any
	// write. Returning a non-nil error aborts the update with that error.
	// Useful for pre-flight checks (disk space, feature flags, user confirm).
	OnBeforeUpdate func() error

	// OnAfterUpdate is called after a successful binary replace, before
	// the process exits. Receives the old and new version strings.
	OnAfterUpdate func(oldVersion, newVersion string)

	// OnUpdateError is called when any update step fails. The error is
	// still returned from SelfUpdate; this hook just lets consumers
	// observe/telemetry the failure in-process.
	OnUpdateError func(err error)

	// CosignPublicKey is an optional ed25519 public key used to verify the
	// detached signature (<asset>.sig) before replacing the binary. The key
	// may be PEM-encoded ("-----BEGIN PUBLIC KEY-----") or bare base64.
	// When empty, signature verification is skipped.
	CosignPublicKey string

	// APIBaseURL overrides the GitHub API URL. Leave empty for production.
	// Exported for testing; not intended for consumer use.
	APIBaseURL string

	// EnableDeltaUpdates opts in to the bsdiff-based delta update path.
	// When true, SelfUpdate first looks for a patch asset matching the
	// current version and applies it locally, falling back to a full
	// archive download on any failure. Default is false.
	EnableDeltaUpdates bool
}

UpdateConfig configures the auto-update system.

type UpdateMode

type UpdateMode int

UpdateMode controls how the update prompt behaves.

const (
	// UpdateNotify shows a non-blocking notification in the TUI after startup.
	UpdateNotify UpdateMode = iota
	// UpdateBlocking prompts the user in stdout before the TUI starts.
	UpdateBlocking
	// UpdateSilent downloads and replaces the binary in the background.
	// The app continues running; a "restart required" banner is shown on the
	// next launch via the update cache.
	UpdateSilent
	// UpdateForced shows a full-screen gate that blocks app launch until the
	// user either updates or quits. Also triggered implicitly when a release
	// sets a minimum_version higher than the current version.
	UpdateForced
	// UpdateDryRun logs every action the updater would take via log.Printf
	// but performs no writes. Useful for debugging without risk.
	UpdateDryRun
)

func (UpdateMode) String

func (m UpdateMode) String() string

String returns the mode name for logging.

type UpdateProgress

type UpdateProgress struct {
	Binary     string
	Version    string
	Total      int64
	Downloaded int64
	StartedAt  time.Time
	Width      int
	Done       bool
	Err        error
	// contains filtered or unexported fields
}

UpdateProgress is a reusable tea.Model component that renders a download progress bar for a self-update. Consumers drive it by sending UpdateProgressMsg updates; the model handles its own render.

Typical wiring inside UpdateBlocking mode:

p := NewUpdateProgress("tool", "v2.0.0", totalBytes)
// ... each time OnProgress fires:
prog.Update(UpdateProgressMsg{Downloaded: n})
fmt.Println(prog.View())

func NewUpdateProgress

func NewUpdateProgress(binary, version string, total int64) *UpdateProgress

NewUpdateProgress constructs a progress component for binary/version with an expected total byte count. If total is zero or unknown, the bar degrades gracefully to an indeterminate spinner-like view.

func (*UpdateProgress) ETA

func (p *UpdateProgress) ETA() time.Duration

ETA returns the estimated time remaining based on current speed. Returns 0 if speed is 0 or total is unknown.

func (*UpdateProgress) Init

func (p *UpdateProgress) Init() tea.Cmd

Init implements tea.Model.

func (*UpdateProgress) Percent

func (p *UpdateProgress) Percent() float64

Percent returns the download completion ratio in [0, 1]. If total is unknown, returns 0.

func (*UpdateProgress) Speed

func (p *UpdateProgress) Speed() float64

Speed returns the average bytes/sec since StartedAt.

func (*UpdateProgress) Update

func (p *UpdateProgress) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update handles UpdateProgressMsg and animTickMsg events.

func (*UpdateProgress) View

func (p *UpdateProgress) View() string

View implements tea.Model. Renders a styled progress bar with bytes, percent, speed, and ETA.

type UpdateProgressMsg

type UpdateProgressMsg struct {
	Downloaded int64
	Done       bool
	Err        error
}

UpdateProgressMsg carries incremental progress updates into the model.

type UpdateResult

type UpdateResult struct {
	Available      bool
	CurrentVersion string
	LatestVersion  string
	ReleaseURL     string
	ReleaseNotes   string
	InstallMethod  InstallMethod
	// Required is true when the release advertises a minimum_version marker
	// that is newer than the current version. Consumers in UpdateForced
	// mode MUST block until updated or quit when Required is true.
	Required bool
}

UpdateResult holds the result of an update check.

func CheckForUpdate

func CheckForUpdate(cfg UpdateConfig) (*UpdateResult, error)

CheckForUpdate checks GitHub Releases for a newer version. If the version is "dev" or empty, it attempts to read the module version from Go's embedded build info (set by go install). Returns a zero-value UpdateResult (Available=false) if no version can be determined. Network/API errors return a zero-value result with no error (fail-silent).

type VBox

type VBox struct {
	Gap     int         // Gap in rows between children.
	Align   FlexAlign   // Cross-axis (horizontal) alignment.
	Justify FlexJustify // Main-axis (vertical) distribution.
	Items   []Component // Children — may be plain Component, Sized, or Flex.
	// contains filtered or unexported fields
}

VBox lays out children vertically (top → bottom). It implements the full Component interface and can be nested.

func (*VBox) Focused

func (v *VBox) Focused() bool

Focused implements Component.

func (*VBox) Init

func (v *VBox) Init() tea.Cmd

Init implements Component.

func (*VBox) KeyBindings

func (v *VBox) KeyBindings() []KeyBind

KeyBindings implements Component.

func (*VBox) SetFocused

func (v *VBox) SetFocused(focused bool)

SetFocused implements Component.

func (*VBox) SetSize

func (v *VBox) SetSize(width, height int)

SetSize implements Component.

func (*VBox) SetTheme added in v0.1.3

func (v *VBox) SetTheme(th Theme)

SetTheme implements Themed by propagating to all children.

func (*VBox) Update

func (v *VBox) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update implements Component.

func (*VBox) View

func (v *VBox) View() string

View implements Component.

type Validator

type Validator func(value string) error

Validator is a function that validates a field value. Return nil if valid, or an error describing the problem.

func ComposeValidators

func ComposeValidators(validators ...Validator) Validator

ComposeValidators returns a Validator that runs all validators in order. The first error encountered is returned.

func EmailValidator

func EmailValidator() Validator

EmailValidator returns a Validator that checks for a basic email format.

func MaxLength

func MaxLength(n int) Validator

MaxLength returns a Validator that fails if the value is longer than n characters.

func MinLength

func MinLength(n int) Validator

MinLength returns a Validator that fails if the value is shorter than n characters.

func RegexValidator

func RegexValidator(pattern, message string) Validator

RegexValidator returns a Validator that checks the value against a pattern.

func Required

func Required() Validator

Required returns a Validator that fails if the value is empty.

func URLValidator

func URLValidator() Validator

URLValidator returns a Validator that checks for http/https URL format.

type Version

type Version struct {
	Major int
	Minor int
	Patch int
}

Version represents a parsed semantic version.

func ParseMinimumVersion

func ParseMinimumVersion(releaseBody string) (Version, bool)

ParseMinimumVersion extracts a "minimum_version: vX.Y.Z" marker from a release body (typically Markdown). Returns the parsed Version and true on match, zero Version and false otherwise. Supports both "minimum_version" and "minimum-version", and the marker is case-insensitive.

func ParseVersion

func ParseVersion(s string) (Version, error)

ParseVersion parses a semver string like "v1.2.3" or "1.2.3". Pre-release (-rc.1) and build metadata (+dirty, +incompatible) suffixes are stripped.

func (Version) NewerThan

func (v Version) NewerThan(other Version) bool

NewerThan reports whether v is a newer version than other.

func (Version) String

func (v Version) String() string

String returns the version as "vMAJOR.MINOR.PATCH".

type Viewport

type Viewport struct {
	// Content is the full text to display (may contain newlines).
	Content string
	// contains filtered or unexported fields
}

Viewport is a themed scroll container for arbitrary string content. It renders a right-side scrollbar (track + thumb) pulled from the theme. Keybinds: j/k, pgup/pgdn, home/end, ctrl+u/ctrl+d, mouse wheel.

func NewViewport

func NewViewport() *Viewport

NewViewport creates a new Viewport with no content.

func (*Viewport) AtBottom

func (v *Viewport) AtBottom() bool

AtBottom returns true when scrolled to the bottom.

func (*Viewport) AtTop

func (v *Viewport) AtTop() bool

AtTop returns true when scrolled to the top.

func (*Viewport) Focused

func (v *Viewport) Focused() bool

Focused reports whether the Viewport is focused.

func (*Viewport) GotoBottom

func (v *Viewport) GotoBottom()

GotoBottom scrolls to the bottom.

func (*Viewport) GotoTop

func (v *Viewport) GotoTop()

GotoTop scrolls to the top.

func (*Viewport) HandleKey

func (v *Viewport) HandleKey(msg tea.KeyMsg) tea.Cmd

HandleKey processes navigation keys. Returns Consumed() if handled.

func (*Viewport) Init

func (v *Viewport) Init() tea.Cmd

Init initializes the Viewport component. It returns nil.

func (*Viewport) KeyBindings

func (v *Viewport) KeyBindings() []KeyBind

KeyBindings returns the key bindings for the Viewport.

func (*Viewport) ScrollBy

func (v *Viewport) ScrollBy(delta int)

ScrollBy moves the viewport by delta lines (positive = down, negative = up).

func (*Viewport) SetContent

func (v *Viewport) SetContent(content string)

SetContent sets the text content and resets the scroll position.

func (*Viewport) SetFocused

func (v *Viewport) SetFocused(f bool)

SetFocused sets the focus state of the Viewport.

func (*Viewport) SetSize

func (v *Viewport) SetSize(w, h int)

SetSize sets the width and height of the Viewport.

func (*Viewport) SetTheme

func (v *Viewport) SetTheme(th Theme)

SetTheme updates the theme used by the Viewport.

func (*Viewport) Update

func (v *Viewport) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)

Update handles incoming messages and updates Viewport state.

func (*Viewport) View

func (v *Viewport) View() string

View renders the Viewport as a string.

func (*Viewport) YOffset

func (v *Viewport) YOffset() int

YOffset returns the current scroll offset.

type ViewportGlyphs

type ViewportGlyphs struct {
	Track string
	Thumb string
}

ViewportGlyphs holds the scrollbar track and thumb symbols for Viewport. Falls back to defaults when nil.

type WindowSizeMsg added in v0.2.24

type WindowSizeMsg = tea.WindowSizeMsg

WindowSizeMsg is an alias for tea.WindowSizeMsg, sent on terminal resize.

Directories

Path Synopsis
Package btest accessibility helpers.
Package btest accessibility helpers.
Package charts provides terminal chart components for blit.
Package charts provides terminal chart components for blit.
Package cli provides interactive CLI primitives for tools that need more than plain stdout but less than a full Bubble Tea TUI.
Package cli provides interactive CLI primitives for tools that need more than plain stdout but less than a full Bubble Tea TUI.
cmd
blit command
Coverage overlay for btest.
Coverage overlay for btest.
sess2tape command
Command sess2tape converts a .tuisess file (produced by btest.SessionRecorder) into a VHS .tape script that can be fed to `vhs` to produce a GIF.
Command sess2tape converts a .tuisess file (produced by btest.SessionRecorder) into a VHS .tape script that can be fed to `vhs` to produce a GIF.
examples
bigtable command
Package main demonstrates the virtualized Table over 1,000,000 rows.
Package main demonstrates the virtualized Table over 1,000,000 rows.
charts command
Package main demonstrates all blit chart types in a single dashboard.
Package main demonstrates all blit chart types in a single dashboard.
cli-demo command
Package main demonstrates blit's cli/ package — interactive CLI primitives that work without a full-screen TUI.
Package main demonstrates blit's cli/ package — interactive CLI primitives that work without a full-screen TUI.
dashboard command
Package main demonstrates a full-featured blit dashboard.
Package main demonstrates a full-featured blit dashboard.
filetree command
flex command
Package main demonstrates HBox/VBox flex layout with mixed fixed and flex children.
Package main demonstrates HBox/VBox flex layout with mixed fixed and flex children.
form command
Package main demonstrates the blit Form component with validators and wizard mode.
Package main demonstrates the blit Form component with validators and wizard mode.
logview command
Package main demonstrates the LogViewer component streaming fake logs at 50 Hz.
Package main demonstrates the LogViewer component streaming fake logs at 50 Hz.
minimal command
Package main demonstrates the simplest possible blit application.
Package main demonstrates the simplest possible blit application.
monitor command
Package main demonstrates a full-featured blit service monitor dashboard.
Package main demonstrates a full-featured blit service monitor dashboard.
picker command
Package main demonstrates the blit Picker as a file browser.
Package main demonstrates the blit Picker as a file browser.
splitpane command
Package main demonstrates the Split, Viewport, and Breadcrumbs components.
Package main demonstrates the Split, Viewport, and Breadcrumbs components.
ssh-serve command
Package main demonstrates hosting a blit dashboard over SSH via Charm Wish.
Package main demonstrates hosting a blit dashboard over SSH via Charm Wish.
tabs command
Package main demonstrates the blit Tabs component.
Package main demonstrates the blit Tabs component.
theme-dev command
Package main demonstrates blit's theme hot-reload feature.
Package main demonstrates blit's theme hot-reload feature.
internal
fuzzy
Package fuzzy implements an fzf-inspired fuzzy scorer for command pickers.
Package fuzzy implements an fzf-inspired fuzzy scorer for command pickers.
scaffold
Package scaffold generates blit boilerplate for a given package path.
Package scaffold generates blit boilerplate for a given package path.
tape
Package tape converts a btest.Session into a VHS .tape script.
Package tape converts a btest.Session into a VHS .tape script.
Package updatetest provides HTTP mocks and fake binaries for testing code that uses blit's auto-update system.
Package updatetest provides HTTP mocks and fake binaries for testing code that uses blit's auto-update system.

Jump to

Keyboard shortcuts

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