Help us shape the future of Go! Take the 2026 Go Developer Survey

ui

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package ui holds the drawing primitives of the seamark console: the theme, the glyphs and the tones, the boxes, the modals and the overlay, the text helpers, the scroll, pager and list state, the line input (input.go), the multi-line text area (textarea.go), the movement keys and the n/a key helpers. The screens of internal/tui draw with them. input.go says why the console adopts no bubbles widget.

What belongs here

A declaration belongs to ui only when it renders or tracks a position without seamark vocabulary. The rule applies to its name, its parameters, its fields and its doc. Seamark vocabulary is, for example, effect, phase, region, proposal, pin, lesson, run, integration, client, setup, policy, brand and workspace. A declaration that names such a concept stays in internal/tui, usually in its widgets.go. So the next author can decide a move from the name alone.

Imports

ui imports the standard library and third-party packages freely, for example Lip Gloss, Bubbles key, x/ansi, termenv, and Bubble Tea for key messages. Of the seamark packages, it imports only internal/redact and internal/render, because the sanitizers need them. It never imports internal/tui or internal/tui/services, so a primitive cannot reach a screen, the console state or an engine. TestUIStaysBelowTheConsole checks this.

Exports

ui exports what internal/tui uses and nothing more; a name that only tests use stays unexported. The state types keep their fields exported, as the Bubbles widgets do, so a screen reads a position without an accessor.

Index

Constants

View Source
const (
	BgSel = iota

	BgWarn
	BgAdd
	BgDel
)

Row backgrounds of the 1a design. The selection spans the full inner width of a pane; diff rows and the stale banner use tinted rows.

View Source
const (
	WideWidth = 100
	MinWidth  = 60
	MinHeight = 20
)

Layout thresholds. A terminal at least WideWidth cells wide shows a list and its detail side by side; a narrower one shows one pane at a time. Below MinWidth by MinHeight the shell asks for more space. MinHeight is 20, because at 16 rows the confirmation dialogs lost their safety notes and the empty states lost their next action.

View Source
const DialogMinBox = 12

DialogMinBox is the narrowest modal box, so the text inside keeps a usable width even in a narrow area.

View Source
const (
	ModalMinW = 80
)

Modal geometry: 80 cells at the 120-column design size, wider on a wide terminal so long lines fold less.

View Source
const UnavailableWord = "n/a"

UnavailableWord marks the keys that the current target cannot use. It is ASCII and it is a word, so the marker reads without color, under NO_COLOR and with the ASCII glyph set.

Variables

View Source
var Nav = NavKeys{
	Up:       key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "up")),
	Down:     key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "down")),
	PageUp:   key.NewBinding(key.WithKeys("pgup", "ctrl+u"), key.WithHelp("pgup", "page up")),
	PageDown: key.NewBinding(key.WithKeys("pgdown", "ctrl+d"), key.WithHelp("pgdn", "page down")),
	Top:      key.NewBinding(key.WithKeys("home", "g"), key.WithHelp("home", "first")),
	Bottom:   key.NewBinding(key.WithKeys("end", "G"), key.WithHelp("end", "last")),
	Enter:    key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "open")),
	Back:     key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "back")),
	Toggle:   key.NewBinding(key.WithKeys(" "), key.WithHelp("space", "select")),
	Next:     key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "next pane")),
	Prev:     key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "previous pane")),
	Left:     key.NewBinding(key.WithKeys("left", "h"), key.WithHelp("←/h", "left")),
	Right:    key.NewBinding(key.WithKeys("right", "l"), key.WithHelp("→/l", "right")),
}

Nav holds the movement and activation bindings of every screen. ScrollState, TextPager and ListState read them, so a key moves a text and a list alike.

Functions

func BoxInner

func BoxInner(w int) int

BoxInner returns the content width of a box of outer width w: the two border cells and one cell of padding on each side.

func BoxRows

func BoxRows(h int) int

BoxRows returns the content height of a box of outer height h.

func BoxTitle

func BoxTitle(t *Theme, title string, focused bool) string

