Summary
Define and implement a distinctive visual identity for Nibble: a charcoal grey base with a metallic green accent. The goal is a palette that is immediately recognisable as Nibble, looks polished in any terminal, and feels different from the inherited Charmtone Pantera defaults.
Motivation
Nibble currently uses the Charmtone Pantera palette, which is a great general-purpose dark theme but carries no Nibble-specific identity. As the project grows, having a signature look — one that any user instantly associates with Nibble — becomes important for brand recognition and user experience.
The chosen direction: deep charcoal backgrounds + metallic/sage green primary — a combination that reads as precise, technical, and distinctive without being aggressive or hard on the eyes.
Proposed Palette
Backgrounds (charcoal scale)
| Token | Hex | Role |
|---|---|---|
bgBase |
#1A1D1A |
Main background — near-black with a green tint |
bgLeastVisible |
#1F231F |
Subtle surface elevation |
bgLessVisible |
#252A25 |
Panel / sidebar backgrounds |
bgMostVisible |
#2E342E |
Active element / selected row backgrounds |
separator |
#2A302A |
Dividers and rule lines |
Foregrounds (cool grey scale)
| Token | Hex | Role |
|---|---|---|
fgBase |
#D4D9D4 |
Primary text — slightly warm grey |
fgSubtle |
#8A9A8A |
Secondary / dimmed labels |
fgMoreSubtle |
#5A6A5A |
Placeholder text, hints |
fgMostSubtle |
#3A4A3A |
Ghost / disabled text |
Brand (metallic green scale)
| Token | Hex | Role |
|---|---|---|
primary |
#4CAF78 |
Main accent — vibrant metallic green |
secondary |
#7EC8A0 |
Highlights, links, secondary labels |
accent |
#2D7A52 |
Focused borders, active indicators |
keyword |
#A8D5B8 |
Syntax keywords, special tokens |
onPrimary |
#0D1A12 |
Text on green backgrounds |
Status colours
| Token | Hex | Role |
|---|---|---|
success |
#4CAF78 |
Same as primary — completion, OK |
successMoreSubtle |
#2D7A52 |
Dimmed success |
successMostSubtle |
#1A4A32 |
Ghost success |
info |
#64B5C8 |
Informational messages |
warning |
#C8A84B |
Warnings |
error |
#C85050 |
Errors |
destructive |
#A03A3A |
Destructive actions |
busy |
#8AC878 |
Spinner, in-progress |
denied |
#C8784B |
Denied permissions |
Implementation
Following the pattern established in themes.go, add a new NibbleCharcoal() function:
`go
// NibbleCharcoal returns the official Nibble theme:
// deep charcoal backgrounds with metallic green accents.
func NibbleCharcoal() Styles {
s := quickStyle(quickStyleOpts{
primary: lipgloss.Color("#4CAF78"),
secondary: lipgloss.Color("#7EC8A0"),
accent: lipgloss.Color("#2D7A52"),
keyword: lipgloss.Color("#A8D5B8"),
fgBase: lipgloss.Color("#D4D9D4"),
fgSubtle: lipgloss.Color("#8A9A8A"),
fgMoreSubtle: lipgloss.Color("#5A6A5A"),
fgMostSubtle: lipgloss.Color("#3A4A3A"),
onPrimary: lipgloss.Color("#0D1A12"),
bgBase: lipgloss.Color("#1A1D1A"),
bgLeastVisible: lipgloss.Color("#1F231F"),
bgLessVisible: lipgloss.Color("#252A25"),
bgMostVisible: lipgloss.Color("#2E342E"),
separator: lipgloss.Color("#2A302A"),
success: lipgloss.Color("#4CAF78"),
successMoreSubtle: lipgloss.Color("#2D7A52"),
successMostSubtle: lipgloss.Color("#1A4A32"),
info: lipgloss.Color("#64B5C8"),
infoMoreSubtle: lipgloss.Color("#3A7A8A"),
infoMostSubtle: lipgloss.Color("#1A3A42"),
warning: lipgloss.Color("#C8A84B"),
warningSubtle: lipgloss.Color("#8A7030"),
error: lipgloss.Color("#C85050"),
destructive: lipgloss.Color("#A03A3A"),
busy: lipgloss.Color("#8AC878"),
denied: lipgloss.Color("#C8784B"),
})
return s
}
`
Then wire it as the default in ThemeForProvider:
go func ThemeForProvider(providerID string) Styles { switch ThemeKeyForProvider(providerID) { case "hyper": return HypercrushObsidiana() default: return NibbleCharcoal() // replaces CharmtonePantera } }
Design Validation Checklist
- All foreground / background token pairs meet WCAG AA contrast (4.5:1 minimum)
- Theme looks correct in both 256-colour and truecolour terminals
- ANSI 16-colour fallback palette maps sensibly to the green/charcoal scale
- Syntax highlighting (Chroma) colours are reviewed against the new background
- Screenshots / catwalk snapshots updated
Notes
- The existing
CharmtonePantera()should be kept as a named theme (not deleted) so users who preferred it can restore it via config in the future - Golden file snapshots under
internal/uiwill need to be regenerated withgo test ./... -updateafter the change - Consider adding a
themeoption tonibble.jsonto allow users to choose between themes explicitly