charmed-bubbles 0.1.2

Common TUI components for bubbletea applications
Documentation

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

[dependencies]
bubbles = { package = "charmed-bubbles", version = "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 bubbles::textinput::TextInput;

let mut input = TextInput::new();
input.set_placeholder("Search...");
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:

fn update(&mut self, msg: Message) -> Cmd {
    self.input.update(msg.clone());
    self.list.update(msg);
    Cmd::none()
}

Styling

Components expose styling hooks via lipgloss. Use Style to customize colors, padding, borders, and layout.

API Overview

  • crates/bubbles/src/textinput.rs
  • crates/bubbles/src/textarea.rs
  • crates/bubbles/src/list.rs
  • crates/bubbles/src/table.rs
  • crates/bubbles/src/viewport.rs
  • crates/bubbles/src/spinner.rs
  • crates/bubbles/src/progress.rs
  • crates/bubbles/src/filepicker.rs

Troubleshooting

  • Component not receiving input: ensure you forward Message to it.
  • Weird layout: check component width/height settings and terminal size.
  • Styling not applied: verify you’re using lipgloss::Style helpers.

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.