BoxTitle styles a box title: the focused pane in the title style, the other panes muted, as in the 1a design. The caller sanitizes the title, because most titles are fixed words.

func ClipWithEllipsis

func ClipWithEllipsis(lines []string, n, w int, ellipsis string) []string

ClipWithEllipsis keeps the first n plain lines. When lines are cut, the last kept line ends with the ellipsis, so the cut is visible.

func Diag

func Diag(s string) string

Diag makes a diagnostic safe: it redacts secrets first, because reader errors and native settings can quote tokens.

func DisplayPath

func DisplayPath(p string) string

DisplayPath shortens an absolute path for the header: the home directory becomes "~".

func DropBlankLines

func DropBlankLines(lines []string, n int) []string

DropBlankLines removes up to n blank lines, the last ones first. The blank lines near the top stay, because they separate the lead text that the reader sees first.

func ErrText

func ErrText(err error) string

ErrText returns a safe one-line error message, or "" for nil.

func Fit

func Fit(s string, w, h int) string

Fit clips or pads rendered text to exactly w cells by h lines. The shell needs exact sizes so a pane never pushes the footer away.

func HJoin

func HJoin(gap int, blocks ...string) string

HJoin places rendered blocks side by side with gap cells between them. Blocks of different heights are padded at the bottom.

func IsBlank

func IsBlank(line string) bool

IsBlank reports a line that shows nothing but spaces.

func IsUnavailable

func IsUnavailable(b key.Binding) bool

IsUnavailable reports an entry that unavailable made. A binding that a screen only disables stays hidden, so no other screen changes.

func JoinBlocks

func JoinBlocks(blocks ...string) string

JoinBlocks joins non-empty blocks with a blank line between them.

func JoinLineBlocks

func JoinLineBlocks(gap int, blocks ...[]string) []string

JoinLineBlocks joins the non-empty line blocks with gap blank lines between them.

func ListAll

func ListAll(bindings []key.Binding) []key.Binding

ListAll returns bindings with each disabled binding that has a key label as an unavailable entry. The help of a screen uses it to name every key of the screen, also the keys that do not work now.

func Listed

func Listed(b key.Binding) bool

Listed reports a binding that the hint rows and the help show: an enabled binding or an unavailable entry, each with a key label.

func ModalBodyWidth

func ModalBodyWidth(minW, w int) int

ModalBodyWidth returns the width of the body lines of a modal in a w-wide area. A caller wraps the body to this width, so the box shows each line whole.

func MultiLine

func MultiLine(s string) string

MultiLine makes untrusted multi-line text safe and keeps its line breaks. Tabs become spaces because they break width arithmetic.

func OneLine

func OneLine(s string) string

OneLine makes untrusted text safe for a single terminal line. Repository content, stored text and file names can hold escape sequences; the sanitizer keeps them inert.

func PadLeft

func PadLeft(s string, w int) string

PadLeft pads s on the left to w cells, for right-aligned counts.

func PadRight

func PadRight(s string, w int) string

PadRight pads s with spaces to w cells.

func Spread

func Spread(left, right string, w int) string

Spread places left and right text on one line of w cells.

func Truncate

func Truncate(s string, w int, ellipsis string) string

Truncate shortens styled or plain text to w cells with an ellipsis.

func TruncateLeft

func TruncateLeft(s string, w int, ellipsis string) string

TruncateLeft shortens s from the left, which keeps the most specific part of a path visible.

func Unavailable

func Unavailable(b key.Binding) key.Binding

Unavailable returns b as an entry that the hint rows and the help list as not available now: muted, after the word n/a. The copy is disabled, so every Enabled check reads it as not offered. A screen uses it for a key that the user must find even when the current target cannot use it (a user decision of 2026-10-04). The screen still handles the key press itself, with its package binding, and explains the refusal.

func Width

func Width(s string) int

Width returns the display width of s in terminal cells.

func WithHelp

func WithHelp(b key.Binding, k, desc string) key.Binding

WithHelp returns a copy of b with a different help text, so a screen can describe what a shared key does in its context.

func Wrap

func Wrap(s string, w int) string

