Bubbletint

repository·master·Indexed 41 days ago

https://github.com/lrstanley/bubbletint

A Go library providing 340+ color palettes (tints) inspired by iTerm2-Color-Schemes for building terminal user interfaces (TUIs). It supports dynamic theme management via a Registry system, integrates with the color.Color interface and lipgloss, and includes a chromatint package for bridging styles to Chroma. It also provides the tintgen CLI to generate Go source files and web assets from theme JSON definitions.

Tokens
8.1K
Snippets
23
Records
26
Agent score
100%

What's inside Bubbletint

  1. How bubbletint usage modes work

    master

    Bubbletint provides three ways to manage and access color palettes (tints):

    1. Global Registry: A singleton approach where you initialize a default registry and set a global tint. This is useful for applications where you want to change the theme globally without passing state through every component.
    2. Custom Registry: An instance-based approach where you create a specific Registry containing a subset of tints. This allows for better encapsulation and is ideal if different parts of your application need different sets of available themes.
    3. Specific Tints: The simplest approach where you bypass registries entirely and use the exported Tint structs directly for static styling.
  2. Define credits for a Tint

    master

    The credits field in the meta object accepts either a single CreditSource object or an array of CreditSource objects. This allows for flexible attribution in JSON templates.

    type CreditSource struct {
    	Name string `json:"name" validate:"required"`
    	Link string `json:"link" validate:"required,url"`
    }
  3. Serialize and deserialize tints with JSON

    master

    Tints are fully JSON serializable.

    • Unmarshalling: Supports both RGBA objects and hex strings. Hex strings are recommended for end-user ease of use.
      • RGBA format: {"r": 255, "g": 0, "b": 0, "a": 255}
      • Hex format: "#ff0000"
    • Marshalling: Tints are marshalled as RGBA objects to preserve the alpha channel (which defaults to 255 for built-in tints).
  4. Initialize the DefaultRegistry

    master

    The DefaultRegistry is an app-wide registry that holds a collection of pre-configured tints. To populate it with all available default tints, call NewDefaultRegistry().

    Note: You should call this during your application's initialization phase before any other part of your app attempts to use the registry. While DefaultRegistry can be overridden, doing so after initialization may lead to inconsistent behavior.

    package main
    
    import "github.com/lrstanley/lrstanley/bubbletint/v2"
    
    func init() {
    	// Initialize the global registry with all default tints
    	tint.NewDefaultRegistry()
    }
  5. Integrate with Chroma via chromatint

    master

    The chromatint/v2 sub-package allows you to map bubbletint's color palettes to chroma.StyleEntries. This is useful for rendering syntax-highlighted code using a specific bubbletint theme.

    import "github.com/lrstanley/bubbletint/chromatint/v2"
  6. Use a Custom Registry

    master

    Use a Registry instance when you want to control exactly which tints are available and manage theme state locally. You can register additional tints at runtime and paginate through available tints using NextTint() and PreviousTint().

    package main
    
    import (
    	"github.com/lrstanley/bubbletint/v2"
    	"github.com/charmbracelet/lipgloss"
    )
    
    func main() {
    	theme := tint.NewRegistry(
    		int.TintDraculaPlus,
    		int.TintCatppuccinFrappe,
    		int.TintCatppuccinMocha,
    		int.TintMonokaiPro,
    		int.TintTinaciousDesignDark,
    	)
    
    	theme.Register(tint.TintNord) // Add more tints
    	theme.SetTint(tint.TintNord)  // Set active tint
    	theme.NextTint()              // Paginate
    
    	style := lipgloss.NewStyle().
    		SetForeground(theme.Current().Fg).
    		Background(theme.Current().BrightGreen)
    }
  7. Use the Global Registry

    master

    The Global Registry allows you to manage a single theme state across your entire application. You must initialize it with tint.NewDefaultRegistry() before use.

    You can set the active tint using either the exported Tint constant or by its string ID via tint.SetTintID().

    package main
    
    import (
    	"github.com/lrstanley/bubbletint/v2"
    	"github.com/charmbracelet/lipgloss"
    )
    
    func main() {
    	int.NewDefaultRegistry()
    	int.SetTint(tint.TintDraculaPlus) // Set by constant
    	int.SetTintID("dracula_plus")   // Or by ID
    
    	// Access the current tint via tint.Current()
    	style := lipgloss.NewStyle().
    		SetForeground(tint.Current().Fg).
    		Background(tint.Current().BrightGreen)
    }
  8. Use specific tints directly

    master

    If you don't need dynamic theme switching or registries, you can use the exported Tint variables directly to style components.

    package main
    
    import (
    	"github.com/lrstanley/bubbletint/v2"
    	"github.com/charmbracelet/lipgloss"
    )
    
    var (
    	// Using a specific tint constant directly
    	statusbarStyle = lipgloss.NewStyle().
    		SetForeground(tint.TintDraculaPlus.Fg).
    		Background(tint.TintDraculaPlus.BrightGreen)
    
    	// Or assigning a tint to a variable
    	theme = tint.TintDraculaPlus
    	style = lipgloss.NewStyle().
    		SetForeground(theme.Fg).
    		Background(theme.BrightGreen)
    )
  9. Use the Color type for RGBA and Hex colors

    master

    The Color struct represents an RGBA color and implements the standard Go color.Color interface. It can be used in any context expecting a color.Color.

    Key features:

    • RGBA fields: R, G, B, and A are all uint8 values.
    • Hex conversion: Use Hex() to get a #RRGGBB string representation.
    • JSON flexibility: When unmarshaling JSON, Color supports both an RGBA object (e.g., {"r": 255, "g": 0, "b": 0, "a": 255}) and a hex string (e.g., "#ff0000").
    ```go
    // Example of creating a color and using its methods
    color := tint.Color{R: 255, G: 0, B: 0, A: 255}
    
    // Get RGBA values for standard library compatibility
    r, g, b, a := color.RGBA()
    
    // Get hex string
    hexStr := color.Hex() // returns "#ff0000"
    ```埋
  10. Set and navigate the current active tint

    master

    The default registry maintains a pointer to a 'current' tint. You can set the active tint directly or navigate through the registered tints using alphabetical ID order.

    Setting the Active Tint

    • SetTint(tint *Tint): Sets the current tint. If the tint is not already registered, it is added to the registry. Note: This panics if the provided tint is nil.
    • SetTintID(id string) (ok bool): Sets the current tint to the one matching the provided ID. Returns false if the ID is not found.
    • Current() *Tint: Returns the currently active tint. Note: This panics if no tint has been set and the registry has no registered tints to fall back to.

    Navigation follows the alphabetical order of the registered tint IDs:

    • NextTint(): Moves the current tint to the next one in the sorted list. If the current tint is the last one, it stays on the last one.
    • PreviousTint(): Moves the current tint to the previous one in the sorted list. If the current tint is the first one, it stays on the first one.
    // Set a tint directly
    tint.SetTint(myTint)
    
    // Or set by ID
    if ok := tint.SetTintID("forest-green"); !ok {
        // handle error
    }
    
    // Navigate through tints
    tint.NextTint()
    tint.PreviousTint()
    
    // Get the active tint
    active := tint.Current()
  11. Manage registered tints in a Registry

    master

    The Registry manages a collection of *Tint objects. You can add, remove, or list them using the following methods:

    • Register(...*Tint): Adds one or more tints to the registry. This does not change the currently active tint.
    • Unregister(...*Tint): Removes specific tint instances from the registry.
    • UnregisterIDs(...string): Removes tints based on their unique ID strings.
    • UnregisterAll(): Clears all tints from the registry.
    • Tints(): Returns a slice of all registered *Tint objects, sorted alphabetically by their ID.
    • TintIDs(): Returns a slice of all registered tint IDs, sorted alphabetically.
    r := tint.NewRegistry(nil)
    
    r.Register(myTint1, myTint2)
    r.UnregisterIDs("tint-id-123")
    
    allTints := r.Tints()
    allIDs := r.TintIDs()