Skip to content

Releases: charmbracelet/bubbles

v0.10.2

20 Jan 18:50
Compare
Choose a tag to compare

Housekeeping

🧹 This is a small release to improve the overall integrity of the viewport and textinput Bubbles.

  • Setting the width and height on a viewport’s style attribute is now a no-op. Previously it would produce some pretty confusing rendering and generally conflict with the Width and Height attributes on the model.
  • Fix a textinput regression where deleting words left of the cursor didn't actually do anything (courtesy @IllusionMan1212)

Full Changelog: v0.10.1...v0.10.2


The Charm logo

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

v0.10.1

19 Jan 18:10
Compare
Choose a tag to compare

Viewport Hotfixes

This release fixes some viewport bugs introduced in v0.10.0:

  • Fixed a bug where the viewport's y-offset could be negative
  • Fixed an off-by-one error in GotoBottom()

🤗 Special thanks to @knipferrc and @IllusionMan1212 for their assistance with the bugfixes.

Also

Full Changelog: v0.10.0...v0.10.1


The Charm logo

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

v0.10.0

13 Jan 19:26
465a66e
Compare
Choose a tag to compare

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.

v0.9.0

08 Sep 14:40
Compare
Choose a tag to compare

Lists, Animated Progress Bar and More

There are a handful of new things in this release, the biggest being the brand new List Bubble we extrapolated from Glow. Read on!

New: List

List Example

The List Bubble is a highly customizable, batteries-included component for browsing a set of items. It features pagination, fuzzy filtering, auto-generated help, an activity spinner, and status messages, all of which can be enabled and disabled as needed.

New: Key

A non-visual component for managing keybindings. It’s useful for allowing users to remap keybindings, allows keys to be enabled and disabled programatically, and can be used to generate help views.

import "github.com/charmbracelet/bubbles/key"

up := key.NewBinding(
    key.WithKeys("up", "k"),
    key.WithHelp("↑/k", "move up"),
)

if key.Matches(msg, up) {
    // ...
}

New: Help

Help Example

A customizable horizontal mini help view that automatically generates itself from your keybindings. It features single and multi-line modes, which the user can optionally toggle between. It will truncate gracefully if the terminal is too wide for the content.

Updated: Progress Bar

The progress bar has been updated so that it can now animate itself via Harmonica. You can, of course, still render non-animated progress bars too.

Note that there are also some minor API changes to the Progress Bubble. See the changelog below.

Progress Bar Changelog

Changed

  • NewModel no longer returns an error
  • Model.View(float64) string is now Model.View() string (to render a static view per the prior version use Model.ViewAs(float64) string)
  • Invalid hex colors now render as black

New

  • Added WithSpringOptions to customize spring animation
  • Added Model.Update for animating the progress bar
  • Added Model.ViewAs(float64) string for rendering static progress bars
  • Model now satisfies the tea.Model interface making more composable

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

The Charm logo

v0.8.0

02 Jun 15:09
Compare
Choose a tag to compare

Textinput Cursor Options and Enhancements

This release introduces options for textinput cursor behavior and improves subtleties with cursor blinking when multiple textinputs are present.

To change the cursor behavior:

import "github.com/charmbracelet/bubbles/textinput"

m := textinput.NewModel()
m.SetCursorMode(textinput.CursorStatic) // no blinking
m.SetCursorMode(textinput.CursorHide)   // actually, let's hide the cursor
m.SetCursorMode(textinput.CursorBlink)  // jk let's make it blink

Changelog

New

  • Cursors now have three modes: CursorBlink, CursorStatic and CursorHide (all of type CursorMode). You can set the cursor mode via textinput’s Model.SetCursor(CursorMode) and get the cursor mode with Model.CursorMode() CursorMode.

Changed

  • textinput’s Model.Focus() is now Model.Focus() tea.Cmd. This will initiate a properly timed cursor blink when focusing on a textinput if the cursor mode is set to blink.

Fixed

  • After their initial cursor blink (initiated by textinput.Blink() tea.Cmd), textinputs can now only receive blink messages they sent. This prevents textinputs from receiving other textinputs blink messages when focus changes.
  • When cursor blink messages are sent, former blink messages in transit are invalidated, eliminating the change of rogue blinks.

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter and The Fediverse, or right here in GitHub Discussions.

The Charm logo

v0.7.9

26 Apr 17:07
Compare
Choose a tag to compare

Minor Textinput Updates

This is a minor PR that improves the textinput API and behavior when dealing with masked input, such as passwords.

Changed

  • SetCursor(int), CursorStart() and CursorEnd() no longer return values.
  • If EchoMode is not EchoNormal word-to-word movement instead jumps to the beginning and end. Word-based deletion also deletes to the beginning and end.

New

  • Cursor() int returns the cursor position.

Removed

  • Removed Cursor string, which did absolutely nothing.

Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter and The Fediverse, or right here in GitHub Discussions.

The Charm logo

v0.7.8

19 Apr 23:51
Compare
Choose a tag to compare

The mini-release prevents a panic that could occur when setting content in the viewport.


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

The Charm logo

v0.7.7

13 Apr 23:27
Compare
Choose a tag to compare

Hello, Lip Gloss

This release introduces Lip Gloss into the Spinner and Text Input components offering a greater range of styling options. Note that this introduces some minor API changes.

New

Text Input

  • Added textinput.Model.PromptStyle. Previously, styling the prompt was left as an exercise for the user.

Changed

Spinner

  • Model.ForegroundColor and Model.BackgroundColor is now simply Model.Style, a lipgloss.Style.

Text Input

  • Model.TextColor is now Model.TextStyle
  • Model.PlaceholderColor is now Model.PlaceholderStyle
  • Model.CursorColor is now Model.CursorStyle

All of these types are now lipgloss.Style.

Improved

  • Better rxvt-based terminal compatibility (courtesy Termenv)
  • Bumped bubbletea, termenv, reflow, go-runewidth and go-colorful dependencies

Fixed

  • Data race in data race rxvt-based terminals (courtesy Termenv)
  • Reset cursor in SetValue when initial position is 0 (thanks, @kiyonlin)

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

The Charm logo

v0.7.6

13 Jan 19:40
c8f4855
Compare
Choose a tag to compare

Progress!

This release features a simple, flexible, and customizable progress bar for your terminal apps.

  • Choose from solid and gradient fills
  • Set the empty and filled runes to whatever you'd like
  • The percentage readout is customizable and can also be omitted entirely

For more info see:

Progress Bar Example

v0.7.5

12 Nov 16:27
Compare
Choose a tag to compare

This release contains design updates to Spinner which provide spin-speeds on a per-spinner basis for a better out-of-the-box experience, as well as a bugfix.

New:

  • Added default spinners: spinner.MiniDot, spinner.Pulse, spinner.Points

Changed:

  • Type spinner.Spinner is now a struct with properies Frames []string and FPS time.Duration
  • Visual improvements to spinner.Monkey, spinner.Globe, and spinner.Moon

Removed:

  • spinner.Bit8

Fixed:

  • spinner.TickMsg is now sent on both start and update; the previous version had an internal un-exported start message which made passing messages to spinners more cumbersome