Wrap word-wraps text to w cells. It breaks a line only at a space, so a command, a flag or a path that fits on one line stays whole. ansi.Wrap is not used, because it always breaks after a '-'. Each input line wraps on its own, so existing line breaks stay.

Types

type BoxOpts

type BoxOpts struct {
	// W and H are the outer size in cells, borders included.
	W, H int
	// Title is the styled label at the left of the top border.
	Title string
	// Right is the styled label at the right of the top border, for
	// example a count or a state.
	Right string
	// Foot is the styled label at the right of the bottom border, for
	// example a scroll position.
	Foot string
	// Focus draws the border in the accent color. Only the pane that
	// receives the movement keys has focus.
	Focus bool
	// Lines are the styled content lines. Each line is clipped to the
	// inner width with an ellipsis; lines past the inner height are
	// dropped, so callers scroll before they render.
	Lines []string
	// Fill paints the modal surface under the whole box.
	Fill bool
}

BoxOpts describes one bordered pane of the 1a layout. The title, the right label and the footer sit inside the border lines, so a pane spends no content line on its own heading.

type ColCell

type ColCell struct {
	Text string
	W    int
}

ColCell is one cell of a fixed-width table row.

func Cell

func Cell(text string, w int) ColCell

Cell builds a ColCell.

type Glyphs

type Glyphs struct {
	HeaderLeft, HeaderMid, HeaderRight string

	Cursor, Check, Uncheck, Locked, Kept, Bullet, Arrow, Sep, Ellipsis string
	Dash, OK, Warn, Fail, Info, Unknown, Unsupported                   string
	Dot, Hollow                                                        string
	RadioOn, RadioOff                                                  string

	RuleLight, RuleHeavy, Vertical string
	CornerTL, CornerTR, CornerBL   string
	CornerBR                       string

	BarFull, BarEmpty string
	Spark             []string

	Add, Del string
	Spinner  []string
}

Glyphs is one glyph set. The Unicode set uses only the single-width symbols of the 1a design, so width arithmetic stays exact. The ASCII set exists for fonts without these symbols. In each set, Sep differs from Vertical, because without color the glyph is the only signal between them.

type LineInput

type LineInput struct {

	// Placeholder is the faint hint of an empty input. "" keeps the
	// path hint.
	Placeholder string
	// Limit bounds the value in runes. 0 keeps lineInputLimit.
	Limit int
	// Accept filters typed runes, for example digits only for a day
	// count. nil accepts every rune that the sanitizer keeps.
	Accept func(rune) bool
	// RefuseMultiline refuses a whole input that holds a line break, for
	// example a paste of two lines, and Notice says why. Without it, the
	// line breaks go away and the lines join, which a filter accepts.
	RefuseMultiline bool
	// RefuseOverLimit refuses a whole input that would pass Limit, and
	// Notice says why. Without it, the runes past the limit go away
	// silently. With it, a value longer than the limit from Set is read
	// only (ReadOnly), because an edit could only shorten it by a cut.
	RefuseOverLimit bool
	// contains filtered or unexported fields
}

LineInput is a minimal single-line text input. The filter bars, the editors and the forms of the console use it. A filter or a count needs only typing, deletion and cursor movement. The optional fields let each form set its own hint, bound and runes. Their zero values keep the path filter behaviour, because the path filter was the first user.

func (*LineInput) Holds

func (in *LineInput) Holds(s string) bool

Holds reports whether the input can show and edit s exactly: the sanitizer and the accept filter keep every rune. A form opens a value that fails it as read-only, because an edit would change runes that the user never touched.

func (*LineInput) Key

func (in *LineInput) Key(msg tea.KeyMsg)

Key applies one key press. The sanitizer, the accept filter and the length bound drop runes, unless an opt-in field refuses the whole input instead. A read-only value takes only the movement keys.

func (*LineInput) MaxRunes

func (in *LineInput) MaxRunes() int

MaxRunes returns the length bound of the value in runes: Limit, or lineInputLimit when Limit is 0. A form names this bound when it locks a stored value, so the form never copies the number.

func (*LineInput) Notice

func (in *LineInput) Notice() string

