Theme the output¶
The progress-family renderers (Status, Progress, Spin) draw their icons,
colours, spinner frames and bar runes from a Theme. Override it with
WithTheme to match your tool's palette.
The default¶
DefaultTheme() provides check / warning / cross icons, a magenta braille
spinner, and an ASCII progress bar:
A custom theme¶
Start from the default and change only what you need:
th := output.DefaultTheme()
th.SuccessIcon = "✔"
th.FailIcon = "✖"
th.SpinnerFrames = []string{"◐", "◓", "◑", "◒"}
th.ProgressFilled = '█'
th.ProgressEmpty = '░'
th.ProgressHead = 0 // 0 → reuse ProgressFilled for the leading edge
r := output.New(output.WithWriter(os.Stderr), output.WithTheme(th))
Theme fields¶
| Field | Used by |
|---|---|
SuccessIcon / WarnIcon / FailIcon |
Status.Success / .Warn / .Fail |
SuccessStyle / WarnStyle / FailStyle |
the lipgloss style of the finalised line |
SpinnerStyle |
spinner frames (Spin, and Status.Update) |
SpinnerFrames |
the animation frame set — see an empty frame set |
ProgressFilled / ProgressEmpty / ProgressHead |
the progress-bar runes |
Styles are lipgloss.Style values, so any lipgloss styling (foreground,
background, bold, …) applies.
What happens if SpinnerFrames is empty¶
The two consumers of SpinnerFrames do different things when it is empty,
which matters if you build a Theme from scratch rather than starting from
DefaultTheme():
Spinsubstitutes the built-inbubblesdot spinner, so the animation still runs.Status.Updaterenders a single space as the working icon — no dot, no animation. The message still appears; the icon column is blank.
If you want both to animate, set at least one frame.
Does the renderer turn colour off when it is not interactive?¶
No. WithInteractive(false) changes layout — no in-place redraw, no
animation, plain sequential lines — but it does not change styling. A
Status.Success call renders its icon through SuccessStyle in both modes, so
a non-interactive run still emits the ANSI colour sequence:
The NO_COLOR and TERM=dumb conventions are not consulted either. If your
tool needs a --no-color switch, implement it by passing a theme whose styles
carry no colour:
plain := output.DefaultTheme()
for _, s := range []*lipgloss.Style{
&plain.SuccessStyle, &plain.WarnStyle, &plain.FailStyle, &plain.SpinnerStyle,
} {
*s = lipgloss.NewStyle()
}
r := output.New(output.WithWriter(os.Stderr), output.WithTheme(plain))
An unstyled lipgloss.Style renders its input unchanged, so this produces
icons and messages with no escape sequences at all.