1
1
Fork
You've already forked kurama
0

feat: Nibble theme — charcoal & metallic green visual identity #16

Closed
opened 2026年07月10日 14:45:48 +02:00 by andeerc · 1 comment

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/ui will need to be regenerated with go test ./... -update after the change
  • Consider adding a theme option to nibble.json to allow users to choose between themes explicitly
## 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`](https://codeberg.org/andeerc/nibble/src/branch/main/internal/ui/styles/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/ui` will need to be regenerated with `go test ./... -update` after the change - Consider adding a `theme` option to `nibble.json` to allow users to choose between themes explicitly
Author
Owner
Copy link

Implementada com a conversão para a kurama

Implementada com a conversão para a kurama
Sign in to join this conversation.
No Branch/Tag specified
main
v1.0.4
v1.0.2
v1.0.1
v1.0.0
v0.1.4
v0.1.3
v0.1.2
v0.1.1
v0.0.3
v0.0.2
v0.0.1
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
andeerc/kurama#16
Reference in a new issue
andeerc/kurama
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?