Notice returns why the last key changed less than the user typed, or "". A form shows it under the input, because a refused paste must be visible. A field without an opt-in always returns "".

func (*LineInput) ReadOnly

func (in *LineInput) ReadOnly() bool

ReadOnly reports a value that is longer than the limit while RefuseOverLimit is set. Only Set can make such a value, for example with a text from a file. Key then moves the cursor but changes no rune.

func (*LineInput) Set

func (in *LineInput) Set(s string)

Set replaces the value and puts the cursor at its end. It keeps s as it is, so a caller checks s with Holds first when s is untrusted.

func (*LineInput) Value

func (in *LineInput) Value() string

Value returns the typed text.

func (*LineInput) View

func (in *LineInput) View(t *Theme) string

View renders the value with the cursor as a glyph (cursorView).

type ListState

type ListState struct {
	Cursor int
	Offset int
	// contains filtered or unexported fields
}

ListState is the cursor and scroll offset of one plain list. Screens keep one per list, so resize and refresh never reset the position.

func (*ListState) Clamp

func (l *ListState) Clamp(n, h int)

Clamp keeps the cursor inside n rows and the cursor row inside a window of h rows. It records a positive h as the window of the page keys. A key handler passes 0, because it does not know the height, and the recorded window then stays.

func (*ListState) Key

func (l *ListState) Key(msg tea.KeyMsg, n int) bool

Key moves the cursor by one movement key inside n rows and reports whether the key was one. Before the first render the window is 0, so a page key moves one row.

func (*ListState) Move

func (l *ListState) Move(delta, n int)

Move shifts the cursor by delta rows inside n rows.

type ModalOpts

type ModalOpts struct {
	Title, Right string
	Body         []string
	// Actions are the keys under the rule at the bottom. The row stays
	// visible while the body scrolls.
	Actions []key.Binding
	// Tail is the summary of a confirmation, for example "Removes 2
	// lines from one file". It stays under the rule, above the
	// actions, and never scrolls, so the minimum layout still shows what
	// y confirms. The caller wraps each line to ModalBodyWidth; the box
	// clips a longer line. A summary taller than the area keeps its first
	// lines, so the actions and the border stay (capTail). Nil keeps the
	// layout without a summary.
	Tail []string
	// MinW is the narrowest modal on a wide terminal; 0 selects
	// ModalMinW. A small terminal still gets a narrower modal.
	MinW int
	// Follow asks the modal to show the body lines Keep[0] to Keep[1],
	// for example the cursor row of a form. Only the modal knows the
	// height of its window, so a key handler sets Follow and the next
	// render scrolls. A negative Keep[0] keeps the position.
	Follow bool
	Keep   [2]int
}

ModalOpts is the content of one modal: the border labels, the body that scrolls, and the actions that the bottom row names.

type NavKeys struct {
	Up       key.Binding
	Down     key.Binding
	PageUp   key.Binding
	PageDown key.Binding
	Top      key.Binding
	Bottom   key.Binding
	Enter    key.Binding
	Back     key.Binding
	Toggle   key.Binding
	Next     key.Binding
	Prev     key.Binding
	Left     key.Binding
	Right    key.Binding
}

NavKeys are the shared movement and activation bindings. Screens use these values so every list moves the same way.

type ScrollState

type ScrollState struct {
	Off int

	Last int
	// contains filtered or unexported fields
}

ScrollState is the vertical position of one scrollable text. The view records the page size and the last offset, because the key handler cannot know how tall the rendered text is. The modals and most panes share this type, so their texts scroll with the same keys.

func (*ScrollState) Fit

func (sc *ScrollState) Fit(n, h int) (from, to int)

Fit records the bounds of a text of n lines in a window of h lines and returns the visible range [from, to). It clamps the offset, because a resize or a refresh can make the text shorter. Every box that scrolls calls it once per render, so all boxes keep one rule.

func (*ScrollState) Key

func (sc *ScrollState) Key(msg tea.KeyMsg) bool

Key applies a movement key and reports whether the key was one.

func (*ScrollState) Reveal

func (sc *ScrollState) Reveal(top, bottom, h int)

