theme

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: May 18, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package theme provides the theme registry and style-atom system for Hygge's terminal UI.

Shell-default philosophy

The built-in "shell" theme assigns each style atom to a numbered slot in the terminal's ANSI 16/256-color palette. It never hard-codes RGB values; the actual hues are whatever the user has configured in their terminal emulator. This means Hygge "inherits" the user's chosen terminal color scheme for free, without requiring a separate theme file.

Atom contract

A style atom is a named, logical surface (e.g. "primary", "code.bg"). The full set of v0.1 atoms is locked: adding or removing atoms requires its own task. Every theme — builtin or user-supplied — must declare every atom. There is intentionally no fallback inheritance from the shell theme; if a user writes a custom theme they must be explicit about every surface.

Background vs. foreground semantics are encoded in the atom name:

  • Atoms ending in ".bg" are applied as Background colours.
  • All other atoms (bare names or ".fg" suffix) are applied as Foreground colours.

Loading

Call Load to resolve a theme by name. Builtin themes are returned without disk I/O. User themes live at ~/.config/hygge/themes/<name>.toml.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrThemeNotFound is returned when the requested theme name is not a
	// builtin and no matching file exists on disk.
	ErrThemeNotFound = errors.New("theme not found")

	// ErrInheritCycle is returned when an "inherit:<atom>" chain forms a
	// cycle or exceeds maxInheritDepth.
	ErrInheritCycle = errors.New("inherit cycle detected")
)

Sentinel errors returned by this package.

Functions

func FormatTheme

func FormatTheme(t *Theme) string

FormatTheme returns a multi-line string showing every atom and its resolved color form. Used by `hygge theme show` (Task 13).

Example output:

theme: shell
  primary        = ansi:4
  code.bg        = (default)

func KnownNames

func KnownNames(opts LoadOptions) []string

KnownNames returns builtin and user theme names available to Load.

func SaturationBoost

func SaturationBoost(c color.Color) color.Color

SaturationBoost returns a more vivid version of c for use as a border color on a tinted background.

  • ansi.BasicColor 0-7 → bright equivalent 8-15 (e.g. 4 → 12, 5 → 13)
  • ansi.BasicColor 8-15 → unchanged (already bright)
  • ansi.IndexedColor (256-color 16-255) → unchanged (no safe boost defined)
  • color.RGBA (from hex) → parse via go-colorful, increase HSL saturation by 0.2 clamped to 1.0, re-emit as hex.

If the input cannot be interpreted (nil, no-color, unknown type), it is returned as-is.

Currently unused by bubble.go — border color is the configured atom directly. Reserved for future per-agent color customization where a saturation-boosted variant may be desirable for contrast on tinted surfaces.

Types

type Atom

type Atom string

Atom is the canonical identifier for a styleable surface.

const (
	AtomPrimary     Atom = "primary"
	AtomAccent      Atom = "accent"
	AtomMuted       Atom = "muted"
	AtomSuccess     Atom = "success"
	AtomWarn        Atom = "warn"
	AtomError       Atom = "error"
	AtomCodeBg      Atom = "code.bg"
	AtomCodeFg      Atom = "code.fg"
	AtomDiffAddBg   Atom = "diff.add.bg"
	AtomDiffDelBg   Atom = "diff.del.bg"
	AtomStatusBarBg Atom = "statusbar.bg"
	AtomStatusBarFg Atom = "statusbar.fg"
	AtomModalBg     Atom = "modal.bg"
	AtomModalBorder Atom = "modal.border"

	// Bubble-specific atoms introduced in Phase 1 of the chat-bubble redesign.
	// The accent color for bubble borders defaults to a slightly muted version
	// of the terminal accent.  Future per-agent-mode theming will override
	// AccentColor at the call site; these atoms provide the session-level default.
	AtomBubbleBorder         Atom = "bubble.border"          // default bubble border (≈ accent, slightly muted)
	AtomBubbleBorderDistinct Atom = "bubble.border.distinct" // SubStyle=Distinct bubble border (≈ muted)
	AtomBubbleHeader         Atom = "bubble.header"          // bubble header accent (matches accent)
	AtomBubbleHeaderMuted    Atom = "bubble.header.muted"    // bubble right-side header muted text
	AtomBubbleBodyMuted      Atom = "bubble.body.muted"      // muted body text (thinking in Phase 2)
	AtomBubbleBg             Atom = "bubble.bg"              // subtle hover-like fill behind every bubble

	// Phase 5: distinct border colors for user vs agent bubbles.
	// AtomBubbleUserBorder is the border/accent for user (right-aligned) bubbles.
	// AtomBubbleAgentBorder is the border/accent for assistant (left-aligned) bubbles.
	// Both are seams for per-agent-mode customisation; AtomBubbleAgentBorder
	// will be overridden per agent session once per-agent theming lands.
	AtomBubbleUserBorder  Atom = "bubble.user.border"  // user bubble border (default: blue / ANSI 4)
	AtomBubbleAgentBorder Atom = "bubble.agent.border" // agent bubble border (default: magenta / ANSI 5)

	// Sidebar atoms (right-side panel added in the sidebar phase).
	// AtomSidebarBorder   — left-side divider color.
	// AtomSidebarSection  — section header label (muted, bold).
	// AtomSidebarValue    — value text (default: terminal fg).
	// AtomSidebarAccent   — accent dot and version glyph.
	// AtomSidebarMuted    — muted text such as "None" or "—".
	// AtomSidebarBg       — subtle hover-like fill behind the whole sidebar column.
	AtomSidebarBorder  Atom = "sidebar.border"  // left-border divider color (default: ANSI 8)
	AtomSidebarSection Atom = "sidebar.section" // section header label (default: ANSI 7)
	AtomSidebarValue   Atom = "sidebar.value"   // value text (default: terminal fg)
	AtomSidebarAccent  Atom = "sidebar.accent"  // accent dot/glyph (default: same as AtomAccent)
	AtomSidebarMuted   Atom = "sidebar.muted"   // muted/empty state text (default: ANSI 7)
	AtomSidebarBg      Atom = "sidebar.bg"      // sidebar fill background (default: ANSI 235)
)

