Releases: charmbracelet/bubbles
v0.13.0
Textarea Bubble
This feature release includes a brand new textarea
bubble that you can use to input as many lines of text as your heart desires (or until your computer memory runs out, whichever comes first).
See the example code for a simple example of how to use the textarea
in your Bubble Tea applications.
Customization
There are a few ways to customize the text area.
SetHeight(height int)
: tells the component how many lines of text it should display at once.SetWidth(width int)
: tells the component how wide the it should be.ShowLineNumbers
: whether or not to show line numbers on the left-hand side of a line of text.Prompt
: the prompt to display on the left-hand side.EndOfBufferCharacter
: the character to display as the line number after the last line to fill the rest of the height. Defaults to~
.CharLimit
: Prevents users from typing more than a set number of characters.KeyMap
: The set of keybindings to navigate and interact with thetextarea
.
Styling
The textarea
can be customized heavily with Lip Gloss.
FocusedStyles
: the styles to be applied while thetextarea
is focused.BlurredStyles
: the styles to be applied while thetextarea
is focused.
Each of the above properties has the below sub-properties that can be modified.
Base lipgloss.Style
CursorLine lipgloss.Style
CursorLineNumber lipgloss.Style
EndOfBuffer lipgloss.Style
LineNumber lipgloss.Style
Placeholder lipgloss.Style
Prompt lipgloss.Style
Text lipgloss.Style
See the split editors example for how to style the textarea
component.
Read more about it in our examples and docs:
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.12.0
Validate Your Darlings
This release of Bubbles allows you to handle input validation by defining validation functions that ensure the user is typing text that you expect.
The Validate
API introduces a function that is called every time the input changes to ensure that it is still valid input.
// ValidateFunc is a function that returns an error if the input is invalid.
type ValidateFunc func(string) error
// Validate is a function that checks whether or not the text within the
// input is valid. If it is not valid, the `Err` field will be set to the
// error returned by the function. If the function is not defined, all
// input is considered valid.
Validate ValidateFunc
View the Example Code to see Validate
and ValidateFunc
s work in code.
With these awesome changes introduced by @IllusionMan1212, we can now build forms that ensure all input is valid like a credit card input form!
See the full example to handle input validation in your Bubble Tea apps.
Custom List Status Bar Item Names
Thanks to @wesleimp, lists now have a new function to allow you to set a custom status bar item name. Simply call SetStatusBarItemName
on your list with the singular and plural name of your list item and Bubbles will handle the rest (defaults to "item", "items").
list.SetStatusBarItemName("grocery", "groceries")
This will change the string displayed underneath the Title
of the list, in this case the item name is being used for displaying 2 groceries
.
New Spinners π«
This release contains two brand new spinners introduced by @wesleimp, check them out:
What's Changed
- Validate Input by @maaslalani in #167
- Custom status bar title by @wesleimp in #169
- New spinners by @wesleimp in #172
New Contributors
- @motemen made their first contribution in #168
- @maaslalani made their first contribution in #167
- @wesleimp made their first contribution in #169
- @vzvu3k6k made their first contribution in #171
- @charlieroth made their first contribution in #177
Full Changelog: v0.11.0...v0.12.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or Slack.
v0.11.0
Housekeeping
π§Ή Hot on the heels of Bubble Tea v0.21.0, this is a maintenance release with a lot of great quality-of-life features from both the Charm team and the community. Enjoy!
Changelog
New
- list: allow custom filter functions by @caarlos0 in #103
- list: allow to set the height of the item by @caarlos0 in #155
- viewport: add missing keymap help by @aymanbagabas in #146
- textinput: add blink method to textinput to return blink state by @aschey in #122
- progress: set a custom termenv color profile by @aymanbagabas in #152
Fixed
- list: fix padding in titlebar when nothing is displayed by @toadle in #139
- textinput: support KeySpace in present and future Bubble Tea versions by @meowgorithm in #161
Changed
- spinner: remove provisional spinner lifetime stuff by @meowgorithm in #112
- list: fix rendering of an empty list by @aymanbagabas in #123
- progress: Percent() now returns progress as presented visually by @meowgorithm in #132
New Contributors
Full Changelog: v0.10.3...v0.11.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.10.3
A Couple βo List Bugfixes
This small patch release fixes a couple small bugs with regard to the quit keybinding in list
. Cheers! π»
Fixed
- Properly set quit keybinding in keybinding update phase #108
- Disable quit keybinding while filtering (thanks @lorenries!) #118
New Contributors
- @aymanbagabas made their first contribution in #108
- @mirkoperillo made their first contribution in #115
- @treilik made their first contribution in #113
- @lorenries made their first contribution in #118
Full Changelog: v0.10.2...v0.10.3
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.10.2
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 theWidth
andHeight
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
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.10.1
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
- Bumped atotto/clipboard to v0.1.4 for clipboard-related WSL and plan9 support
- Bumped Lip Gloss to
v0.4.0
Full Changelog: v0.10.0...v0.10.1
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.10.0
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 aNew()
constructor at the package level #92viewport
now has customizable keybindings via thekey
package #92viewport
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 ofNew()
#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 alist
(thanks @paralin) #90 - Update keybindings after calling
InsertItem
on alist
#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.
See the example code and docs for details.
New: Stopwatch
To match the timer, @caarlos0 also added a simple stopwatch Bubble for counting up.
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
- @caarlos0 made their first contribution #67
- @anirvan made their first contribution #81
- @paralin made their first contribution #90
- @IllusionMan1212 made their first contribution #89
- @jon4hz made their first contribution #77
Full Changelog: v0.9.0...v0.10.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Slack.
v0.9.0
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
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
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 errorModel.View(float64) string
is nowModel.View() string
(to render a static view per the prior version useModel.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 thetea.Model
interface making more composable
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter or The Fediverse.
v0.8.0
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
andCursorHide
(all of typeCursorMode
). You can set the cursor mode viatextinput
βsModel.SetCursor(CursorMode)
and get the cursor mode withModel.CursorMode() CursorMode
.
Changed
textinput
βsModel.Focus()
is nowModel.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.
v0.7.9
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()
andCursorEnd()
no longer return values.- If
EchoMode
is notEchoNormal
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.