Reveal moves the offset so that the lines top to bottom show in a window of h lines. A negative top means no line to keep, so nothing moves. When the range is taller than the window, the top line wins, because it holds the heading of the cursor group. The caller runs fit next, which brings the offset back inside the bounds.

func (*ScrollState) Scrolls

func (sc *ScrollState) Scrolls() bool

Scrolls reports text that is taller than its window.

type TextArea

type TextArea struct {

	// Placeholder is the faint hint of an empty area. "" shows only the
	// cursor.
	Placeholder string
	// contains filtered or unexported fields
}

TextArea is a multi-line text input with soft wrap. enter inserts a line break, so a form leaves the area with another key, for example esc. The arrows, home and end, ctrl+a and ctrl+e, pgup and pgdown move the cursor. The zero value is an empty area.

func (*TextArea) Holds

func (a *TextArea) Holds(s string) bool

Holds reports whether the area can show and edit s exactly: it keeps every rune of s.

func (*TextArea) Key

func (a *TextArea) Key(msg tea.KeyMsg)

Key applies one key press. A paste arrives as one key with every rune. A terminal without bracketed paste sends a line break as enter or ctrl+j, and a tab as tab. So these keys insert their rune.

func (*TextArea) Notice

func (a *TextArea) Notice() string

Notice returns why the last input lost runes, or "". A form shows it under the area, because a dropped rune must be visible.

func (*TextArea) SetValue

func (a *TextArea) SetValue(s string)

SetValue replaces the text and puts the cursor at its end. A rune that the area cannot hold goes away, and Notice then says how many went away. A form checks a stored text with Holds first, because it must not change a text that the user did not edit.

func (*TextArea) Value

func (a *TextArea) Value() string

Value returns the text of the area.

func (*TextArea) View

func (a *TextArea) View(t *Theme, w, h int) string

View renders at most h rows of w cells. It scrolls the rows so that the cursor row shows, and it draws the cursor with the glyphs of LineInput (cursorView). A tab shows as spaces (MultiLine).

w must be at least 5 cells. A row always holds its first cluster, and a tab takes 4 cells plus 1 for the cursor. So a narrower view can hold a row wider than w. A form gives the area a far wider box.

type TextPager

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

TextPager scrolls one long text that a selection picks, for example the detail of a list row or the diff of a planned write. A new id starts at the top, because a new selection is a new text. The same id keeps the offset, so a refresh keeps the position.

The pager replaces a bubbles/viewport and keeps three of its rules, so every frame stays the same:

  • An empty text is one empty line, and the window has at least one row.
  • A line wider than the box loses its end without an ellipsis.
  • The offset moves back only when it passes the last line. After the box grows, the text can end above the bottom row. A down key then keeps the offset, and an up key moves to the last full page.

The scroll state is a named field and not an embedded one. A caller then cannot reach ScrollState.Key, which does not know the third rule.

func (*TextPager) Foot

func (p *TextPager) Foot(t *Theme) string

Foot returns span while the text is taller than its window, else "".

func (*TextPager) Key

func (p *TextPager) Key(msg tea.KeyMsg) bool

Key applies a movement key and reports whether the key was one. A down key keeps an offset past the bottom, which is the third rule of the type comment.

func (*TextPager) Lines

func (p *TextPager) Lines(id string, body []string, w, h int) []string

Lines records the bounds of body in a window of h rows and returns the visible lines, each cut to w cells.

func (*TextPager) Span

func (p *TextPager) Span(t *Theme) string

Span returns the faint "a–b of n" of the visible lines, also when every line fits, because a diff box of the 1a design shows it. It returns "" before the first render.

type Theme

