feat: tree bubble - #893
Conversation
34a0a7b to
ba6f094
Compare
|
@andreynering I see 2.1 was released. Just checking, is this planned for 2.2? |
|
Anything else needed here @andreynering ? |
ba6f094 to
8519a5d
Compare
| s.nodeFunc = func(_ Nodes, _ int) lipgloss.Style { | ||
| return s.NodeStyle | ||
| } | ||
|
|
There was a problem hiding this comment.
dead code due to SetStyles overriding either way? (unsure)
There was a problem hiding this comment.
this will be overwritten only when the user calls SetStyles with styles.NodeStyleFunc, which the default don't set.
andrinoff
left a comment
There was a problem hiding this comment.
just a little more!
p.s. lint fails
| func (m Model) cursorView() string { | ||
| if m.cursorCharacter == "" { | ||
| return "" | ||
| } | ||
| cursor := strings.Split(strings.Repeat(" ", m.root.Size()), "") | ||
| cursor[m.yOffset] = m.cursorCharacter | ||
| return m.styles.CursorStyle.Render(lipgloss.JoinVertical(lipgloss.Left, cursor...)) | ||
| } |
There was a problem hiding this comment.
draws one cursor row per node, but the tree renders one row per line. those are the same number only if every node is exactly one line tall.
There was a problem hiding this comment.
Hmm I haven't tested multi line nodes. I can try and support that, but I never tested that. Is that something you're interested in?
A lot of the implementation assumes this, so it will probably not be straightforward, but it is a cool idea.
There was a problem hiding this comment.
2026-08-19.12-22-21.mp4
this is a nit, but at the same time i can imagine a user creating a multi-line node, or even having word-wrapping.
It shouldn't be that hard to fix, from what i've seen
There was a problem hiding this comment.
ok, I'll give it a shot.
Do note that it will make the yOffset calculation for each node more taxing though, since we'll need to call lipgloss.Height on each node.
There was a problem hiding this comment.
I've had at it for a couple of hours but couldn't find an elegant solution for multiline items.
When going "up" (to the previous item, not necessarily the parent) the tree, I would need to know the height of the previous item. I can maintain a bunch of pointers and maintain them and on every interaction update them. I couldn't manage to hack this.
I also tried modifying the current slow implementation of maintaning the yOffsets.
I faced an issue with scrolling the viewport. By how much should I scroll it when a line is 50 lines long? The user would probably want to scroll it independently of the tree. We'd then have to add more keybinds if we want.
Maybe there's some intuitive solution to this that I'm too tired to think of.
There was a problem hiding this comment.
I did end up hacking this with the existing yOffset implementation.
Not sure how I feel about the up/down not going to the previous/next item, but maybe it makes sense?
Screen.Recording.2026-08-19.at.22.52.40.mov
There was a problem hiding this comment.
hm, it seems like a clanky hack, where it does not go to the next/previous item... I'll try something out
|
@andrinoff I've fixed the small comments. For the two big comment, let me know how you want to proceed.
|
|
let's fix multi-lines. we can leave performance as is for now, i'll still be improving performance across elements |
|
@dlvhdr got it working! |
|
@andrinoff just tested it on |
refactor test: add basic tests
Signed-off-by: drew <me@andrinoff.com>
069bf4e to
52022cc
Compare
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [charm.land/bubbles/v2](https://github.com/charmbracelet/bubbles) | `v2.1.1` → `v2.2.1` |  |  | | [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) | `v2.0.8` → `v2.0.9` |  |  | | [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) | `v2.0.5` → `v2.0.6` |  |  | | [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) | `v1.14.49` → `v1.14.52` |  |  | --- ### Release Notes <details> <summary>charmbracelet/bubbles (charm.land/bubbles/v2)</summary> ### [`v2.2.1`](https://github.com/charmbracelet/bubbles/releases/tag/v2.2.1) [Compare Source](charmbracelet/bubbles@v2.2.0...v2.2.1) ### Tiny Monday bugfix Textarea element had a bug, where you used to be able to go 1 word backwards, even if there was nothing, which resulted in the whole TUI freezing. It was now fixed by [@​OxQuasar](https://github.com/OxQuasar)! #### Changelog ##### Fixed - [`f613411`](charmbracelet/bubbles@f613411): fix(textarea): stop word-left at input boundary ([#​1036](charmbracelet/bubbles#1036)) ([@​OxQuasar](https://github.com/OxQuasar)) ##### Docs - [`87d4458`](charmbracelet/bubbles@87d4458): docs: update godoc link in readme to new package ([@​meowgorithm](https://github.com/meowgorithm)) ##### Other stuff - [`10489b5`](charmbracelet/bubbles@10489b5): readme: drop tree section for now ([@​meowgorithm](https://github.com/meowgorithm)) - [`4909481`](charmbracelet/bubbles@4909481): v2.2.1 ([@​andrinoff](https://github.com/andrinoff)) *** <a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a> Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@​charmcli), [Bluesky](https://bsky.app/profile/charm.land). ### [`v2.2.0`](https://github.com/charmbracelet/bubbles/releases/tag/v2.2.0) [Compare Source](charmbracelet/bubbles@v2.1.1...v2.2.0) ### A new Bubble and some new Textarea stuff There are a couple nice features in today's release. Let's check em out! #### If a tree falls in the forest… At last, the tree Bubble from all star contributor [@​dlvhdr](https://github.com/dlvhdr)’s is here! He built it for [DiffNav](https://github.com/dlvhdr/diffnav) and graciously contributed to Bubbles. We've been working with Dolev for a long time and were totally stoked when he offerd to contribute. <p><img width="500" src="https://github.com/user-attachments/assets/10f36c36-4669-45ef-b957-f214ca27c34f" /></p> #### Select all, ctrl+c, ctrl+v…done! Our own [@​andrinoff](https://github.com/andrinoff) added a bunch of awesome stuff to Textarea, including the long awaited *text selection*. Select, copy, and cut your way into mini text editing. <p><img width="600" src="https://github.com/user-attachments/assets/49b241cb-468a-483a-8ace-5d0742869cd9" /></p> For more info see [the docs](https://pkg.go.dev/charm.land/bubbles/v2@​v2.2.0/textarea). And special thanks to [@​zoriya](https://github.com/zoriya) for adding <kbd>ctrl+left/right</kbd> bindings. xoxo, Charm! 💌 #### Changelog ##### New! - [`8cea431`](charmbracelet/bubbles@8cea431): feat(textarea): support ctrl + left/right/backspace ([#​1020](charmbracelet/bubbles#1020)) ([@​zoriya](https://github.com/zoriya)) - [`037ad37`](charmbracelet/bubbles@037ad37): feat: textarea selection ([#​1029](charmbracelet/bubbles#1029)) ([@​andrinoff](https://github.com/andrinoff)) - [`e97af08`](charmbracelet/bubbles@e97af08): feat: tree bubble ([#​893](charmbracelet/bubbles#893)) ([@​dlvhdr](https://github.com/dlvhdr)) ##### Fixed - [`6484e49`](charmbracelet/bubbles@6484e49): fix(filepicker): don't blank the view when height is unset ([#​1026](charmbracelet/bubbles#1026)) ([@​andrinoff](https://github.com/andrinoff)) ##### Other stuff - [`355f960`](charmbracelet/bubbles@355f960): ci: sync dependabot config ([#​896](charmbracelet/bubbles#896)) ([@​charmcli](https://github.com/charmcli)) - [`ef8af03`](charmbracelet/bubbles@ef8af03): v2.2.0 ([@​andrinoff](https://github.com/andrinoff)) *** <a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a> Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@​charmcli), [Bluesky](https://bsky.app/profile/charm.land). </details> <details> <summary>charmbracelet/bubbletea (charm.land/bubbletea/v2)</summary> ### [`v2.0.9`](https://github.com/charmbracelet/bubbletea/releases/tag/v2.0.9) [Compare Source](charmbracelet/bubbletea@v2.0.8...v2.0.9) ### Small patches 🩹 #### Keybinds missing! MouseButton11 and media record buttons were improperly handled, now fixed! (thanks to [@​Ricardo-M-L](https://github.com/Ricardo-M-L) and [@​bunlongheng](https://github.com/bunlongheng)) #### Weird UI artifacts with some terminals 👽 Sometimes, when switching between tabs in your terminal for example, the screen would not clear, now fixed! ... And some small corrections to docs! Happy coding 🤖 #### Changelog ##### Fixed - [`dc4b017`](charmbracelet/bubbletea@dc4b017): fix(key): map media record to ultraviolet code ([#​1757](charmbracelet/bubbletea#1757)) ([@​Ricardo-M-L](https://github.com/Ricardo-M-L)) - [`1862dfb`](charmbracelet/bubbletea@1862dfb): fix: assign MouseButton11 = uv.MouseButton11 ([#​1754](charmbracelet/bubbletea#1754)) ([@​bunlongheng](https://github.com/bunlongheng)) - [`930e18c`](charmbracelet/bubbletea@930e18c): fix: don't panic in ProgressBarState.String() for out-of-range values ([#​1748](charmbracelet/bubbletea#1748)) ([@​ankit090701](https://github.com/ankit090701)) - [`faf4dcf`](charmbracelet/bubbletea@faf4dcf): fix: pendingErase in cursedRenderer ([#​1755](charmbracelet/bubbletea#1755)) ([@​andrinoff](https://github.com/andrinoff)) - [`0d3e281`](charmbracelet/bubbletea@0d3e281): fix: restore kitty keyboard stack on exit ([#​1750](charmbracelet/bubbletea#1750)) ([@​deepakganesh78](https://github.com/deepakganesh78)) - [`0ef9fc9`](charmbracelet/bubbletea@0ef9fc9): fix: typo in doc ([#​1756](charmbracelet/bubbletea#1756)) ([@​andrinoff](https://github.com/andrinoff)) ##### Docs - [`d40db14`](charmbracelet/bubbletea@d40db14): docs: fix background color detection example in doc comment ([@​meowgorithm](https://github.com/meowgorithm)) - [`882727b`](charmbracelet/bubbletea@882727b): docs: fix links to tutorials & examples ([#​1645](charmbracelet/bubbletea#1645)) ([@​mhdna](https://github.com/mhdna)) ##### Other stuff - [`708ee75`](charmbracelet/bubbletea@708ee75): ci: fix examples workflow ([#​1734](charmbracelet/bubbletea#1734)) ([@​kobihikri](https://github.com/kobihikri)) - [`351d215`](charmbracelet/bubbletea@351d215): ci: sync dependabot config ([#​1763](charmbracelet/bubbletea#1763)) ([@​charmcli](https://github.com/charmcli)) - [`6fb1f47`](charmbracelet/bubbletea@6fb1f47): examples/sequence: fix milisecond typo in SleepPrintln ([@​makoto-developer](https://github.com/makoto-developer)) - [`73b6d91`](charmbracelet/bubbletea@73b6d91): v2.0.9 ([@​andrinoff](https://github.com/andrinoff)) *** <a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a> Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@​charmcli), [Bluesky](https://bsky.app/profile/charm.land). </details> <details> <summary>charmbracelet/lipgloss (charm.land/lipgloss/v2)</summary> ### [`v2.0.6`](https://github.com/charmbracelet/lipgloss/releases/tag/v2.0.6) [Compare Source](charmbracelet/lipgloss@v2.0.5...v2.0.6) ### Devanagari, auto-grapheme mode, and more Hi! The big news in this release is that Lip Gloss now properly renders Devanagari (Hindi)! Beyond that—or perhaps as a result—Lip Gloss will now switch to mode 2027 for grapheme support when possible. There's other good stuff too. Let's go! #### क्या हाल है? Hindi speakers, it's about time! Lip Gloss and Ultraviolet now properly renders Devanagari. That means Bubble Tea will as well. <img width="434" height="198" alt="Screenshot 2026-08-12 at 10 12 14" src="https://github.com/user-attachments/assets/9d7e58be-baf6-425c-ae4e-9aafde1d9a89" /> This brings us to… #### Cyberpunk 2027 Lip Gloss (and Ultraviolet) now asks the terminal at startup whether it supports Unicode core mode (DEC mode 2027), and when it does, measures widths the same way the terminal does. We did this for Devanagari but it also means Emojis and things render better now too. Let's go! #### Shrinky tables: not anymore Columns no longer shrink to zero width. Thanks, [@​taciturnaxolotl](https://github.com/taciturnaxolotl)! *** #### Changelog ##### Fixed - [`d231906`](charmbracelet/lipgloss@d231906): fix(table): prevent columns from shrinking to zero width ([#​671](charmbracelet/lipgloss#671)) ([@​taciturnaxolotl](https://github.com/taciturnaxolotl)) *** <a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a> Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@​charmcli), [Bluesky](https://bsky.app/profile/charm.land). </details> <details> <summary>mattn/go-sqlite3 (github.com/mattn/go-sqlite3)</summary> ### [`v1.14.52`](https://github.com/mattn/go-sqlite3/releases/tag/v1.14.52): 1.14.52 [Compare Source](mattn/go-sqlite3@v1.14.51...v1.14.52) #### What's Changed - Replace schema probe with eager first step for cached statements by [@​mattn](https://github.com/mattn) in [#​1454](mattn/go-sqlite3#1454) **Full Changelog**: <mattn/go-sqlite3@v1.14.51...v1.14.52> ### [`v1.14.51`](https://github.com/mattn/go-sqlite3/releases/tag/v1.14.51): 1.14.51 [Compare Source](mattn/go-sqlite3@v1.14.50...v1.14.51) #### What's Changed - fix: Exec returns wrong arg count in "not enough args" error by [@​semihbkgr](https://github.com/semihbkgr) in [#​1396](mattn/go-sqlite3#1396) - refactor: Clean up deprecated // +build legacy build tags by [@​zxysilent](https://github.com/zxysilent) in [#​1428](mattn/go-sqlite3#1428) - Fixed som typos and wrappings in sqlite3\_func\_crypt.go documentation. by [@​kberov](https://github.com/kberov) in [#​1367](mattn/go-sqlite3#1367) - Replace copy-on-write handle map with sync.Map by [@​mattn](https://github.com/mattn) in [#​1453](mattn/go-sqlite3#1453) - Avoid per-row goroutines for query cancellation by [@​bradengroom](https://github.com/bradengroom) in [#​1444](mattn/go-sqlite3#1444) - Flush statement cache when the schema changes by [@​mattn](https://github.com/mattn) in [#​1452](mattn/go-sqlite3#1452) #### New Contributors - [@​semihbkgr](https://github.com/semihbkgr) made their first contribution in [#​1396](mattn/go-sqlite3#1396) - [@​zxysilent](https://github.com/zxysilent) made their first contribution in [#​1428](mattn/go-sqlite3#1428) - [@​kberov](https://github.com/kberov) made their first contribution in [#​1367](mattn/go-sqlite3#1367) - [@​bradengroom](https://github.com/bradengroom) made their first contribution in [#​1444](mattn/go-sqlite3#1444) **Full Changelog**: <mattn/go-sqlite3@v1.14.50...v1.14.51> ### [`v1.14.50`](https://github.com/mattn/go-sqlite3/releases/tag/v1.14.50): 1.14.50 [Compare Source](mattn/go-sqlite3@v1.14.49...v1.14.50) #### What's Changed - Handle NULL and BLOB values in json example Scan by [@​mattn](https://github.com/mattn) in [#​1441](mattn/go-sqlite3#1441) - Add workflow to create releases on tag push by [@​mattn](https://github.com/mattn) in [#​1443](mattn/go-sqlite3#1443) - fix: keep vtab handle registered when xDestroy fails by [@​canesin](https://github.com/canesin) in [#​1446](mattn/go-sqlite3#1446) #### New Contributors - [@​canesin](https://github.com/canesin) made their first contribution in [#​1446](mattn/go-sqlite3#1446) **Full Changelog**: <mattn/go-sqlite3@v1.14.49...v1.14.50> </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My43My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNzMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Reviewed-on: https://forgejo.internal/forgejo_admin/maximus/pulls/22
Co-authored-by: Dolev Hadar <dolev@komodor.io> Co-authored-by: drew <me@andrinoff.com> Signed-off-by: drew <me@andrinoff.com>
CONTRIBUTING.md.