Skip to content

fix(deps): update module charm.land/bubbles/v2 to v2.1.0#298

Open
botty-mcbottington[bot] wants to merge 1 commit intomainfrom
renovate/charm.land-bubbles-v2-2.x
Open

fix(deps): update module charm.land/bubbles/v2 to v2.1.0#298
botty-mcbottington[bot] wants to merge 1 commit intomainfrom
renovate/charm.land-bubbles-v2-2.x

Conversation

@botty-mcbottington
Copy link
Copy Markdown
Contributor

@botty-mcbottington botty-mcbottington bot commented Feb 24, 2026

This PR contains the following updates:

Package Change Age Confidence
charm.land/bubbles/v2 v2.0.0-rc.1v2.1.0 age confidence

Release Notes

charmbracelet/bubbles (charm.land/bubbles/v2)

v2.1.0

Compare Source

Shrink ’n’ grow your textareas

The update adds a new feature to automatically resize your textarea vertically as its content changes.

ta := textarea.New()
ta.DynamicHeight = true   // Enable dynamic resizing
ta.MinHeight = 3          // Minimum visible rows
ta.MaxHeight = 10         // Maximum visible rows
ta.MaxContentHeight = 20  // Maximum rows of content

Piece of cake, right?

Enjoy! 💘

Changelog

New!

The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on X, Discord, Slack, The Fediverse, Bluesky.

v2.0.0

Compare Source

bubbles-v2-block

Bubbles v2 is here! 🫧

We're thrilled to share Bubbles v2 with you! This release accompanies Bubble Tea v2 and Lip Gloss v2 and brings a ton of consistency, new features, and quality-of-life improvements across every component. Catch 'em all:

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

You can also check the Upgrade Guide for more info.

There are a lot of changes in here, but we've found upgrading pretty easy, especially with a linter. Read on for the full breakdown!

[!NOTE]
When in doubt, check the examples for reference — they've all been updated for v2.

🏠 New Home

Bubbles v2 now lives at charm.land:

import "charm.land/bubbles/v2"

All sub-packages follow the same pattern: charm.land/bubbles/v2/viewport, charm.land/bubbles/v2/list, etc.

🎨 Light and Dark Styles

Some Bubbles, like help, offer default styles for both light and dark backgrounds. Since Lip Gloss v2 removes AdaptiveColor, choosing light or dark is now a manual process. You've got a couple of options.

🎩 The Best Way

Have Bubble Tea query the background color for you. This properly queries the correct inputs and outputs, and happens in lockstep with your application:

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:
        m.help.Styles = help.DefaultStyles(msg.IsDark())
        return m, nil
    }
    // ...
}

If you're using Wish you must do it this way to get the background color of the client.

🤠 The Quick Way

Use the compat package in Lip Gloss. It's less recommended because it contains blocking I/O that operates independently of Bubble Tea, and when used with Wish it won't detect the client's background:

import "charm.land/lipgloss/v2/compat"

var hasDarkBG = compat.HasDarkBackground()

h := help.New()
h.Styles = help.DefaultStyles(hasDarkBG)
👀 Or Just Pick One
h.Styles = help.DefaultLightStyles() // light mode!
h.Styles = help.DefaultDarkStyles()  // jk dark mode

This pattern applies to help, list, textarea, and textinput.

🔑 The Init You Know and Love is Back

After experimenting with a few different forms of Init during the alphas, we decided the v1 signature was the right call after all. Init was a bit too redundant for our tastes given that initialization already happens in New:

func (m Model) Init() tea.Cmd

✨ The Big Highlights

Getters and Setters Everywhere

All components now use getter/setter methods instead of exported Width and Height fields. This lets us do internal bookkeeping when things change, and it makes the API consistent across every Bubble:

// Before
vp.Width = 40
fmt.Println(vp.Width)

// After
vp.SetWidth(40)
fmt.Println(vp.Width())

Affected: filepicker, help, progress, table, textinput, viewport.

Functional Options

Constructors now use the functional options pattern instead of positional args or separate constructor functions:

vp := viewport.New(viewport.WithWidth(80), viewport.WithHeight(24))
sw := stopwatch.New(stopwatch.WithInterval(500 * time.Millisecond))
t := timer.New(30*time.Second, timer.WithInterval(100*time.Millisecond))
DefaultKeyMap is a Function Now

All DefaultKeyMap package-level variables are now functions, so you get fresh values every time:

km := textinput.DefaultKeyMap()   // was textinput.DefaultKeyMap
km := textarea.DefaultKeyMap()    // was textarea.DefaultKeyMap
km := paginator.DefaultKeyMap()   // was paginator.DefaultKeyMap
Real Cursor Support 🖱️

Both textarea and textinput now support real terminal cursors! The feature is opt-in, so by default your programs will continue to use the easy-breezy virtual cursor. Set VirtualCursor to false and use Model.Cursor() for the real deal. Check out the textarea and textinput examples to see it in action.

Cleaned House 🧹

