github charmbracelet/bubbles v0.10.0

latest releases: v2.0.0-alpha.2, v2.0.0-alpha.1, v0.20.0...
2 years ago

Timer, stopwatch, bugfixes and quality-of-life improvements

🎊 Happy New Year! This is a big release with a couple new components, a bunch of bug fixes, and some general quality-of-life improvements across the board.

tl;dr

New

  • Add timer component (thanks @caarlos0) #67
  • Add stopwatch component (thanks @caarlos0) #68
  • viewport can now be initialized with a New() constructor at the package level #92
  • viewport now has customizable keybindings via the key package #92
  • viewport mouse wheel speed can be customized #92
  • The mouse's scroll wheel can now be disabled for a viewport #92

Changed

  • NewModel() constructors are now deprecated in favor of New() #93
  • Expose list.FilterMachesMsg (thanks @jon4hz) #77
  • Expand key.Matches to accept multiple binding arguments #84
  • spinner now ignores messages sent by other spinners #91

Fixed

  • Update keybindings when calling SetItems on a list (thanks @paralin) #90
  • Update keybindings after calling InsertItem on a list #94
  • Fix textinput infinite loop and panic (thanks @IllusionMan1212) #89
  • Fix bug where viewport wasn't rendering final lines #74
  • Fix bug where viewport performance rendering could render one line too many #74

Hungry for more? Here are the details.

New: Timer

@caarlos0 added a simple timer Bubble for counting down.

Timer example

See the example code and docs for details.

New: Stopwatch

To match the timer, @caarlos0 also added a simple stopwatch Bubble for counting up.

Timer example

See the example code and docs for details.

Constructor Changes

Prior to this update the convention was to create new models via a NewModel. We've changed that convention to New() for brevity and readability. NewModel() will continue to work in a deprecated fashion to ease the update process.

// Old
s := spinner.NewModel()

// New!
s := spinner.New()

Viewport Improvements

As of this update you're strongly encouraged to initialize viewport models with the new New(width, height int) Model function, however it's currently optional to reduce friction when upgrading.

const width, height = 40, 80
vp := viewport.New(width, height)

Viewport models also now have a Style lipgloss.Style property you can use to apply borders, margins, and padding directly to a viewport. Not more magic numbers, random constants, and fussy arithmetic.

vp.Style = lipgloss.NewStyle().
        BorderStyle(lipgloss.RoundedBorder()).
        BorderForeground(lipgloss.Color("62")).
        PaddingRight(2)

Keybindings on a viewport are now defined via the key Bubble and can now be easily remapped.

vp.KeyMap.Up = key.NewBinding(WithKeys("up", "w"))

For details see the available bindings. Note that you can also just match on keys in the parent Update and call viewport methods like LineUp programmatically.

And, lastly, you can now change the mouse wheel scroll speed, or disable it entirely:

vp := viewport.New()
vp.MouseWheelDelta = 5 // make mouse scrolling really fast!
vp.MouseWheelEnabled = false // jk, turn it off

See the viewport docs for details.

Spinner Improvements

Now spinners only respond to their own spin messages so you don't need any more fancy logic when you want to control multiple spinners at once. To start a specific spinner you now call Tick() on the model instead of the package:

s := spinner.New()

// Old
cmd := spinner.Tick()

// New
cmd := s.Tick()

For posterity, you can still use the package-level Tick method in a deprecated fashion, however note that it will affect all spinners that process the resulting TickMsg as it did prior to the release.

For details see the spinner docs.

Keybindings

key.Binding currently allows you to bind against multiple keys:

binding := key.Binding(key.WithKeys("q", "ctrl+c"))

However, sometimes you may also want to match on multiple bindings:

left := key.Binding(key.WithKeys("h", "left"))
right := key.Binding(key.WithKeys("l", "right"))

case key.Matches(msg, left), key.Matches(msg, right):

This update expands key.Matches to accept multiple arguments so you can condense the above case statement to:

case key.Matches(msg, left, right):

For more on how keybindings work see the key docs.


New Contributors

Full Changelog: v0.9.0...v0.10.0


The Charm logo

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.

Don't miss a new bubbles release

NewReleases is sending notifications on new releases.