Releases: charmbracelet/bubbles
v0.21.0
Viewport improvements
Finally, viewport
finally has horizontal scrolling ✨!1
To enable it, use SetHorizontalStep
(default in v2 will be 6
).
You can also scroll manually with ScrollLeft
and ScrollRight
, and use
SetXOffset
to scroll to a specific position (or 0
to reset):
vp := viewport.New()
vp.SetHorizontalStep(10) // how many columns to scroll on each key press
vp.ScrollRight(30) // pan 30 columns to the right!
vp.ScrollLeft(10) // pan 10 columns to the left!
vp.SetXOffset(0) // back to the left edge
To make the API more consistent, vertical scroll functions were also renamed,
and the old ones were deprecated (and will be removed in v2):
// Scroll n lines up/down:
func (m Model) LineUp(int) // deprecated
func (m Model) ScrollUp(int) // new!
func (m Model) LineDown(int) // deprecated
func (m Model) ScrollDown(int) // new!
// Scroll half page up/down:
func (m Model) HalfViewUp() []string // deprecated
func (m Model) HalfPageUp() []string // new!
func (m Model) HalfViewDown() []string // deprecated
func (m Model) HalfPageDown() []string // new!
// Scroll a full page up/down:
func (m Model) ViewUp(int) []string // deprecated
func (m Model) PageUp(int) []string // new!
func (m Model) ViewDown(int) []string // deprecated
func (m Model) PageDown(int) []string // new!
Note
In v2, these functions will not return lines []string
anymore, as it is no
longer needed due to HighPerformanceRendering
being deprecated as well.
Other improvements
The list
bubble got a couple of new functions: SetFilterText
,
SetFilterState
, and GlobalIndex
- which you can use to get the index of the
item in the unfiltered, original item list.
On textinput
, you can now get the matched suggestions and more with
MatchedSuggestions
and CurrentSuggestionIndex
.
To put the cherry on top, this release also includes numerous bug fixes.
You can read about each of them in the linked commits/PRs below.
Changelog
New Features
- d019ed3: feat(list): add SetFilterText and SetFilterState (#335) (@taigrr)
- 171a9d6: feat(list): implement GlobalIndex helper (#574) (@nobe4)
- 4382fdf: feat(textinput): expose matched suggestions and index (@luevano)
- 2d53a61: feat(viewport): horizontal scroll (#240) (@tty2)
- ea344ab: feat(viewport): horizontal scroll with mouse wheel (#761) (@UnseenBook)
Bug fixes
- f2434c3: Revert "fix(viewport): normalize method names" (@caarlos0)
- 8101a34: fix(ci): add lint and lint-sync workflows and update golangci.yml (#651) (@aymanbagabas)
- 54f28b6: fix(filepicker): properly scrolling filepicker (#753) (@caarlos0)
- 81d444a: fix(help): wrong full help sep rendering (@luevano)
- f439d83: fix(textarea): max height should not determine max lines (@meowgorithm)
- 8b55efb: fix(textarea): placeholder with chinese chars (#767) (@caarlos0)
- 8624776: fix(textinput): slicing outside cap (#532) (@MikaelFangel)
- c7f889e: fix(viewport): normalize method names (@caarlos0)
- 39668ec: fix(viewport): normalize method names (#763) (@caarlos0)
- 7ab08fb: fix(viewport): scroll to last line when borders (#706) (@caarlos0)
- 730f5a2: fix: debounce stopwatch and timer (@meowgorithm)
- bd2a5b0: fix: golangci-lint 2 fixes (#769) (@caarlos0)
- 9589cbc: fix: lint issues and disable predeclared linter (#614) (@aymanbagabas)
- 398e92c: fix: remove default character limit (@meowgorithm)
- 1bdd4c6: fix: stopwatch.Start() (#707) (@bevicted)
- 9a262e9: fix: use atomic for ids (#634) (@caarlos0)
Dependency updates
- 1797ac2: feat(deps): bump github.com/charmbracelet/bubbletea from 1.1.0 to 1.1.1 (#611) (@dependabot[bot])
- a9b780a: feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.0 to 0.13.1 (@dependabot[bot])
- db3514c: feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.1 to 1.0.0 (#655) (@dependabot[bot])
- 43aa82c: feat(deps): bump github.com/charmbracelet/x/ansi (#716) (@dependabot[bot])
- c1199d7: feat(deps): bump github.com/charmbracelet/x/ansi from 0.2.3 to 0.3.0 (#613) (@dependabot[bot])
- d3ac47d: feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.0 to 0.3.1 (#615) (@dependabot[bot])
- ed14316: feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.1 to 0.3.2 (#618) (@dependabot[bot])
Documentation updates
- cf3f46a: docs(list): fix grammar in doc comment and README (#627) (@oahshtsua)
- 9e5365e: docs: add example for ValidateFunc (#705) (@bashbunni)
- 87a4e45: docs: additional bubbles (#583) (@caarlos0)
- e3ce11a: docs: update charm & friends blurb (#703) (@bashbunni)
- 178590b: docs: update contributing guidelines (#640) (@bashbunni)
Other work
- 0f9e38c: Don't render suggestions when textinput is not focused. (@elProxy)
- e5296a2: ci: fix goreleaser config (#668) (@caarlos0)
- 76433f7: ci: fix linting on windows (@andreynering)
- d91c9aa: ci: rm .golangci-soft.yml (@caarlos0)
- 2f49443: ci: sync dependabot config (#734) (@charmcli)
- 7a6b190: ci: sync dependabot config (#736) (@charmcli)
- d58217b: ci: sync golangci-lint config (#750) (@github-actions[bot])
- cce8481: ci: sync golangci-lint config (#770) (@github-actions[bot])
- 0305695: ci: test on oldstable and stable go versions, automerge dependabot (#755) (@caarlos0)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
-
It is disabled by default in v1, but will be enabled in v2. ↩
v2.0.0-beta.1
Ready for Bubbles v2 Beta?
We're excited to share Bubbles v2.0.0-beta.1
with you! This release builds on the last alpha release and includes a few more API changes and improvements. As usual, the upgrade path is pretty straightforward, but let us know if you have any questions.
Bear in mind you’ll want to use this updates alongside v2.0.0-beta.1
versions of Bubble Tea and Lip Gloss.
# Collect them all
go get github.com/charmbracelet/[email protected]
go get github.com/charmbracelet/[email protected]
go get github.com/charmbracelet/[email protected]
Let’s dive in!
The Init you know and love is back
After spending time with many different forms of Init
, we've decided the v1 signature is the right way to go after all. Init
is a bit too redundant for our tastes given that initialization is already happening in New
. Note that this change is in alignment with current shape of Init
in Bubble Tea.
// Before in alpha.2
func (m Model) Init() (Model, tea.Cmd)
// After
func (m Model) Init() tea.Cmd
What’s Changed?
In general, we've made a lot of small changes to Bubbles for consistency and future proofing. There are a lot of changes here, but we've found upgrading pretty easy regardless. If you're having trouble with anything let us know in the discussions.
🥕 List
Styles.FilterCursor
andStyles.FilterPrompt
have been removed and consolidated into the newStyles.Filter
👟 Progress
- The
Model.EmptyColor
andModel.FullColor
members have been changed fromstring
toimage/color.Color
Model.Update
now returns aModel
instead of atea.Model
WithColorProfile
has been removed (Bubble Tea now manages this automatically)WithSolidFill
now takes ancolor.Color
(from theimage
package) instead of astring
✏️ Textarea
The big change to textarea
is that you now have the option to use a real cursor per Bubble Tea v2.0.0-beta1
. The feature is opt-in, so by default if you don't do anything your programs will continue to use the easy-breezy virtual cursor.
To get an idea of how to use a real cursor with textarea
see
the v2 textarea example.
Model.Cursor
is now a function that returns a*tea.Cursor
(formerly, it was the virtual cursor model)Model.SetCursor
has been renamed toModel.SetCursorColumn
CursorStyle
has been added to define the cursor styleModel.VirtualCursor
(abool
) has been added to define whether the textarea should render a virtual cursor; set tofalse
when using a real cursorStyles.Cursor
has been added to define the cursor style
📜 Textinput
Most of the changes in textinput
are to bring it to parity with textarea
,
including support for a real cursor. For an example illustrating the use of
textinput
with a real cursor see
the v2 textinput example.
Most styling has been moved into StyleState
which contains styling for
focused and blurred states.
Model.CompletionStyle
has been moved toStylesState.Suggestion
Model.PlaceholderStyle
has been moved toStylesState.Placeholder
Model.PromptStyle
has been and moved toStyleState.Prompt
Model.TextStyle
has been moved toStyleState.Text
CursorStyle
has been added to define the cursor styleModel.VirtualCursor
was added; use it to disable the virtual cursorModel.Styles
(andStyles
) was added to house all styling.StyleState
was added to manage styling for focused and blurred statesModel.Cursor
is now afunc() *tea.Cursor
for real cursor support (formerly, it was the virtual cursor model)DefaultStyles
has been addedDefaultDarkStyles
has been addedDefaultLightStyles
has been added
📦 Viewport
The new viewport
now supports horizontal scrolling as well as setting a custom gutter column! You can also now scroll horizontally with the left and right arrow keys. Finally, you can now highlight parts of what's being viewed based on regex.
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 things:
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
You may now also let viewport do the soft wrapping for you:
vp := viewport.New()
vp.SoftWrap = true
vp.SetContent("hello world from a very long line")
But, if you need more fine control on soft wrapping, you can also use the SetContentLines
method. This method allows you to set "virtual lines", which may contain \n
in them. These lines are automatically treated as soft wraps, and scrolling also takes then into consideration.
Like details?
Here’s the full changelog since v2.0.0-alpha.2
💝 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.
Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة
v2.0.0-alpha.2
Smells like Bubbles v2 Alpha 2!
Thanks for trying out Bubbles v2.0.0-alpha.2
! This release was designed to work with Bubble Tea and Lip Gloss v2 alphas with the same tag, so make sure you catch ’em all:
go get github.com/charmbracelet/bubbletea/[email protected]
go get github.com/charmbracelet/bubbles/[email protected]
go get github.com/charmbracelet/lipgloss/[email protected]
There are a lot of small API changes in this release, around two general ideas:
- Consistency across Bubbles
- Manual light/dark background management for Lip Gloss v2 (see below)
We've found upgrading pretty easy, especially with a linter, but let us know how it goes for you. Read on for the breakdown.
Note
When in doubt, check the examples for reference: they've all been updated for v2.
A Note on Light and Dark Styles
Some Bubbles, like help
, offer defaults for light and dark background colors. Selecting one or the other now a manual process, and you have two options.
🎩 The Best Way
Ideally, you have Bubble Tea query the background color for you. This means that you'll be properly querying the correct input and outputs with your program, and the query will happen in lockstep with the application.
// Query for the background color.
func (m model) Init() (tea.Model, tea.Cmd) {
return m, tea.RequestBackgroundColor
}
// Listen for the response and initialize your styles accordigly.
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.BackgroundColorMsg:
// Initialize your styles now that you know the background color.
m.help = help.DefaultStyles(msg.IsDark())
return m, nil
}
}
If you're using Wish you must do it this way in to get the background color of the client.
🤠 The Quick Way
The quick way is to use detect the background color via 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 will not return the background color of the client (because it's running locally on the server).
import "github.com/charmbracelet/lipgloss/v2/compat"
var hasDarkBG = compat.HasDarkBackground()
func main() {
var m model
h := help.New()
h.Styles = help.DefaultStyles(hasDarkBG)
// And so on...
m.help = h
}
For details on the compat
package see the Lip Gloss v2.0.0-alpha.2 release notes.
👀 Also Note
You can also just apply defaults manually.
h.Styles = help.DefaultLightStyles() // light mode!
h.Styles = help.DefaultDarkStyles() // jk dark mode
What’s Changed: the Laundry List
Filepicker
- Removed:
DefaultStylesWithRenderer()
. Lip Gloss is pure now, so just useDefaultStyles()
. Model.Height
has been broken into a getter and setter; useModel.SetHeight(int)
andModel.Height() int
instead
Help
help
now defaults to using colors for dark backgrounds. You can manually change them with DefaultLightStyles()
and DefaultDarkStyles()
:
h := help.New()
h.Styles = help.DefaultDarkStyles() // dark mode
h.Styles = help.DefaultLightStyles() // light mode
Or, just detect the background color and apply the appropriate set of styles accordingly:
func (m Model) Init() (tea.Model, tea.Cmd) {
// Ask for the background color.
return m, tea.RequestBackgroundColor
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.BackgroundColorMsg:
// We know the background color, so let’s update our styling.
m.help.Styles = help.DefaultStyles(msg.IsDark())
}
}
List
DefaultStyles()
now takes a boolean to determine whether it should be rendered with light or dark styles:DefaultStyles(isDark bool)
DefaultItemStyles()
now takes a boolean to determine whether it should be rendered with light or dark styles:DefaultItemStyles(isDark bool)
Paginator
- The global variable
DefaultKeyMap
is now a function:func DefaultKeyMap() KeyMap
Progress
Model.Width
has been broken into a getter and setter; useModel.SetWidth(int)
andModel.Width() int
instead
p := progress.New()
// Before
p.Width = 25
fmt.Printf("%w is a good width", p.Width)
// After
p.SetWidth(25)
fmt.Printf("%w is a good width", p.Width())
Stopwatch
NewWithInterval(time.Duration)
has been removed. Pass anOption
toNew()
instead:New(WithInterval(time.Duration))
Table
Model.Width
has been broken into a getter and setter; useModel.SetWidth(int)
andModel.Width() int
insteadModel.Height
has been broken into a getter and setter; useModel.SetHeight(int)
andModel.Height() int
instead
Textarea
- The global variable
DefaultKeyMap
is now a function:func DefaultKeyMap() KeyMap
Model.FocusedStyle
andModel.BlurredStyle
have been replaced byModel.Styles.Focused
andModel.Styles.Blurred
DefaultStyles() (blurred, focused Style)
is nowDefaultStyles(isDark bool) Styles
. Seehelp
above for an example on how to work with this.
Textinput
- The global variable
DefaultKeyMap
is now a function:func DefaultKeyMap() KeyMap
Model.Width
has been broken into a getter and setter; useModel.SetWidth(int)
andModel.Width() int
instead
Timer
NewWithInterval(time.Duration)
has been removed. Pass anOption
toNew()
instead:New(time.Duration, WithInterval(time.Duration))
Viewport
Model.Width
andModel.Height
have been replaced with getters and setters:
m := v.New()
// Before
vp.Width = 40
vp.Height = 80
fmt.Println("%d is my favorite width", vp.Width)
// After
vp.SetWidth(40)
vp.SetHeight(80)
fmt.Println("%d is my favorite width", vp.Width())
New()
doesn’t have deafult args anymore:New(width, height int)
is nowNew(...Option)
. To set an initial width and height do one of the following:
// Use functional arguments:
vp := viewport.New(viewport.WithWidth(40), viewport.WithHeight(80)
// Or just:
vp := viewport.New()
vp.SetWidth(40)
vp.SetHeight(80)
Changelog
- feat(textinput): expose matched suggestions and index by @luevano in #556
- fix: use atomic package for ids by @caarlos0 in #634
- docs(list): fix grammar in doc comment and README by @oahshtsua in #627
- chore: Remove duplicate and redundant code by @cuishuang in #626
- feat(list): implement GlobalIndex helper by @nobe4 in #574
- fix(help): wrong full help sep rendering by @luevano in #554
- chore(help): add small full help test by @meowgorithm in #636
- docs: update contributing guidelines by @bashbunni in #640
- (v2) refactor!: viewport: remove deprecated HighPerformanceRendering by @aymanbagabas in #619
- (v2) refactor!: remove deprecated references by @aymanbagabas in #620
- feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.0 to 0.13.1 by @dependabot in #645
- chore(lint): fix and suppress all soft lint issues; update directives by @meowgorithm in #647
- (v2) tidying up by @meowgorithm in #649
- (v2) chore: minimal updates for Lip Gloss v2 by @meowgorithm in #652
- fix(ci): add lint and lint-sync workflows and update golangci.yml by @aymanbagabas in #651
- (v2) consistency and best practices by @meowgorithm in #656
- feat(deps): bump github.com/charmbracelet/lipgloss from 0.13.1 to 1.0.0 by @dependabot in #655
- Sync golangci-lint config by @github-actions in #660
- (v2) expose function for choosing light or dark styles by @meowgorithm in #663
- fix: debounce stopwatch and timer by @meowgorithm in #664
New Contributors
- @luevano made their first contribution in #556
- @oahshtsua made their first contribution in #627
- @cuishuang made their first contribution in #626
- @nobe4 made their first contribution in #574
- @github-actions made their first contribution in #660
Full Changelog: v2.0.0-alpha.1...v2.0.0-alpha.2
💝 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.
v2.0.0-alpha.1
Changelog
New Features
- d019ed3: feat(list): add SetFilterText and SetFilterState (#335) (@taigrr)
- 0fdf5f5: feat: use bubbletea/v2 (@aymanbagabas)
Bug fixes
- 9589cbc: fix: lint issues and disable predeclared linter (#614) (@aymanbagabas)
- f81fd52: fix: spacebar keybinding is now "space" instead of a literal space (@aymanbagabas)
Dependency updates
- 1797ac2: feat(deps): bump github.com/charmbracelet/bubbletea from 1.1.0 to 1.1.1 (#611) (@dependabot[bot])
- c1199d7: feat(deps): bump github.com/charmbracelet/x/ansi from 0.2.3 to 0.3.0 (#613) (@dependabot[bot])
- d3ac47d: feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.0 to 0.3.1 (#615) (@dependabot[bot])
- ed14316: feat(deps): bump github.com/charmbracelet/x/ansi from 0.3.1 to 0.3.2 (#618) (@dependabot[bot])
Other work
- 8972b56: feat!: make Init return the model (@aymanbagabas)
- a93bfef: feat!: use bubbletea@v2-exp (@aymanbagabas)
- a2602f8: feat!: v2: move to v2 module (@aymanbagabas)
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.20.0
Focus. Breathe.
This features support for Bubble Tea's new focus-blur feature as well as a quality-of-life update to paginator
. Enjoy!
Focus
You heard that right. Focus-blur window events are now enabled for textinput
and textarea
which were recently added to Bubble Tea v1.1.0. As long as WithReportFocus
is enabled in your Program you'll automatically get nicer inputs.
To enable focus reporting:
p := tea.NewProgram(model{}, tea.WithReportFocus())
Remember to stay focused and hydrated!
Paginator opts
Speaking of functional arguments, paginator
also received some some new quality-of-life startup options, courtesy @nervo.
p := paginator.New(
paginator.WithPerPage(42),
paginator.WithTotalPages(42),
)
Of course, you can still set the values on the model directly too:
p := paginator.New()
p.PerPage = 42
p.TotalPages = 24
Happy paging!
Changelog
New!
- d3bd075: feat(cursor): focus/blur support (#581) (@caarlos0)
- 5110925: feat: Introduce paginator options (@nervo)
Deps
- 3eaf8da: feat(deps): bump github.com/charmbracelet/bubbletea from 0.27.0 to 1.0.0 (#604) (@dependabot[bot])
- 6fc27e9: feat(deps): bump github.com/charmbracelet/bubbletea from 1.0.0 to 1.1.0 (#607) (@dependabot[bot])
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.19.0
Bugs? Squashed (along with a few nice lil’ features).
Community-Driven Development?! Yep, the majority of the changes in this release were done by the community. Thank you all for your contributions that made this release possible.
Progress: custom chars
You can now customize the filled and empty characters of the progress bar.
p := progress.New(progress.WithFillCharacters('>', '.'))
Table improvements
Help is on the way
Table now includes a short and full help view so it's easier than ever to tell your users how to interact with the table.
// Render a table with its help.
t := table.New()
view := t.View() + "\n" + t.HelpView()

Accessing columns
You can also now get the table's columns (this already existed for rows).
package table
// Columns returns the current columns.
func (m Model) Columns() []Column
List: page navigation is fixed!
Previously, list.NextPage()
and list.PrevPage()
didn't work because the methods did not have pointer receivers. We've fixed this…by making them pointer receivers!
package progress
// NextPage moves to the next page, if available.
func (m *Model) NextPage()
// PrevPage moves to the previous page, if available.
func (m *Model) PrevPage()
What’s Changed
Changed
- Textarea: Improve setting width by @mikelorant in #496
- Textinput: fix out of range panic if no matched suggestions by @rdnt in #473
- List: Fix no-op list pagination functions by @nekopy in #458
- Table: Clarify position constant in JoinHorizontal by @aditipatelpro in #577
- Progress: make full/empty fill characters configurable by @rwinkhart in #409
- Dependencies: switch to x/ansi for text manipulation by @aymanbagabas in #505
Added
- Textarea: add help to textarea key bindings by @TravisYeah in #418
- Textarea: Add multiline placeholder by @mikelorant in #302
- Table: Add column return function by @abeleinin in #369
- Table: Implement help.Keymap interface and add quit mapping by @prgres in #440
- Ctrl+Left/Right for WordForward/Backward by @maaslalani in #387
- Use goreleaser for releases by @aymanbagabas in #526
Fixed
- Table: Render Row Tests by @maaslalani in #487
- Table: Only render columns with a positive width by @fabio42 in #465
- Table: Fix inheritence of SelectedStyle in StyleFunc by @gabrielfu in #539
- Table: Don't include header height in the total table size by @prgres in #434
- Table: Fix premature viewport scroll by @dzeleniak in #429
- Textarea: Fix end of buffer character by @mikelorant in #491
- Textarea: Set textarea default EndOfBufferCharacter to ' ' by @blvrd in #510
- Textarea: End of Buffer alignment by @maaslalani in #486
- Textinput: don't block input on validation by @GabrielNagy in #185
- Viewport: Fix division by zero in scrollpercentage by @zMoooooritz in #494
- Help: Fix centering by @gabe565 in #516
- Progress: Stop spring defaults from overriding WithStringOptions by @nervo in #540
- Cursor: Make SetMode method in cursor library handle invalid mode values correctly by @anirudhaCodes in #477
Test coverage ✅
- Add tests for textarea view by @mikelorant in #485
- Add tests for paginator by @anirudhaCodes in #480
- Add tests for textInput Tests by @KevM in #500
- Improve textarea tests by @mikelorant in #490
New Contributors
- @rdnt made their first contribution in #473
- @rwinkhart made their first contribution in #409
- @mikelorant made their first contribution in #485
- @anirudhaCodes made their first contribution in #480
- @nekopy made their first contribution in #458
- @TravisYeah made their first contribution in #418
- @abeleinin made their first contribution in #369
- @fabio42 made their first contribution in #465
- @prgres made their first contribution in #440
- @zMoooooritz made their first contribution in #494
- @dzeleniak made their first contribution in #429
- @KevM made their first contribution in #500
- @gabe565 made their first contribution in #516
- @blvrd made their first contribution in #510
- @nervo made their first contribution in #540
- @gabrielfu made their first contribution in #539
- @aditipatelpro made their first contribution in #577
Full Changelog: v0.18.0...v0.19.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.18.0
Textarea, but faster
This release features several fixes and big performance improvements for the textarea
bubble.
What's Changed
New
- Optional File Permissions and File Size by @maaslalani in #471
- Add Paginator OnFirstPage method by @maaslalani in #463
Improved
- Implement Memoization to Speed Up Textarea Rendering by @wesen in #427
- refactor(textinput): reduce allocations by @naglis in #413
- Use
uniseg.StringWidth
by @maaslalani in #462
Fixed
- fix(textarea): correctly trim incoming paste by @muesli in #469
- fix(textinput): Placeholder No Longer Changes Width + Paste Calculation by @hopefulTex in #451
- fix(viewport): pad width to contentWidth by @ivanvc in #388
New Contributors
- @seanbanko made their first contribution in #442
- @hopefulTex made their first contribution in #451
- @ivanvc made their first contribution in #388
- @wesen made their first contribution in #427
Full Changelog: v0.17.1...v0.18.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.17.1
Bumping Bubble Tea
This is just a little update to update to the latest version of Bubble Tea.
What's Changed
- feat: upgrade bubbletea and remove deprecated code by @aymanbagabas in #448
Full Changelog: v0.17.0...v0.17.1
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.17.0
Text input autocompletions and various improvements
Autocompletion in Text Input
So @toadle wanted textinput
s to support autocompletion in a ghost-text kind of a way. Rather than wait for us to do it he did what any dedicated open source developer would: he sent a PR! And now we can all benefit from his hard work.
Autocompletion is super easy to use:
ti := textinput.New()
ti.SetSuggestions([]string{"meow", "purr"})
By default you can press ctrl+n and ctrl+p to cycle through suggestions, but those keybindings can be changed as you, the application developer, see fit. For details check out textinput.SetSuggestions
and the corresponding KeyMap
in the docs.
Is the progress bar done yet?
@yrashk acutely noticed that to nicely transition from one state to another after an animated progress bar fills up it's helpful to know when the animated has finished animating before transitioning. To solve for this he added an IsAnimating
method to the progress
model. Thanks, @yrashk!
Changelog
New!
- Support suggestions and autocompletion in textinput by @toadle in #407
- Add method for determining if progress bar is animating by @yrashk in #386
Improved
- Update fuzzy library by @caarlos0 in #379
- Reduce allocations in
filterItems
by @naglis in #396 - Improve message when list is empty by @maaslalani in #393
Fixed
Full Changelog: v0.16.1...v0.17.0
New Contributors
- @yrashk made their first contribution in #386
- @naglis made their first contribution in #391
- @lc-1010 made their first contribution in #421
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.
v0.16.1
File Picker Bubble 📁 🫧
This release introduces a brand new filepicker
bubble, new features, and a tonne of bugfixes.
Let us know what you think, ask questions, or just say hello in our Discord.
For a quick start on how to use this bubble, take a look at the Example code.
Getting Started
Create a new file picker and add it to your Bubble Tea model.
picker := filepicker.New()
picker.CurrentDirectory, err = os.UserHomeDir()
if err != nil {
// ...
}
m := model{
picker: picker,
// ...
}
Initialize the file picker in your Model
's Init
function.
func (m model) Init() tea.Cmd {
return tea.Batch(
m.picker.Init(),
// ...
)
}
Update the filepicker as any other bubble in the Update
function.
After the picker.Update
, use the DidSelectFile(msg tea.Msg)
function to perform an action when the user selects a valid file.
You may allow only certain file types to be selected with the AllowedTypes
property and allow directories to be selected with the DirAllowed
property. To see the currently selected file/directory use the Path
property.
var cmd tea.Cmd
m.picker, cmd = m.picker.Update(msg)
// Did the user select a file?
if didSelect, path := m.picker.DidSelectFile(msg); didSelect {
// Get the path of the selected file.
return m, tea.Println("You selected: " + selectedPath)
}
return m, cmd
For the full example on how to use this bubble, take a look at the Example code.
New
- Filepicker: new bubble by @maaslalani in #343
- Textarea: max width/height configurable by @knz in #370
- Spinner: periods of ellipsis by @meowgorithm in #375
- List: infinite scrolling by @jon4hz in #316
Fixed
- app would crash if
deleteWordRight
was called at the end of line by @infastin in #313 - support pastes that end with a newline character by @knz in #314
- data corruption after multi-line input by @knz in #318
- Remove unused
BackgroundStyle
in TextInput by @savannahostrowski in #341 - add bounds checking to the
SelectedRow
by @MikaelFangel in #351 - fix(progress): last gradient color off by one by @residualmind in #338
- deprecate
CursorStyle
in favour ofCursor.Style
by @maaslalani in #365 - Reset blink only when
CursorBlink
by @remiposo in #378
New Contributors
- @infastin made their first contribution in #313
- @gzipChrist made their first contribution in #332
- @savannahostrowski made their first contribution in #341
- @MikaelFangel made their first contribution in #351
- @stefanbildl made their first contribution in #339
- @residualmind made their first contribution in #338
- @bashbunni made their first contribution in #359
- @squrki made their first contribution in #373
- @remiposo made their first contribution in #378
Full Changelog: v0.15.0...v0.16.0
Thoughts? Questions? We love hearing from you. Feel free to reach out on Twitter, The Fediverse, or on Discord.