All previously deprecated symbols have been removed:

  • NewModel variants — just use New
  • spinner.Tick() — use Model.Tick() instead
  • paginator.UsePgUpPgDownKeys and friends — customize KeyMap directly
  • filepicker.DefaultStylesWithRenderer() — Lip Gloss is pure now, use DefaultStyles()
  • viewport.HighPerformanceRendering — no longer needed
  • runeutil and memoization packages moved to internal/ (they were never meant for public use anyway)

What's Changed: the Laundry List

🔮 Cursor
  • Model.Blink renamed to Model.IsBlinked for clarity
  • Model.BlinkCmd() renamed to Model.Blink()
  • Each cursor now gets a unique ID
📂 Filepicker
  • DefaultStylesWithRenderer() removed — Lip Gloss is pure now, so just use DefaultStyles()
  • Model.Height broken into SetHeight(int) / Height() int
❓ Help
  • Model.Width broken into SetWidth(int) / Width() int
  • New DefaultStyles(isDark bool), DefaultDarkStyles(), and DefaultLightStyles()
  • Defaults to dark background styles out of the box
🥕 List
  • DefaultStyles() and NewDefaultItemStyles() now take an isDark bool parameter
  • Styles.FilterPrompt and Styles.FilterCursor have been consolidated into Styles.Filter (a textinput.Styles)
  • GlobalIndex helper added
📄 Paginator
  • DefaultKeyMap variable → DefaultKeyMap() function
  • Deprecated fields (UsePgUpPgDownKeys, UseLeftRightKeys, etc.) removed — customize KeyMap directly
🌈 Progress

This one got the biggest makeover!

  • Complete color API overhaul:
    • WithGradient / WithScaledGradientWithColors(...color.Color) — pass 2+ colors for blending
    • WithSolidFill(string)WithColors(color) — pass a single color for a solid fill
    • WithDefaultGradient()WithDefaultBlend()
    • New WithScaled(bool) to scale the blend to fit only the filled portion
    • New WithColorFunc(func(total, current float64) color.Color) for fully dynamic coloring
    • WithColorProfile removed — Bubble Tea handles this automatically now
  • Model.FullColor and Model.EmptyColor changed from string to image/color.Color
  • Model.Width broken into SetWidth(int) / Width() int
  • Model.Update now returns Model instead of tea.Model
  • Improved blend algorithm with support for multiple color stops — special thanks to the legendary @​lrstanley!
🌀 Spinner
  • Tick() package-level function removed — use Model.Tick() instead
⏱️ Stopwatch
  • NewWithInterval(d) removed — use New(WithInterval(d)) instead
  • Debounced tick messages
🔢 Table
  • Model.Width / Model.Height replaced with getter/setter methods
  • Uses ansi.Truncate instead of runewidth.Truncate
  • Fixed a critical out-of-bounds cursor bug — thanks @​s0ders!
✏️ Textarea

The big change here is real cursor support — but that's opt-in, so by default your programs will keep using the virtual cursor.

  • DefaultKeyMap variable → DefaultKeyMap() function
  • New PageUp / PageDown key bindings
  • Model.FocusedStyle / Model.BlurredStyleModel.Styles.Focused / Model.Styles.Blurred
  • Style type renamed to StyleState; new Styles struct groups Focused, Blurred, and Cursor
  • Model.SetCursor renamed to Model.SetCursorColumn
  • Model.Cursor is now func() *tea.Cursor for real cursor support
  • Model.VirtualCursor bool added — set to false when using a real cursor
  • New DefaultStyles(isDark bool), DefaultDarkStyles(), DefaultLightStyles()
  • New methods: Column(), ScrollYOffset(), ScrollPosition(), MoveToBeginning(), MoveToEnd()
  • Focus status now passed to SetPromptFunc
📜 Textinput

Most of the changes here bring textinput to parity with textarea, including real cursor support. Styling has been consolidated into a Styles struct with Focused and Blurred states:

  • DefaultKeyMap variable → DefaultKeyMap() function
  • Model.Width broken into SetWidth(int) / Width() int
  • Model.PromptStyleStyleState.Prompt
  • Model.TextStyleStyleState.Text
  • Model.PlaceholderStyleStyleState.Placeholder
  • Model.CompletionStyleStyleState.Suggestion
  • Model.Cursor is now func() *tea.Cursor for real cursor support
  • Model.VirtualCursor() / SetVirtualCursor(bool) added
  • Model.Styles() / SetStyles(Styles) added
  • New DefaultStyles(isDark bool), DefaultDarkStyles(), DefaultLightStyles()
  • Exposed matched suggestions and suggestion index
⏲️ Timer
  • NewWithInterval(timeout, interval) removed — use New(timeout, WithInterval(interval))
  • Debounced tick messages
📦 Viewport

viewport got a ton of love in v2. Let's dive in!

Breaking changes:

  • New(width, height int)New(...Option) with WithWidth / WithHeight
  • Model.Width, Model.Height, Model.YOffset replaced with getter/setter methods
  • HighPerformanceRendering removed

Shiny new features:

You can now scroll horizontally with the left and right arrow keys, and set up a custom gutter column for things like line numbers:

vp := viewport.New()
vp.SetContent("hello world")