type Theme struct {
	ASCII  bool
	Glyphs Glyphs

	Header     lipgloss.Style // the product name and the outer marks
	HeaderMark lipgloss.Style // the channel mark between the wedges
	Subtitle   lipgloss.Style
	TabActive  lipgloss.Style
	TabIdle    lipgloss.Style
	TabNum     lipgloss.Style
	Rule       lipgloss.Style // unfocused borders, rules, dimmed backdrop
	RuleOn     lipgloss.Style // focused borders, the active tab rule

	Title   lipgloss.Style // item titles
	Heading lipgloss.Style // upper-case section labels
	Body    lipgloss.Style
	Muted   lipgloss.Style // secondary text and labels
	Faint   lipgloss.Style // tertiary text, column headers, hints
	Accent  lipgloss.Style
	Key     lipgloss.Style // key names in hints
	Code    lipgloss.Style // selectable commands and paths
	Marked  lipgloss.Style // multi-selected rows

	Success   lipgloss.Style
	Attention lipgloss.Style
	Failure   lipgloss.Style
	Unknown   lipgloss.Style
	Info      lipgloss.Style

	Button lipgloss.Style // the label of a primary next action
	Ghost  lipgloss.Style // the label of a secondary next action
}

Theme holds the glyphs and styles of one session. Screens take every style from here so the console keeps one visual vocabulary.

func NewTheme

func NewTheme(ascii bool) *Theme

NewTheme builds the session theme. lipgloss downgrades the colors to the terminal profile and drops them under NO_COLOR, so the glyphs and labels carry every state on their own.

func (*Theme) ASCIIFrame

func (t *Theme) ASCIIFrame(s string) string

ASCIIFrame replaces the known Unicode symbols in a rendered frame when the session uses the ASCII glyph set. It is a safety net for literals that do not come from Glyphs, because a font without these symbols shows a replacement box. Escape sequences are ASCII, so the swap never changes a style.

func (*Theme) Action

func (t *Theme) Action(k, label string, primary bool) string

Action renders one next action with its key, for example "enter Apply". primary=true gives it the prominent style.

func (*Theme) Badge

func (t *Theme) Badge(tone Tone, label string) string

Badge renders a glyph and a text label in the tone color, for example "✓ current". The label keeps the meaning when color is off.

func (*Theme) Bar

func (t *Theme) Bar(n, total, w int, tone Tone) string

Bar renders a horizontal bar of w cells: the filled part in the tone color and the rest in the line color. The count beside it carries the value, so the bar is a visual aid only.

func (*Theme) Box

func (t *Theme) Box(o BoxOpts) string

Box renders a bordered pane of exactly W by H cells.

func (*Theme) Card

func (t *Theme) Card(w, h int, title, right string, lines []string) string

Card renders a summary card: a short box whose title is a dim upper-case label and whose right label carries the state.

func (*Theme) Cols

func (t *Theme) Cols(cells ...ColCell) string

Cols lays out cells in fixed-width columns. Each cell is clipped with an ellipsis and padded, so a table never wraps a cell.

func (*Theme) Columns

func (t *Theme) Columns(vals []int, h int, tone Tone) []string

Columns renders a column chart of h rows. Each value takes two cells with a one-cell gap. The top cell of a column uses an eighth-block glyph, so small differences stay visible at a low height.

func (*Theme) Empty

func (t *Theme) Empty(tone Tone, title, body, next string, w, h int) string

Empty renders a centered empty or error state: a title, an explanation, and the next valid action.

The title and the next action are the most important lines, so they stay visible when the block is taller than h. The body gives up its lines first, and its last kept line ends with an ellipsis. The next action is clipped only when it does not fit next to the title.

func (*Theme) Highlight

func (t *Theme) Highlight(row string, w, bg int) string

Highlight paints a background under a rendered row and pads it to w cells. The row keeps its own foreground styles: every reset inside it sets the background again, so the fill never breaks at a styled word.

func (*Theme) Hints

func (t *Theme) Hints(bindings []key.Binding) string

Hints renders key bindings as "key action" pairs for the footer.

Consecutive unavailable entries (see Unavailable) form one faint group that starts with the word n/a, for example "n/a: w write, v view". The word carries the state without color. One word for the group costs fewer cells than one word for each key.

func (*Theme) KeyHints

func (t *Theme) KeyHints(bindings []key.Binding) string

KeyHints renders every hint by its key alone, for example "space n i d - n/a: w t v". A footer uses it as the last step before it cuts an n/a entry, so every key stays in view; the help names the action of each key.

func (*Theme) KeyLabel