The following constants are the locked v0.1 style atom identifiers. Callers should use these constants rather than bare string literals.

func AllAtoms

func AllAtoms() []Atom

AllAtoms returns the locked list of v0.1 style atoms in stable order. The slice is a copy; callers may not modify it.

type Color

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

Color is an abstract color reference resolved at Style() call time. The zero value represents "no color" (terminal default).

func (Color) IsDefault

func (c Color) IsDefault() bool

IsDefault reports whether this Color means "use the terminal default" (empty-string case).

func (Color) String

func (c Color) String() string

String returns a human-readable description suitable for FormatTheme output.

type ErrIncompleteTheme

type ErrIncompleteTheme struct {
	Missing []Atom
}

ErrIncompleteTheme is returned when a parsed theme file is missing one or more atoms from AllAtoms().

func (*ErrIncompleteTheme) Error

func (e *ErrIncompleteTheme) Error() string

type ErrInvalidColor

type ErrInvalidColor struct {
	Atom  Atom
	Value string
}

ErrInvalidColor is returned when a color value string is not in any recognized form.

func (*ErrInvalidColor) Error

func (e *ErrInvalidColor) Error() string

type ErrUnknownAtom

type ErrUnknownAtom struct {
	Atoms []Atom
}

ErrUnknownAtom is returned when a theme file contains keys that are not in AllAtoms().

func (*ErrUnknownAtom) Error

func (e *ErrUnknownAtom) Error() string

type LoadOptions

type LoadOptions struct {
	// ConfigHome overrides $XDG_CONFIG_HOME; "" uses the real environment.
	ConfigHome string

	// HomeDir overrides $HOME; "" uses the real home directory.
	HomeDir string
}

LoadOptions controls theme loading.

type Theme

type Theme struct {
	Name   string
	Colors map[Atom]Color
}

Theme is a fully-resolved theme: every atom maps to a Color.

func Load

func Load(themeName string, opts LoadOptions) (*Theme, error)

Load returns the theme named by themeName, looking up:

  1. Builtin themes (currently: "shell")
  2. ~/.config/hygge/themes/<name>.toml

If themeName is "" or "shell", returns the shell theme without disk I/O. Returns ErrThemeNotFound if the name is not builtin and not on disk.

func ShellTheme

func ShellTheme() *Theme

ShellTheme returns the builtin shell-palette theme.

Every atom maps to a numbered slot in the terminal's ANSI palette. No RGB values are hard-coded; the actual hues depend on the user's terminal emulator color scheme. An empty raw string means "no override" — the terminal's default background or foreground carries through.

func (*Theme) BlockStyle

func (t *Theme) BlockStyle(fg, bg Atom) lipgloss.Style

BlockStyle returns a lipgloss.Style that has both Foreground and Background set, combining a foreground atom and a background atom. This is a convenience for callers that need both in one style (e.g. "code").

If either atom's color is default or resolution fails, that attribute is left unset.

func (*Theme) Style

func (t *Theme) Style(a Atom) lipgloss.Style

Style returns a lipgloss.Style for the given atom.

Background atoms (.bg suffix) apply Background(); all others apply Foreground(). If the atom's color is the empty/default kind, the returned style has neither attribute set (the terminal default carries through).

Inherit chains are resolved on every call. If resolution fails (cycle or missing atom) a blank style is returned and the error is silently dropped — the caller receives a workable (blank) style rather than a panic.

Jump to

Keyboard shortcuts

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