Bubbles
Pre-built TUI components for bubbletea: inputs, lists, tables, viewports, and more.
TL;DR
The Problem: Building a robust TUI requires a lot of reusable widgets.
The Solution: Bubbles provides a curated component suite that already
implements Model and integrates with bubbletea and lipgloss.
Why Bubbles
- Composable: components are models you can embed and update.
- Consistent: shared styling and event handling.
- Productive: avoids rewriting common UI widgets.
Role in the charmed_rust (FrankenTUI) stack
Bubbles sits directly above bubbletea and provides reusable components. It is
used by huh (forms), glow (markdown reader), and the demo showcase.
Crates.io package
Package name: charmed-bubbles
Library crate name: bubbles
Installation
[]
= { = "charmed-bubbles", = "0.1.2" }
Component Catalog
textinput: single-line text entry.textarea: multi-line text editing.list: selectable lists with optional filtering.table: fixed-width tabular rendering.spinner: loading indicators.progress: progress bars.viewport: scrollable content area.filepicker: filesystem navigation.paginator: pagination control.timer: countdown timers.stopwatch: elapsed time counters.help: keybinding hints.cursor: shared cursor utilities.
Quick Start (Text Input)
use TextInput;
let mut input = new;
input.set_placeholder;
input.focus;
// in update:
// input.update(msg);
// in view:
// input.view()
Integration Pattern
Each component implements a bubbletea-compatible update/view pattern. You usually wire them into a parent model and forward messages:
Styling
Components expose styling hooks via lipgloss. Use Style to customize colors,
padding, borders, and layout.
API Overview
crates/bubbles/src/textinput.rscrates/bubbles/src/textarea.rscrates/bubbles/src/list.rscrates/bubbles/src/table.rscrates/bubbles/src/viewport.rscrates/bubbles/src/spinner.rscrates/bubbles/src/progress.rscrates/bubbles/src/filepicker.rs
Troubleshooting
- Component not receiving input: ensure you forward
Messageto it. - Weird layout: check component width/height settings and terminal size.
- Styling not applied: verify you’re using
lipgloss::Stylehelpers.
Limitations
- Components assume terminal I/O and bubbletea’s message loop.
- Some components require explicit sizing to render correctly.
FAQ
Can I use a component outside bubbletea?
They’re designed for bubbletea’s update/view model; you can adapt if needed.
Are all components themeable?
Yes, through lipgloss styles and configuration hooks.
About Contributions
Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via gh and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.
License
MIT. See LICENSE at the repository root.