// Show line numbers:
vp.LeftGutterFunc = func(info viewport.GutterContext) string {
    if info.Soft {
        return "     │ "
    }
    if info.Index >= info.TotalLines {
        return "   ~ │ "
    }
    return fmt.Sprintf("%4d │ ", info.Index+1)
}

Highlight parts of what's being viewed with regex:

vp.SetHighlights(regexp.MustCompile("hello").FindAllStringIndex(vp.GetContent(), -1))
vp.HighlightNext()      // highlight and navigate to next match
vp.HighlightPrevious()  // highlight and navigate to previous match
vp.ClearHighlights()    // clear all highlights

Let viewport handle soft wrapping for you:

vp.SoftWrap = true
vp.SetContent("hello world from a very long line")

Or, if you need fine control, use SetContentLines with "virtual lines" containing \n — they're treated as soft wraps automatically.

Also new:

  • Horizontal mouse wheel scrolling (thanks @​UnseenBook!)
  • GetContent() to retrieve content
  • FillHeight to pad the viewport with empty lines
  • StyleLineFunc for per-line styling
  • HighlightStyle and SelectedHighlightStyle for highlight appearance

Changelog

Fixed
  • f744b929dddecc7863cf78605c5bfc396d90abc3: fix(ci): use local golangci-lint config (@​aymanbagabas)
  • 251e612949595b006e0e4739029d45e32c6b34b6: fix(filepicker): fix a panic due to an unchecked assertion (#​891) (@​meowgorithm)
  • f3f0ca0fe2f05b56e5a0c69b226b4d752c5e8f4a: fix(lint): exclude var-naming rule for revive (@​aymanbagabas)
  • d004225e8c3b8c8ddb14a76a5101728d666396f3: fix(table): use ansi.Truncate instead of runewidth.Truncate (#​884) (@​jedevc)
  • 93a004ab70c8ea979940b2720b3993c8f68bf8dc: fix(viewport): optimize subline splitting by skipping lines without line endings (@​aymanbagabas)
  • d0166363eb8176b331de98dba1d6e997560f216f: fix: changed 'recieve' to 'receive' for 100% quality of Go Report Card (#​881) (@​Atennop1)
  • af98365cc63af118d838e05522f8dddf16ad827e: fix: lint issues (@​aymanbagabas)
Docs
  • c81d525337e1a059c4343cf65a02eea020470a48: docs(readme): update for v2 (#​888) (@​aymanbagabas)
  • 6a799f4d58cc0eaeab0874f4ce9c98b5a922bd01: docs(readme): update header image, minor corrections (@​meowgorithm)
  • 24081b3590e746db4efa2ec09e31a85e2c078427: docs: add v2 upgrade and changes guide (#​885) (@​aymanbagabas)
  • 3a5ea3e2eb42aa064bb4a0ffe3262cb2b8a1f19b: docs: update mascot image (@​aymanbagabas)
Other stuff
  • ae99f46cec66f45862c2d953bb1af31efdc4f073: feat(v2/textarea): expose Column(), clarify 0-indexing (#​875) (@​caarlos0)

💝 That's a wrap!

Feel free to reach out, ask questions, give feedback, and let us know how it's going. We'd love to know what you think.


Part of Charm.

The Charm logo

Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

@botty-mcbottington botty-mcbottington bot enabled auto-merge (squash) February 24, 2026 18:29
@botty-mcbottington
Copy link
Copy Markdown
Contributor Author

botty-mcbottington bot commented Feb 24, 2026

ℹ️ Artifact update notice

File name: go.mod

In order to perform the update(s) described in the table above, Renovate ran the go get command, which resulted in the following additional change(s):

  • 9 additional dependencies were updated

Details:

Package Change
charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251212194116-6348bd4b7475 -> v2.0.2
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251205162909-7869489d8971 -> v2.0.2
github.com/aymanbagabas/go-udiff v0.3.1 -> v0.4.1
github.com/charmbracelet/colorprofile v0.4.1 -> v0.4.2
github.com/charmbracelet/ultraviolet v0.0.0-20251212194010-b927aa605560 -> v0.0.0-20260205113103-524a6607adb8
github.com/clipperhouse/displaywidth v0.9.0 -> v0.11.0
github.com/clipperhouse/uax29/v2 v2.5.0 -> v2.7.0
github.com/mattn/go-runewidth v0.0.19 -> v0.0.21
golang.org/x/sys v0.41.0 -> v0.42.0

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 45.16%. Comparing base (f29a6d4) to head (4a8b369).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #298   +/-   ##
=======================================
  Coverage   45.16%   45.16%           
=======================================
  Files          53       53           
  Lines        4886     4886           
=======================================
  Hits         2207     2207           
  Misses       2523     2523           
  Partials      156      156           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@botty-mcbottington botty-mcbottington bot force-pushed the renovate/charm.land-bubbles-v2-2.x branch from 22f6508 to 4a8b369 Compare March 27, 2026 00:51
@botty-mcbottington botty-mcbottington bot changed the title fix(deps): update module charm.land/bubbles/v2 to v2.0.0 fix(deps): update module charm.land/bubbles/v2 to v2.1.0 Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants