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.
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 ¶
- Constants
- func ApplyDeltaPatch(exePath string, patch []byte) ([]byte, error)
- func Badge(text string, fg lipgloss.Color, bold bool) string
- func CleanupOldBinary()
- func ClearSkippedVersions(cfg UpdateConfig) error
- func Consumed() tea.Cmd
- func Contrast(bg, fg lipgloss.Color) float64
- func CopyToClipboardCmd(text string) tea.Cmd
- func CopyToClipboardWithNotify(text string) tea.Cmd
- func DefaultConfigPath(appName string) (string, error)
- func DevConsoleToggleCmd() tea.Cmd
- func Divider(width int, theme Theme) string
- func EaseInCubic(t float64) float64
- func EaseInOut(t float64) float64
- func EaseOutCubic(t float64) float64
- func EaseOutExpo(t float64) float64
- func EnsureConfigDir(appName string) (string, error)
- func ExtractBinary(archive []byte, binaryName, format string) ([]byte, error)
- func Hyperlink(url, text string) string
- func Interpolate[T any](from, to T, t float64, e Ease) T
- func IsRateLimited(err error) bool
- func IsVersionSkipped(cfg UpdateConfig, v string) bool
- func Linear(t float64) float64
- func LoadYAML(path string, dst any) error
- func LogAppendCmd(line LogLine) tea.Cmd
- func Markdown(md string, theme Theme) string
- func NotifyCmd(text string, duration time.Duration) tea.Cmd
- func OSC8Link(url, text string) string
- func OpenURL(url string)
- func Presets() map[string]Theme
- func Register(name string, t Theme)
- func RelativeTime(t time.Time, now time.Time) string
- func RenderGradient(text string, g Gradient) string
- func RetryCmd(fn func() (tea.Msg, error), opts RetryOpts) tea.Cmd
- func SaveYAML(path string, src any) error
- func SelfUpdate(cfg UpdateConfig) error
- func SelfUpdateRollback() error
- func Serve(ctx context.Context, cfg ServeConfig) error
- func SetThemeCmd(t Theme) func() tea.Msg
- func SkipVersion(cfg UpdateConfig, v string) error
- func Sparkline(data []float64, maxWidth int, opts *SparklineOpts) (string, int)
- func ToastCmd(severity ToastSeverity, title, body string, duration time.Duration, ...) tea.Cmd
- func ToastError(title, body string) tea.Cmd
- func ToastInfo(title, body string) tea.Cmd
- func ToastSuccess(title, body string) tea.Cmd
- func ToastWarn(title, body string) tea.Cmd
- func Truncate(s string, maxWidth int) string
- func ValidateConfig(cfg UpdateConfig) error
- func VerifyChecksum(data []byte, assetName string, checksumFile []byte) error
- func VerifyCosignSignature(assetData []byte, sigData []byte, pubKeyPEM string) error
- func VerifyInstalled(expectedTag string) error
- func WriteCache(path string, cache UpdateCache) error
- type Activatable
- type Alignment
- type AnySignal
- type App
- type BackoffStrategy
- type BorderSet
- type Breadcrumbs
- func (b *Breadcrumbs) Focused() bool
- func (b *Breadcrumbs) Init() tea.Cmd
- func (b *Breadcrumbs) KeyBindings() []KeyBind
- func (b *Breadcrumbs) SetFocused(f bool)
- func (b *Breadcrumbs) SetSize(w, h int)
- func (b *Breadcrumbs) SetTheme(th Theme)
- func (b *Breadcrumbs) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (b *Breadcrumbs) View() string
- type CLICommand
- type CellRenderer
- type Clock
- type CollapsibleSection
- type Column
- type Command
- type CommandBar
- func (c *CommandBar) Close()
- func (c *CommandBar) Focused() bool
- func (c *CommandBar) Init() tea.Cmd
- func (c *CommandBar) Inline() bool
- func (c *CommandBar) IsActive() bool
- func (c *CommandBar) KeyBindings() []KeyBind
- func (c *CommandBar) SetActive(v bool)
- func (c *CommandBar) SetFocused(f bool)
- func (c *CommandBar) SetSize(w, h int)
- func (c *CommandBar) SetTheme(t Theme)
- func (c *CommandBar) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (c *CommandBar) View() string
- type Component
- type Config
- func (c *Config[T]) AsSignal() *Signal[T]
- func (c *Config[T]) CLICommands() map[string]CLICommand
- func (c *Config[T]) Defaults() T
- func (c *Config[T]) Editor() *ConfigEditor
- func (c *Config[T]) IsDirty() bool
- func (c *Config[T]) Path() string
- func (c *Config[T]) Reset() error
- func (c *Config[T]) Save() error
- func (c *Config[T]) SetValue(fn func(*T)) error
- func (c *Config[T]) WatchFile(ctx context.Context, onChange func(T)) error
- type ConfigEditor
- func (c *ConfigEditor) Close()
- func (c *ConfigEditor) Focused() bool
- func (c *ConfigEditor) Init() tea.Cmd
- func (c *ConfigEditor) IsActive() bool
- func (c *ConfigEditor) KeyBindings() []KeyBind
- func (c *ConfigEditor) SetFocused(f bool)
- func (c *ConfigEditor) SetSize(w, h int)
- func (c *ConfigEditor) SetTheme(t Theme)
- func (c *ConfigEditor) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (c *ConfigEditor) View() string
- type ConfigField
- type ConfigOption
- type ConfirmField
- func (f *ConfirmField) FieldID() string
- func (f *ConfirmField) Init() tea.Cmd
- func (f *ConfirmField) Label() string
- func (f *ConfirmField) SetFocused(_ bool)
- func (f *ConfirmField) SetValue(v string)
- func (f *ConfirmField) Update(msg tea.Msg) tea.Cmd
- func (f *ConfirmField) Validate() error
- func (f *ConfirmField) Value() string
- func (f *ConfirmField) View(focused bool, theme Theme, _ int) string
- func (f *ConfirmField) WithDefault(v bool) *ConfirmField
- func (f *ConfirmField) WithHint(hint string) *ConfirmField
- type Context
- type CopyToClipboardMsg
- type CursorChangeHandler
- type CursorStyle
- type DebugDataProvider
- type DebugProvider
- type DebugProviderWithLifecycle
- type DetailOverlay
- func (d *DetailOverlay[T]) Close()
- func (d *DetailOverlay[T]) Focused() bool
- func (d *DetailOverlay[T]) Init() tea.Cmd
- func (d *DetailOverlay[T]) IsActive() bool
- func (d *DetailOverlay[T]) Item() T
- func (d *DetailOverlay[T]) KeyBindings() []KeyBind
- func (d *DetailOverlay[T]) SetActive(v bool)
- func (d *DetailOverlay[T]) SetFocused(f bool)
- func (d *DetailOverlay[T]) SetSize(w, h int)
- func (d *DetailOverlay[T]) SetTheme(t Theme)
- func (d *DetailOverlay[T]) Show(item T)
- func (d *DetailOverlay[T]) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (d *DetailOverlay[T]) View() string
- type DetailOverlayOpts
- type DetailRenderer
- type DualPane
- type Ease
- type Field
- type FilePicker
- func (fp *FilePicker) Focused() bool
- func (fp *FilePicker) Init() tea.Cmd
- func (fp *FilePicker) KeyBindings() []KeyBind
- func (fp *FilePicker) SetFocused(f bool)
- func (fp *FilePicker) SetSize(w, h int)
- func (fp *FilePicker) SetTheme(t Theme)
- func (fp *FilePicker) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (fp *FilePicker) View() string
- type FilePickerOpts
- type FilterFunc
- type Flex
- type FlexAlign
- type FlexJustify
- type FloatingOverlay
- type Focus
- type ForcedChoice
- type ForcedUpdateScreen
- type Form
- func (f *Form) Focused() bool
- func (f *Form) Init() tea.Cmd
- func (f *Form) KeyBindings() []KeyBind
- func (f *Form) Reset()
- func (f *Form) SetFocused(focused bool)
- func (f *Form) SetSize(width, height int)
- func (f *Form) SetTheme(th Theme)
- func (f *Form) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (f *Form) Values() map[string]string
- func (f *Form) View() string
- type FormGroup
- type FormOpts
- type FormSubmitMsg
- type Glyphs
- type Gradient
- type HBox
- func (h *HBox) Focused() bool
- func (h *HBox) Init() tea.Cmd
- func (h *HBox) KeyBindings() []KeyBind
- func (h *HBox) SetFocused(focused bool)
- func (h *HBox) SetSize(width, height int)
- func (h *HBox) SetTheme(th Theme)
- func (h *HBox) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (h *HBox) View() string
- type Help
- func (h *Help) Close()
- func (h *Help) Focused() bool
- func (h *Help) Init() tea.Cmd
- func (h *Help) IsActive() bool
- func (h *Help) KeyBindings() []KeyBind
- func (h *Help) SetFocused(f bool)
- func (h *Help) SetSize(w, ht int)
- func (h *Help) SetTheme(t Theme)
- func (h *Help) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (h *Help) View() string
- type InlineOverlay
- type InputCapture
- type InstallMethod
- type KeyBind
- type KeyGroup
- type Layout
- type ListView
- func (l *ListView[T]) CursorIndex() int
- func (l *ListView[T]) CursorItem() *T
- func (l *ListView[T]) Focused() bool
- func (l *ListView[T]) HandleKey(msg tea.KeyMsg) tea.Cmd
- func (l *ListView[T]) Init() tea.Cmd
- func (l *ListView[T]) IsAtBottom() bool
- func (l *ListView[T]) IsAtTop() bool
- func (l *ListView[T]) ItemCount() int
- func (l *ListView[T]) Items() []T
- func (l *ListView[T]) KeyBindings() []KeyBind
- func (l *ListView[T]) Refresh()
- func (l *ListView[T]) ScrollToBottom()
- func (l *ListView[T]) ScrollToTop()
- func (l *ListView[T]) SetCursor(idx int)
- func (l *ListView[T]) SetFocused(f bool)
- func (l *ListView[T]) SetItems(items []T)
- func (l *ListView[T]) SetSize(w, h int)
- func (l *ListView[T]) SetTheme(th Theme)
- func (l *ListView[T]) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (l *ListView[T]) View() string
- type ListViewOpts
- type LogAppendMsg
- type LogLevel
- type LogLine
- type LogViewer
- func (lv *LogViewer) Append(line LogLine)
- func (lv *LogViewer) Clear()
- func (lv *LogViewer) Focused() bool
- func (lv *LogViewer) Init() tea.Cmd
- func (lv *LogViewer) KeyBindings() []KeyBind
- func (lv *LogViewer) Lines() []LogLine
- func (lv *LogViewer) SetFocused(f bool)
- func (lv *LogViewer) SetSize(w, h int)
- func (lv *LogViewer) SetTheme(th Theme)
- func (lv *LogViewer) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (lv *LogViewer) View() string
- type Module
- type ModuleWithKeybinds
- type ModuleWithProviders
- type MultiSelectField
- func (f *MultiSelectField) FieldID() string
- func (f *MultiSelectField) Init() tea.Cmd
- func (f *MultiSelectField) Label() string
- func (f *MultiSelectField) SetFocused(_ bool)
- func (f *MultiSelectField) SetValue(v string)
- func (f *MultiSelectField) Update(msg tea.Msg) tea.Cmd
- func (f *MultiSelectField) Validate() error
- func (f *MultiSelectField) Value() string
- func (f *MultiSelectField) View(focused bool, theme Theme, _ int) string
- func (f *MultiSelectField) WithHint(hint string) *MultiSelectField
- func (f *MultiSelectField) WithRequired() *MultiSelectField
- type Node
- type NotifyMsg
- type NumberField
- func (f *NumberField) FieldID() string
- func (f *NumberField) Init() tea.Cmd
- func (f *NumberField) Label() string
- func (f *NumberField) SetFocused(focused bool)
- func (f *NumberField) SetValue(v string)
- func (f *NumberField) Update(msg tea.Msg) tea.Cmd
- func (f *NumberField) Validate() error
- func (f *NumberField) Value() string
- func (f *NumberField) View(focused bool, theme Theme, width int) string
- func (f *NumberField) WithDefault(v float64) *NumberField
- func (f *NumberField) WithHint(hint string) *NumberField
- func (f *NumberField) WithMax(max float64) *NumberField
- func (f *NumberField) WithMin(min float64) *NumberField
- func (f *NumberField) WithPlaceholder(p string) *NumberField
- func (f *NumberField) WithRequired() *NumberField
- type Option
- func WithAnimations(enabled bool) Option
- func WithAutoUpdate(cfg UpdateConfig) Option
- func WithComponent(name string, c Component) Option
- func WithDebugProvider(p DebugProvider) Option
- func WithDevConsole() Option
- func WithFocusCycleKey(key string) Option
- func WithHelp() Option
- func WithKeyBind(kb KeyBind) Option
- func WithLayout(l *DualPane) Option
- func WithModule(m Module) Option
- func WithMouseSupport() Option
- func WithOverlay(name string, triggerKey string, o Overlay) Option
- func WithSlot(name SlotName, c Component) Option
- func WithSlotOverlay(name, triggerKey string, o Overlay) Option
- func WithStatusBar(left, right func() string) Option
- func WithStatusBarSignal(left, right *Signal[string]) Option
- func WithTheme(t Theme) Option
- func WithThemeHotReload(path string) Option
- func WithTickInterval(d time.Duration) Option
- type Orientation
- type Overlay
- type PasswordField
- func (f *PasswordField) FieldID() string
- func (f *PasswordField) Init() tea.Cmd
- func (f *PasswordField) Label() string
- func (f *PasswordField) SetFocused(focused bool)
- func (f *PasswordField) SetValue(v string)
- func (f *PasswordField) Update(msg tea.Msg) tea.Cmd
- func (f *PasswordField) Validate() error
- func (f *PasswordField) Value() string
- func (f *PasswordField) View(focused bool, theme Theme, width int) string
- func (f *PasswordField) WithHint(hint string) *PasswordField
- func (f *PasswordField) WithPlaceholder(p string) *PasswordField
- func (f *PasswordField) WithRequired() *PasswordField
- func (f *PasswordField) WithValidator(v Validator) *PasswordField
- type Picker
- func (p *Picker) Close()
- func (p *Picker) CursorItem() *PickerItem
- func (p *Picker) Focused() bool
- func (p *Picker) Init() tea.Cmd
- func (p *Picker) IsActive() bool
- func (p *Picker) Items() []PickerItem
- func (p *Picker) KeyBindings() []KeyBind
- func (p *Picker) Open()
- func (p *Picker) SetFocused(f bool)
- func (p *Picker) SetItems(items []PickerItem)
- func (p *Picker) SetSize(w, h int)
- func (p *Picker) SetTheme(t Theme)
- func (p *Picker) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (p *Picker) View() string
- type PickerItem
- type PickerOpts
- type Poller
- func (p *Poller) Check(msg TickMsg) tea.Cmd
- func (p *Poller) ClearRateLimit()
- func (p *Poller) DebugProvider() DebugDataProvider
- func (p *Poller) ForceRefresh()
- func (p *Poller) IsPaused() bool
- func (p *Poller) LastPoll() time.Time
- func (p *Poller) NextPoll() time.Time
- func (p *Poller) Pause()
- func (p *Poller) Resume()
- func (p *Poller) SetInterval(d time.Duration)
- func (p *Poller) SetRateLimited(resetAt time.Time)
- func (p *Poller) Stats() PollerStats
- func (p *Poller) TogglePause()
- type PollerErrorMsg
- type PollerOpts
- type PollerRateLimitedMsg
- type PollerStartMsg
- type PollerStats
- type PollerSuccessMsg
- type ProgressFunc
- type RateLimitError
- type Registry
- type Release
- type ReleaseAsset
- func MatchAsset(assets []ReleaseAsset, binaryName, goos, goarch string) (ReleaseAsset, error)
- func MatchChecksumAsset(assets []ReleaseAsset) (ReleaseAsset, error)
- func MatchDeltaAsset(assets []ReleaseAsset, binaryName, fromVersion, toVersion, goos, goarch string) (ReleaseAsset, error)
- func MatchSigAsset(assets []ReleaseAsset, assetName string) (ReleaseAsset, error)
- type ReleaseNotesOverlay
- func (o *ReleaseNotesOverlay) Init() tea.Cmd
- func (o *ReleaseNotesOverlay) MaxOffset() int
- func (o *ReleaseNotesOverlay) SetTheme(t Theme)
- func (o *ReleaseNotesOverlay) Update(msg tea.Msg) (tea.Model, tea.Cmd)
- func (o *ReleaseNotesOverlay) View() string
- func (o *ReleaseNotesOverlay) VisibleLines() int
- type RetryErrorMsg
- type RetryOpts
- type Row
- type RowClickHandler
- type RowStyler
- type SelectField
- func (f *SelectField) FieldID() string
- func (f *SelectField) Init() tea.Cmd
- func (f *SelectField) Label() string
- func (f *SelectField) SetFocused(_ bool)
- func (f *SelectField) SetValue(v string)
- func (f *SelectField) Update(msg tea.Msg) tea.Cmd
- func (f *SelectField) Validate() error
- func (f *SelectField) Value() string
- func (f *SelectField) View(focused bool, theme Theme, _ int) string
- func (f *SelectField) WithDefault(v string) *SelectField
- func (f *SelectField) WithHint(hint string) *SelectField
- func (f *SelectField) WithRequired() *SelectField
- func (f *SelectField) WithValidator(v Validator) *SelectField
- type ServeConfig
- type SetThemeMsg
- type Signal
- type SinglePane
- type Size
- type Sized
- type SlotName
- type SortFunc
- type SparklineOpts
- type Split
- func (s *Split) Focused() bool
- func (s *Split) Init() tea.Cmd
- func (s *Split) KeyBindings() []KeyBind
- func (s *Split) SetFocused(f bool)
- func (s *Split) SetSize(w, h int)
- func (s *Split) SetTheme(th Theme)
- func (s *Split) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (s *Split) View() string
- type StatusBar
- func (s *StatusBar) Focused() bool
- func (s *StatusBar) Init() tea.Cmd
- func (s *StatusBar) KeyBindings() []KeyBind
- func (s *StatusBar) SetFocused(f bool)
- func (s *StatusBar) SetSize(w, h int)
- func (s *StatusBar) SetTheme(t Theme)
- func (s *StatusBar) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (s *StatusBar) View() string
- type StatusBarOpts
- type StringSource
- type StyleSet
- type TabItem
- type Table
- func (t *Table) CapturesInput() bool
- func (t *Table) CursorIndex() int
- func (t *Table) CursorRow() Row
- func (t *Table) FilterQuery() string
- func (t *Table) Focused() bool
- func (t *Table) Init() tea.Cmd
- func (t *Table) KeyBindings() []KeyBind
- func (t *Table) RowCount() int
- func (t *Table) SetCursor(idx int)
- func (t *Table) SetFilter(fn FilterFunc)
- func (t *Table) SetFocused(f bool)
- func (t *Table) SetRows(rows []Row)
- func (t *Table) SetSize(w, h int)
- func (t *Table) SetSort(col int, asc bool)
- func (t *Table) SetTheme(th Theme)
- func (t *Table) SortAsc() bool
- func (t *Table) SortCol() int
- func (t *Table) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (t *Table) View() string
- func (t *Table) VisibleRowCount() int
- type TableOpts
- type TableRowProvider
- type TableRowProviderFunc
- type Tabs
- func (t *Tabs) ActiveIndex() int
- func (t *Tabs) Focused() bool
- func (t *Tabs) Init() tea.Cmd
- func (t *Tabs) KeyBindings() []KeyBind
- func (t *Tabs) OnChange(fn func(int))
- func (t *Tabs) SetActive(i int)
- func (t *Tabs) SetFocused(focused bool)
- func (t *Tabs) SetSize(w, h int)
- func (t *Tabs) SetTheme(th Theme)
- func (t *Tabs) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (t *Tabs) View() string
- type TabsOpts
- type TextField
- func (f *TextField) FieldID() string
- func (f *TextField) Init() tea.Cmd
- func (f *TextField) Label() string
- func (f *TextField) SetFocused(focused bool)
- func (f *TextField) SetValue(v string)
- func (f *TextField) Update(msg tea.Msg) tea.Cmd
- func (f *TextField) Validate() error
- func (f *TextField) Value() string
- func (f *TextField) View(focused bool, theme Theme, width int) string
- func (f *TextField) WithDefault(v string) *TextField
- func (f *TextField) WithHint(hint string) *TextField
- func (f *TextField) WithPlaceholder(p string) *TextField
- func (f *TextField) WithRequired() *TextField
- func (f *TextField) WithValidator(v Validator) *TextField
- type Theme
- func CatppuccinMochaTheme() Theme
- func DefaultTheme() Theme
- func DraculaTheme() Theme
- func FromAlacritty(data []byte) (Theme, error)
- func FromGogh(data []byte) (Theme, error)
- func FromIterm2(data []byte) (Theme, error)
- func GruvboxDarkTheme() Theme
- func KanagawaTheme() Theme
- func LightTheme() Theme
- func NordTheme() Theme
- func OneDarkTheme() Theme
- func ParseThemeYAML(data []byte) (Theme, error)
- func RosePineTheme() Theme
- func ThemeFromMap(m map[string]string) Theme
- func TokyoNightTheme() Theme
- type ThemeHotReload
- type ThemeHotReloadErrMsg
- type ThemeHotReloadMsg
- type Themed
- type TickMsg
- type ToastAction
- type ToastManagerOpts
- type ToastMsg
- type ToastSeverity
- type Tree
- func (t *Tree) CursorNode() *Node
- func (t *Tree) Focused() bool
- func (t *Tree) Init() tea.Cmd
- func (t *Tree) KeyBindings() []KeyBind
- func (t *Tree) Roots() []*Node
- func (t *Tree) SetFocused(f bool)
- func (t *Tree) SetRoots(roots []*Node)
- func (t *Tree) SetSize(w, h int)
- func (t *Tree) SetTheme(theme Theme)
- func (t *Tree) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (t *Tree) View() string
- type TreeOpts
- type Tween
- type Unsubscribe
- type UpdateCache
- type UpdateConfig
- type UpdateMode
- type UpdateProgress
- type UpdateProgressMsg
- type UpdateResult
- type VBox
- func (v *VBox) Focused() bool
- func (v *VBox) Init() tea.Cmd
- func (v *VBox) KeyBindings() []KeyBind
- func (v *VBox) SetFocused(focused bool)
- func (v *VBox) SetSize(width, height int)
- func (v *VBox) SetTheme(th Theme)
- func (v *VBox) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (v *VBox) View() string
- type Validator
- type Version
- type Viewport
- func (v *Viewport) AtBottom() bool
- func (v *Viewport) AtTop() bool
- func (v *Viewport) Focused() bool
- func (v *Viewport) GotoBottom()
- func (v *Viewport) GotoTop()
- func (v *Viewport) HandleKey(msg tea.KeyMsg) tea.Cmd
- func (v *Viewport) Init() tea.Cmd
- func (v *Viewport) KeyBindings() []KeyBind
- func (v *Viewport) ScrollBy(delta int)
- func (v *Viewport) SetContent(content string)
- func (v *Viewport) SetFocused(f bool)
- func (v *Viewport) SetSize(w, h int)
- func (v *Viewport) SetTheme(th Theme)
- func (v *Viewport) Update(msg tea.Msg, ctx Context) (Component, tea.Cmd)
- func (v *Viewport) View() string
- func (v *Viewport) YOffset() int
- type ViewportGlyphs
Examples ¶
Constants ¶
const ( ChannelStable = "stable" ChannelBeta = "beta" ChannelPrerelease = "prerelease" )
Update channels.
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.
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 ¶
This section is empty.
Functions ¶
func ApplyDeltaPatch ¶
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 ¶
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 ¶
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 ¶
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
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
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
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 ¶
DevConsoleToggleCmd returns a tea.Cmd that toggles the dev console.
func Divider ¶
Divider renders a horizontal line of ─ characters at the given width, styled with the theme's Border color.
func EnsureConfigDir ¶ added in v0.1.1
EnsureConfigDir creates the configuration directory for appName if it does not already exist. Returns the directory path.
func ExtractBinary ¶
ExtractBinary extracts the named binary from a tar.gz or zip archive.
func Hyperlink ¶
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 ¶
Interpolate interpolates between from and to using easing e at progress t in [0,1]. Supported types: float64, int, lipgloss.Color.
func IsRateLimited ¶
IsRateLimited reports whether err is a RateLimitError.
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 LoadYAML ¶ added in v0.1.1
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 ¶
LogAppendCmd returns a tea.Cmd that appends a LogLine to any LogViewer that receives it via Update.
func Markdown ¶
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 OSC8Link ¶
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 RelativeTime ¶
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 ¶
RenderGradient renders text with the given gradient. Convenience wrapper for Gradient.RenderText.
func RetryCmd ¶ added in v0.1.1
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 SaveYAML ¶ added in v0.1.1
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 ¶
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
ToastError returns a tea.Cmd that shows an error toast with a 6s duration.
func ToastInfo ¶ added in v0.1.1
ToastInfo returns a tea.Cmd that shows an informational toast with a 4s duration.
func ToastSuccess ¶ added in v0.1.1
ToastSuccess returns a tea.Cmd that shows a success toast with a 4s duration.
func ToastWarn ¶ added in v0.1.1
ToastWarn returns a tea.Cmd that shows a warning toast with a 6s duration.
func Truncate ¶
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 ¶
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 ¶
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 ¶
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 Activatable ¶
type Activatable interface {
SetActive(bool)
}
Activatable is implemented by overlays that can be explicitly activated.
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 ¶
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
}
Output:
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
}
Output:
func (*App) AddKeyBind ¶
AddKeyBind adds a global keybinding after construction. The binding appears in the help screen and its Handler is called on key press.
func (*App) Model ¶
Model returns the underlying tea.Model for use with btest or other testing frameworks that need a tea.Model directly.
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 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 Breadcrumbs ¶
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 renders a horizontal trail of path segments separated by a configurable separator. When the rendered width exceeds MaxWidth the leading segments are replaced with "…" until it fits.
func NewBreadcrumbs ¶
func NewBreadcrumbs(segments []string) *Breadcrumbs
NewBreadcrumbs creates a Breadcrumbs component with default separator " / ".
func (*Breadcrumbs) Focused ¶
func (b *Breadcrumbs) Focused() bool
Focused reports whether the Breadcrumbs is focused.
func (*Breadcrumbs) Init ¶
func (b *Breadcrumbs) Init() tea.Cmd
Init initializes the Breadcrumbs component. It returns nil.
func (*Breadcrumbs) KeyBindings ¶
func (b *Breadcrumbs) KeyBindings() []KeyBind
KeyBindings returns the key bindings for the Breadcrumbs.
func (*Breadcrumbs) SetFocused ¶
func (b *Breadcrumbs) SetFocused(f bool)
SetFocused sets the focus state of the Breadcrumbs.
func (*Breadcrumbs) SetSize ¶
func (b *Breadcrumbs) SetSize(w, h int)
SetSize sets the width and height of the Breadcrumbs.
func (*Breadcrumbs) SetTheme ¶
func (b *Breadcrumbs) SetTheme(th Theme)
SetTheme updates the theme used by the Breadcrumbs.
func (*Breadcrumbs) View ¶
func (b *Breadcrumbs) View() string
View renders the Breadcrumbs as a string.
type CLICommand ¶ added in v0.1.13
CLICommand is a config subcommand that can be invoked from a CLI.
type CellRenderer ¶
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 Clock ¶
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 CollapsibleSection ¶
CollapsibleSection is a render helper for collapsible panel sections. It is not a Component — the parent component owns its state and calls Toggle().
func NewCollapsibleSection ¶
func NewCollapsibleSection(title string) *CollapsibleSection
NewCollapsibleSection creates an expanded section with the given title.
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) Toggle ¶
func (s *CollapsibleSection) Toggle()
Toggle flips the collapsed state.
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) 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 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
}
Output:
func (*Config[T]) AsSignal ¶ added in v0.1.13
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
}
Output:
func (*Config[T]) Reset ¶ added in v0.1.3
Reset restores all fields to their default values and saves.
func (*Config[T]) SetValue ¶ added in v0.1.3
SetValue updates the config via a mutator function and marks it dirty.
func (*Config[T]) WatchFile ¶ added in v0.1.13
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) 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) Init ¶
func (f *ConfirmField) Init() tea.Cmd
Init initializes the ConfirmField component.
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
}
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 ¶
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]) 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 ¶
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 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.
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) KeyBindings ¶
func (fp *FilePicker) KeyBindings() []KeyBind
KeyBindings implements Component.
func (*FilePicker) SetFocused ¶
func (fp *FilePicker) SetFocused(f bool)
SetFocused 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 ¶
FilterFunc returns true if a row should be visible. Used for predicate-based filtering (e.g., show only gainers, filter by type).
type Flex ¶
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) KeyBindings ¶
KeyBindings returns the key bindings for the Flex.
func (Flex) SetFocused ¶
SetFocused sets the focus state of the Flex.
func (Flex) SetTheme ¶ added in v0.1.3
SetTheme implements Themed by delegating to the wrapped component.
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 ¶
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 ¶
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
}
Output:
func (*Form) Reset ¶
func (f *Form) Reset()
Reset clears the form submission state and returns focus to the first field.
type FormSubmitMsg ¶
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 ¶
Gradient defines a linear color gradient between two lipgloss colors.
func (Gradient) RenderText ¶
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.
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 (*Help) KeyBindings ¶
KeyBindings returns the key bindings for the Help.
func (*Help) SetFocused ¶
SetFocused sets the focus state of the Help.
type InlineOverlay ¶
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 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 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 ¶
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]) HandleKey ¶
HandleKey processes navigation keys. Use this when embedding ListView in another component. Returns Consumed() if handled, nil otherwise.
func (*ListView[T]) IsAtBottom ¶
IsAtBottom returns true if the viewport is scrolled to the bottom.
func (*ListView[T]) KeyBindings ¶
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]) SetFocused ¶
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.
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 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
}
Output:
func (*LogViewer) KeyBindings ¶
KeyBindings implements Component.
func (*LogViewer) SetFocused ¶
SetFocused implements Component.
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 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) Init ¶
func (f *MultiSelectField) Init() tea.Cmd
Init initializes the MultiSelectField component.
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
// 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
}
Node is a single node in a Tree.
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) Init ¶
func (f *NumberField) Init() tea.Cmd
Init initializes the NumberField component.
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 ¶
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 WithComponent ¶
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 WithFocusCycleKey ¶
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 ¶
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 ¶
WithLayout sets a dual-pane layout.
Slot mapping: DualPane.Main -> SlotMain, DualPane.Side -> SlotSidebar.
func WithModule ¶ added in v0.1.3
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
}
Output:
func WithMouseSupport ¶
func WithMouseSupport() Option
WithMouseSupport enables mouse event tracking.
func WithOverlay ¶
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 ¶
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 ¶
WithSlotOverlay pushes an overlay into SlotOverlay with an associated trigger key and display name. It is the slot-native equivalent of WithOverlay.
func WithStatusBar ¶
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 ¶
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 WithThemeHotReload ¶
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 ¶
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) Init ¶
func (f *PasswordField) Init() tea.Cmd
Init initializes the PasswordField component.
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
}
Output:
func (*Picker) CursorItem ¶
func (p *Picker) CursorItem() *PickerItem
CursorItem returns the currently highlighted item, or nil if there are none.
func (*Picker) Items ¶
func (p *Picker) Items() []PickerItem
Items returns the full (unfiltered) item list.
func (*Picker) KeyBindings ¶
KeyBindings implements Component.
func (*Picker) SetItems ¶
func (p *Picker) SetItems(items []PickerItem)
SetItems replaces the item list and re-runs the filter.
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 ¶
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
}
Output:
func NewPollerWithClock ¶
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
}
Output:
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
}
Output:
func (*Poller) Check ¶
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) NextPoll ¶ added in v0.1.3
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) SetInterval ¶
SetInterval changes the polling interval.
func (*Poller) SetRateLimited ¶ added in v0.1.3
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) TogglePause ¶
func (p *Poller) TogglePause()
TogglePause toggles between paused and active.
type PollerErrorMsg ¶ added in v0.1.3
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
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
PollerSuccessMsg wraps the successful fetch result.
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 ¶
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 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 ¶
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 ¶
FetchLatestReleaseForChannel selects the appropriate release for the configured channel. Stable falls through to FetchLatestRelease for backward compatibility; non-stable channels walk /releases.
func FetchReleases ¶
FetchReleases returns the full list of releases for the repo, newest first, using the rate-limited fetcher.
func PickReleaseForChannel ¶
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) 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
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 RowClickHandler ¶
RowClickHandler is called when a row is clicked or Enter is pressed.
type RowStyler ¶
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) Init ¶
func (f *SelectField) Init() tea.Cmd
Init initializes the SelectField component.
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 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 ¶
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 ¶
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
}
Output:
type SinglePane ¶
type SinglePane struct{}
SinglePane is a layout with one component filling all available space.
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) KeyBindings ¶
KeyBindings returns the key bindings for the Sized.
func (Sized) SetFocused ¶
SetFocused sets the focus state of the Sized.
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" // 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 ¶
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 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 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
}
Output:
func (*Split) KeyBindings ¶
KeyBindings returns the key bindings for the Split.
func (*Split) SetFocused ¶
SetFocused sets the focus state of the Split.
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) KeyBindings ¶
KeyBindings returns the key bindings for the StatusBar.
func (*StatusBar) SetFocused ¶
SetFocused sets the focus state of the StatusBar.
type StatusBarOpts ¶
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 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 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 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 ¶
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
}
Output:
func (*Table) CapturesInput ¶
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 ¶
CursorIndex returns the current cursor position.
func (*Table) CursorRow ¶
CursorRow returns the row at the current cursor position, or nil if empty.
func (*Table) FilterQuery ¶
FilterQuery returns the active built-in text search query.
func (*Table) KeyBindings ¶
KeyBindings returns the key bindings for the Table.
func (*Table) RowCount ¶
RowCount returns the total number of rows (before filtering). In virtual mode this is the provider's Len.
func (*Table) SetCursor ¶
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 ¶
SetFocused sets the focus state of the Table.
func (*Table) SetRows ¶
SetRows replaces the table data and rebuilds the view. In virtual mode this is a no-op; update the underlying TableRowProvider instead.
func (*Table) SetSort ¶
SetSort sets the sort column and direction, then rebuilds the view. Pass col=-1 to clear sorting.
func (*Table) VisibleRowCount ¶
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 ¶
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 ¶
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 (*Tabs) ActiveIndex ¶
ActiveIndex returns the currently active tab index.
func (*Tabs) SetFocused ¶
SetFocused implements Component. When focused, the active content is also focused.
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 ¶
NewTextField creates a new single-line text field.
func (*TextField) SetFocused ¶
SetFocused sets the focus state of the TextField.
func (*TextField) Validate ¶
Validate checks the current value against the field's validation rules.
func (*TextField) WithDefault ¶
WithDefault sets the initial value.
func (*TextField) WithPlaceholder ¶
WithPlaceholder sets the placeholder text.
func (*TextField) WithRequired ¶
WithRequired marks the field as required.
func (*TextField) WithValidator ¶
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
}
Output:
func FromAlacritty ¶
FromAlacritty imports a Theme from an Alacritty TOML config file.
func FromIterm2 ¶
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 LightTheme ¶
func LightTheme() Theme
LightTheme returns a light theme for light terminal backgrounds.
func ParseThemeYAML ¶
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 ThemeFromMap ¶
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 ¶
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 ¶
RegisterStyle stores a custom StyleSet override for name on this Theme instance. Subsequent calls to Style(name) will return this override.
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 ¶
TickMsg is sent to all components at the configured tick interval. Use it for animations, countdowns, polling, and flash effects.
type ToastAction ¶
type ToastAction struct {
Label string
Handler func()
}
ToastAction is a labelled action button on a toast.
type ToastManagerOpts ¶
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 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 ¶
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
}
Output:
func (*Tree) CursorNode ¶
CursorNode returns the currently highlighted node, or nil if the tree is empty.
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)
}
TreeOpts configures Tree behaviour.
type Tween ¶
Tween tracks animation progress over a fixed duration. When BLIT_NO_ANIM=1, Start is a no-op and Progress always returns 1.
type Unsubscribe ¶
type Unsubscribe func()
Unsubscribe removes a previously registered Subscribe callback.
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.
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) 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) View ¶
func (p *UpdateProgress) View() string
View implements tea.Model. Renders a styled progress bar with bytes, percent, speed, and ETA.
type UpdateProgressMsg ¶
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.
type Validator ¶
Validator is a function that validates a field value. Return nil if valid, or an error describing the problem.
func ComposeValidators ¶
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 MinLength ¶
MinLength returns a Validator that fails if the value is shorter than n characters.
func RegexValidator ¶
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 ¶
Version represents a parsed semantic version.
func ParseMinimumVersion ¶
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 ¶
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.
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 (*Viewport) KeyBindings ¶
KeyBindings returns the key bindings for the Viewport.
func (*Viewport) ScrollBy ¶
ScrollBy moves the viewport by delta lines (positive = down, negative = up).
func (*Viewport) SetContent ¶
SetContent sets the text content and resets the scroll position.
func (*Viewport) SetFocused ¶
SetFocused sets the focus state of the Viewport.
type ViewportGlyphs ¶
ViewportGlyphs holds the scrollbar track and thumb symbols for Viewport. Falls back to defaults when nil.
Source Files
¶
- anim.go
- app.go
- breadcrumbs.go
- clipboard.go
- collapsible.go
- commandbar.go
- component.go
- config.go
- config_module.go
- configeditor.go
- context.go
- detailoverlay.go
- devconsole.go
- doc.go
- filepicker.go
- form.go
- glyphs.go
- gradient.go
- help.go
- keybind.go
- layout.go
- listview.go
- logviewer.go
- markdown.go
- module.go
- notify.go
- overlay.go
- picker.go
- poller.go
- serve.go
- signal.go
- slot.go
- split.go
- statusbar.go
- style_registry.go
- table.go
- tabs.go
- theme.go
- theme_hot_reload.go
- theme_importers.go
- theme_presets.go
- tree.go
- update_forced.go
- update_notes_overlay.go
- update_progress.go
- updater.go
- updater_channel.go
- updater_cosign.go
- updater_delta.go
- updater_minversion.go
- updater_ratelimit.go
- updater_skip.go
- utils.go
- viewport.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package btest provides a virtual terminal screen and assertion helpers for testing Bubble Tea TUI applications.
|
Package btest provides a virtual terminal screen and assertion helpers for testing Bubble Tea TUI applications. |
|
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. |