Bubbles

repository·main·Indexed 27 days ago

https://github.com/charmbracelet/bubbles

A collection of UI components (primitives) designed for the Bubble Tea TUI framework. It provides ready-to-use elements such as text inputs, lists, tables, spinners, progress meters, viewports, and file pickers to accelerate terminal application development. The library includes a Key component for managing keybindings and a Help component for generating help text.

Tokens
4.5K
Snippets
8
Records
25
Agent score
92%

What's inside bubbles

  1. Overview of Bubbles components

    main

    Bubbles provides UI primitives for Bubble Tea applications. It includes a variety of pre-built components for common terminal interface tasks such as input, navigation, and data display.

    Available components include:

    • Spinner: Indicates ongoing operations.
    • Text Input: Single-line text field.
    • Text Area: Multi-line text field.
    • Table: Displays tabular data (rows and columns).
    • Progress: Customizable progress meters (supports animation via Harmonica).
    • Paginator: Handles pagination logic and UI (dot-style or numeric).
    • Viewport: Vertically scrolling content with optional pager keybindings.
    • List: A feature-rich component for browsing items with fuzzy filtering and pagination.
    • File Picker: For navigating and selecting files from the file system.
    • Timer & Stopwatch: Components for counting down or up.
    • Help: A horizontal view that automatically generates help text from keybindings.
    • Key: A non-visual component for managing and matching keybindings.
  2. Handle Light and Dark Styles in Bubbles v2

    main

    Bubbles v2 no longer uses AdaptiveColor to auto-detect terminal backgrounds. You must explicitly provide light or dark styles to components.

    Use tea.RequestBackgroundColor to detect the background color from the terminal/client (especially important for Wish).

    func (m model) Init() tea.Cmd {
        return tea.RequestBackgroundColor
    }
    
    func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
        switch msg := msg.(type) {
        case tea.BackgroundColorMsg:
            isDark := msg.IsDark()
            m.help.Styles = help.DefaultStyles(isDark)
            m.list.Styles = list.DefaultStyles(isDark)
        }
        return m, nil
    }

    Quick: Use compat Package

    If you need a quick check (note: this uses blocking I/O and may not work correctly over SSH/remote clients):

    import "charm.land/lipgloss/v2/compat"
    
    var isDark = compat.HasDarkBackground()
    
    func main() {
        h := help.New()
        h.Styles = help.DefaultStyles(isDark)
    }

    Manual

    Force a specific theme:

    • help.DefaultDarkStyles()
    • help.DefaultLightStyles()
  3. Migrate Viewport component to Bubbles v2

    main

    When upgrading the viewport component to v2:

    • Replace New(w, h int) with the variadic options pattern: New(...Option).
    • Access dimensions and offsets via methods:
      • Model.Width $\rightarrow$ Model.SetWidth() / Model.Width()
      • Model.Height $\rightarrow$ Model.SetHeight() / Model.Height()
      • Model.YOffset $\rightarrow$ Model.SetYOffset() / Model.YOffset()
    • HighPerformanceRendering has been removed.
  4. Migrate Paginator component to Bubbles v2

    main

    When upgrading the paginator component from v1 to v2:

    • Replace NewModel(...) with New(...).
    • DefaultKeyMap is now a function: DefaultKeyMap() instead of a variable.
    • Key Customization: Boolean flags like UsePgUpPgDownKeys, UseLeftRightKeys, UseUpDownKeys, UseHLKeys, and UseJKKeys have been removed. To change key bindings, customize the KeyMap directly.
  5. Migrate Table component to Bubbles v2

    main

    When upgrading the table component from v1 to v2, use the getter/setter methods for dimensions. While these existed in v1, they now wrap the internal viewport:

    • Use model.Width() and model.SetWidth(w).
    • Use model.Height() and model.SetHeight(h).
  6. Migrate Textarea component to Bubbles v2

    main

    The textarea component has undergone significant restructuring in v2:

    KeyMap

    • textarea.DefaultKeyMap is now a function: textarea.DefaultKeyMap().
    • New key bindings added: PageUp, PageDown.

    Styles

    Styles are now nested under a Styles struct of type StyleState:

    // After
    ta := textarea.New()
    // Access via Styles.Focused and Styles.Blurred
    ta.Styles.Focused = ...
    ta.Styles.Blurred = ...

    Cursor

    • ta.Cursor (the model) is now accessed via the method ta.Cursor() which returns *tea.Cursor.
    • ta.SetCursor(col) is renamed to ta.SetCursorColumn(col).
    • Use ta.VirtualCursor (bool) to toggle between virtual and real cursors.
    • New methods: Column(), ScrollYOffset(), ScrollPosition(), MoveToBeginning(), and MoveToEnd().
  7. Migrate Help component to Bubbles v2

    main

    When upgrading the help component from v1 to v2:

    • Replace NewModel() with New().
    • Replace direct field access for width (model.Width = 80) with model.SetWidth(80).
    • Replace direct field access for width reading (_ = model.Width) with model.Width().
    • Explicit Styling Required: Styles no longer auto-adapt. You must explicitly apply them using DefaultStyles(isDark), DefaultDarkStyles(), or DefaultLightStyles().
    // Before
    h := help.New()
    
    // After
    h := help.New()
    h.Styles = help.DefaultStyles(isDark)
  8. Update Import Paths for Bubbles v2

    main

    Replace all github.com/charmbracelet/bubbles import paths with charm.land/bubbles/v2.

    Note: The runeutil and memoization packages are now internal and cannot be imported directly.

    Search-and-replace pattern:

    • Replace github.com/charmbracelet/bubbles/ with charm.land/bubbles/v2/
    • Replace github.com/charmbracelet/bubbles with charm.land/bubbles/v2
    // Before
    import (
        "github.com/charmbracelet/bubbles/cursor"
        "github.com/charmbracelet/bubbles/help"
        "github.com/charmbracelet/bubbles/key"
        "github.com/charmbracelet/bubbles/list"
        "github.com/charmbracelet/bubbles/paginator"
        "github.com/charmbracelet/bubbles/progress"
        "github.com/charmbracelet/bubbles/runeutil"
        "github.com/charmbracelet/bubbles/spinner"
        "github.com/charmbracelet/bubbles/stopwatch"
        "github.com/charmbracelet/bubbles/table"
        "github.com/charmbracelet/bubbles/textarea"
        "github.com/charmbracelet/bubbles/textinput"
        "github.com/charmbracelet/bubbles/timer"
        "github.com/charmbracelet/bubbles/viewport"
    )
    
    // After
    import (
        "charm.land/bubbles/v2/cursor"
        "charm.land/bubbles/v2/help"
        "charm.land/bubbles/v2/key"
        "charm.land/bubbles/v2/list"
        "charm.land/bubbles/v2/paginator"
        "charm.land/bubbles/v2/progress"
        "charm.land/bubbles/v2/spinner"
        "charm.land/bubbles/v2/stopwatch"
        "charm.land/bubbles/v2/table"
        "charm.land/bubbles/v2/textarea"
        "charm.land/bubbles/v2/textinput"
        "charm.land/bubbles/v2/timer"
        "charm.land/bubbles/v2/viewport"
    )
  9. Migrate TextInput component to Bubbles v2

    main

    When upgrading the textinput component to v2:

    • Replace NewModel with New().
    • Replace DefaultKeyMap variable with DefaultKeyMap() function.
    • Access Model.Width via getter/setter methods: Model.SetWidth() and Model.Width().
    • Styles are now part of StyleState. Map old styles to the new fields:
      • Model.PromptStyle $\rightarrow$ StyleState.Prompt
      • Model.TextStyle $\rightarrow$ StyleState.Text
      • Model.PlaceholderStyle $\rightarrow$ StyleState.Placeholder
      • Model.CompletionStyle $\rightarrow$ StyleState.Suggestion
      • Model.CursorStyle $\rightarrow$ Styles.Cursor
    • Replace Model.Cursor (the cursor.Model field) with the Model.Cursor() method, which returns a *tea.Cursor.
  10. Migrate Progress component to Bubbles v2

    main

    The progress component has significant breaking changes in v2:

    Width

    Use getters and setters instead of direct field access:

    // Before
    p.Width = 40
    fmt.Println(p.Width)
    
    // After
    p.SetWidth(40)
    fmt.Println(p.Width())

    Colors

    Color types changed from string to image/color.Color. Use lipgloss.Color() to convert:

    // After
    p.FullColor = lipgloss.Color("#FF0000")
    p.EmptyColor = lipgloss.Color("#333333")

    Gradient and Fill Options

    Options have been renamed and restructured:

    v1 Optionv2 Option
    WithGradient(a, b string)WithColors(colors ...color.Color)
    WithDefaultGradient()WithDefaultBlend()
    WithScaledGradient(a, b string)WithColors(...) + WithScaled(true)
    WithDefaultScaledGradient()WithDefaultBlend() + WithScaled(true)
    WithSolidFill(string)WithColors(color) (single color)

    New Options

    • WithColorFunc(func(total, current float64) color.Color): For dynamic per-cell coloring.
    • WithScaled(bool): Scales the blend to the filled portion.
  11. Migrate Stopwatch component to Bubbles v2

    main

    When upgrading the stopwatch component from v1 to v2, the constructor pattern has changed to use functional options:

    // Before
    sw := stopwatch.NewWithInterval(500 * time.Millisecond)
    
    // After
    sw := stopwatch.New(stopwatch.WithInterval(500 * time.Millisecond))
  12. Upgrade to Bubbles v2

    main

    When migrating from Bubbles v1 to Bubbles v2, you must upgrade Bubble Tea and Lip Gloss simultaneously to ensure compatibility. Use the following commands to upgrade all three dependencies to their latest v2 versions:

    go get charm.land/bubbletea/v2@latest
    go get charm.land/bubbles/v2@latest
    go get charm.land/lipgloss/v2@latest