theme

package
v0.0.28 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package theme is the pure styling layer for mecatui. It owns the semantic colour palette, the derived lipgloss styles, and the glamour markdown style config — and nothing else. It imports only the charm styling libraries and stdlib: NO contracts/gen, NO grpc, NO mecatui/ui, NO internal/... packages. This keeps the visual language reusable and the architectural layering clean (ui depends on theme; theme depends on nobody in this repo).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Palette

type Palette struct {
	// Brand / structural accents.
	Primary   string `json:"primary"`
	Secondary string `json:"secondary"`
	Accent    string `json:"accent"`

	// Surfaces (backgrounds), darkest to lightest.
	Bg        string `json:"bg"`
	BgPanel   string `json:"bgPanel"`
	BgElement string `json:"bgElement"`

	// Borders.
	Border       string `json:"border"`
	BorderActive string `json:"borderActive"`
	BorderSubtle string `json:"borderSubtle"`

	// Foreground text.
	Text      string `json:"text"`
	TextMuted string `json:"textMuted"`

	// In-app text-selection highlight background. Empty ⇒ derived from Accent.
	// The foreground is NOT a palette slot: it is computed from this background's
	// relative luminance (see contrastingText) so the block is legible on any
	// theme, dark or light.
	Selection string `json:"selection"`

	// Status colours.
	Success string `json:"success"`
	Warning string `json:"warning"`
	Error   string `json:"error"`
	Info    string `json:"info"`

	// Speaker / block roles.
	User      string `json:"user"`
	Assistant string `json:"assistant"`
	Tool      string `json:"tool"`

	// Markdown slots (glamour body styling).
	MdText    string `json:"mdText"`
	MdHeading string `json:"mdHeading"`
	MdLink    string `json:"mdLink"`
	MdCode    string `json:"mdCode"`
	MdQuote   string `json:"mdQuote"`

	// Syntax-highlight slots (glamour code-block chroma).
	SynComment     string `json:"synComment"`
	SynKeyword     string `json:"synKeyword"`
	SynFunction    string `json:"synFunction"`
	SynVariable    string `json:"synVariable"`
	SynString      string `json:"synString"`
	SynNumber      string `json:"synNumber"`
	SynType        string `json:"synType"`
	SynOperator    string `json:"synOperator"`
	SynPunctuation string `json:"synPunctuation"`
}

Palette is the raw, semantic colour set a theme is defined by. Every field is a hex string ("#rrggbb"). Themes are authored (in Go or JSON) purely as a Palette; the lipgloss styles and the glamour StyleConfig are derived from it in compile(). The slots are semantic (what a colour means) rather than literal (what colour it is), so a new theme only has to answer "what is my accent?", not restyle every widget.

func AztecPalette

func AztecPalette() Palette

AztecPalette returns a copy of the built-in Aztec palette. Exposed so load.go (and tests) can use it as the merge base for partial user themes.

type Registry

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

Registry holds a set of themes by name and answers Get/List/Default. main.go builds one (built-ins + any loaded user themes) and hands the resolved Theme to the ui. Keeping registration in an instance (rather than a global) keeps tests isolated and the package free of init-order surprises.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns a registry seeded with the built-in themes.

func (*Registry) Default

func (r *Registry) Default() Theme

Default returns the Aztec theme — the guaranteed-present fallback.

func (*Registry) Get

func (r *Registry) Get(name string) (Theme, bool)

Get returns the theme for name and whether it was found. Lookup is case-insensitive (keys are stored lowercase), so "--theme Aztec" resolves.

func (*Registry) List

func (r *Registry) List() []string

List returns the sorted names of all registered themes (for a --list-themes affordance or a runtime /theme picker).

func (*Registry) LoadDir

func (r *Registry) LoadDir(dir string) error

LoadDir loads every *.json theme in dir and registers it in r, merging each partial palette over the Aztec base so partial themes are complete. Missing dirs are not an error (the dir hierarchy is best-effort). Per-file parse errors are collected and returned joined, but valid files still register.

func (*Registry) Register

func (r *Registry) Register(t Theme)

Register adds or replaces a theme by its (lowercased-by-caller) name. User JSON themes are registered here, overriding a built-in of the same name.

func (*Registry) Resolve

func (r *Registry) Resolve(name string) (Theme, bool)

Resolve returns the named theme, or the default if name is empty/unknown, plus whether the requested name was actually found. This is the one call main.go needs: "give me what the user asked for, but never fail".

type Theme

type Theme struct {
	Name    string
	Palette Palette
	// contains filtered or unexported fields
}

Theme is a named Palette plus its derived, ready-to-use styles. Construct one with New (which calls compile); never build the styles map by hand.

func LoadFile

func LoadFile(path string) (Theme, error)

LoadFile parses a single theme JSON file, merges its partial palette over the Aztec base, and returns the compiled Theme. The name defaults to the file's base name (sans .json) when the JSON omits "name". The name is lowercased so lookups are case-insensitive at the boundary.

func New

func New(name string, p Palette) Theme

New builds a Theme from a name and palette, compiling the derived styles. It is the only constructor: it guarantees the styles map is populated so Style() never returns a zero value for a known slot.

func ParseTheme

func ParseTheme(raw []byte) (Theme, error)

ParseTheme parses theme JSON bytes and returns the compiled Theme with the partial palette merged over Aztec. Exposed (and base of LoadFile) so tests can exercise the round-trip and merge without touching the filesystem.

func Solar added in v0.0.23

func Solar() Theme

Solar returns the built-in "solar" theme — the light-leaning variant used as the automatic fallback when the terminal reports a light background (ADR 0280) and no explicit theme was requested. It always returns the built-in, never a user override registered under the same name, so the auto-detect outcome is predictable regardless of --theme-dir contents.

func (Theme) Color

func (t Theme) Color(slot string) color.Color

Color returns the color.Color for a semantic slot name (e.g. "accent", "error", "user"). Unknown slots return nil (terminal default). The lookup is by the palette's JSON field name so callers and JSON authors share one vocabulary.

func (Theme) GlamourStyle

func (t Theme) GlamourStyle() ansi.StyleConfig

GlamourStyle maps the theme's semantic slots onto a glamour ansi.StyleConfig for markdown rendering. It is built from scratch (the glamour styles package in v2 ships only ASCII/Dracula/TokyoNight, no neutral DarkStyleConfig to clone), so every colour is driven by the palette — this is what makes the markdown obey the active theme. Code-block syntax colours come from the syntax* slots via the Chroma config.

func (Theme) MarshalJSON

func (t Theme) MarshalJSON() ([]byte, error)

MarshalJSON emits a theme as the on-disk fileTheme shape (name + full palette). Used by tests for the round-trip and handy for a "dump current theme" affordance.

func (Theme) Style

func (t Theme) Style(name string) lipgloss.Style

Style returns the derived lipgloss.Style for a named UI element. Known names: header, footer, viewport, userBlock, userLabel, assistantLabel, toolCard, toolName, toolArgs, toolOk, toolErr, askCard, askTitle, askArgs, askButton, askButtonActive, spinner, muted, warning, dangerPill, errorText. Unknown names return an empty style so callers degrade gracefully rather than panic.

Jump to

Keyboard shortcuts

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