func (t *Theme) KeyLabel(k string) string

KeyLabel returns a key label in the session glyph set.

func (*Theme) Modal

func (t *Theme) Modal(o ModalOpts, sc *ScrollState, w, h int) string

Modal renders the modal of the 1a design. It draws a filled box with an accent border, a body that scrolls in sc, and the actions under a rule. It records the scroll bounds in sc, because a key handler cannot know the rendered height. The shell dims the frame and centers the block.

func (*Theme) MutedLines

func (t *Theme) MutedLines(lines []string) []string

MutedLines renders plain body lines in the muted style.

func (*Theme) Overlay

func (t *Theme) Overlay(base, block string, w, h int) string

Overlay places a rendered block on a dimmed copy of base, centered in w by h cells. The base keeps its text around the block, so the user still sees where the modal came from.

func (*Theme) PositionNote

func (t *Theme) PositionNote(first, last, total int) string

PositionNote returns the plain "a–b of n" position of a scrolled window. first and last are the 1-based visible rows, and total is the row count. Callers add the style and the words around it. The ASCII glyph set gets a plain hyphen, because a view that renders outside the shell skips the frame-wide ASCII swap.

func (*Theme) RangeNote

func (t *Theme) RangeNote(from, to, n int) string

RangeNote renders the faint "3–12 of 40" position of a scrolled window. from is the 0-based first row and to the end of the window, as the list offsets give them.

func (*Theme) ScrollBox

func (t *Theme) ScrollBox(o BoxOpts, body, tail []string, sc *ScrollState, keep [2]int, follow bool) string

ScrollBox renders body lines in a box that scrolls in sc, with the tail lines always visible under the body. When follow is set, the window moves so that the lines keep[0] to keep[1] show, for example the cursor group and its detail lines. A box that scrolls shows its position in the bottom border.

func (*Theme) ScrollNote

func (t *Theme) ScrollNote(offset, window, n, w int) string

ScrollNote renders the "a–b of n" position of a scrolling window, right-aligned, so hidden rows are never a surprise.

func (*Theme) ShortHints

func (t *Theme) ShortHints(bindings []key.Binding) string

ShortHints renders the hints as Hints does, but each n/a group shows only its keys, for example "n/a: w t v". A footer that cannot hold every hint uses it, so the unavailable keys stay in view at a cost of two cells for each key.

func (*Theme) SpinnerFrame

func (t *Theme) SpinnerFrame(tick int) string

SpinnerFrame returns the activity glyph for a tick count. The count comes from state.tick, the one injectable tick of the shell, so the console does not use bubbles/spinner (input.go gives the reasons).

func (*Theme) StickyBox

func (t *Theme) StickyBox(o BoxOpts, head, body, tail []string, sc *ScrollState, keep [2]int, follow bool) string

StickyBox is ScrollBox with head lines that stay above the body, for example the headline of a long operation. Only the body scrolls, and keep counts body lines. Several screens share it, so every scrolling box keeps the same rules.

func (*Theme) ToneGlyph

func (t *Theme) ToneGlyph(tone Tone) string

ToneGlyph returns the glyph of a semantic tone.

func (*Theme) ToneStyle

func (t *Theme) ToneStyle(tone Tone) lipgloss.Style

ToneStyle returns the style of a semantic tone.

type Tone

type Tone int

Tone is the semantic state of a value. Every tone has a glyph and a text label as well as a color, because color alone must never carry meaning (NO_COLOR, monochrome terminals, color vision).

const (
	// ToneNeutral is plain information.
	ToneNeutral Tone = iota
	// ToneSuccess is a current or healthy state.
	ToneSuccess
	// ToneAttention is an actionable problem, a pending decision, or a
	// stale state.
	ToneAttention
	// ToneFailure is a broken state or a failed operation.
	ToneFailure
	// ToneUnknown is missing data. It is never shown as success.
	ToneUnknown
	// ToneAccent marks the primary action or the active destination.
	ToneAccent
	// ToneUnsupported marks a capability that the console does not provide.
	ToneUnsupported
)

Jump to

Keyboard shortcuts

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