Components
Components keep reusable meaning separate from terminal presentation. Build an
immutable data value, then ask a Theme or an explicit presentation policy to
compose it into a View.
See the component catalog
Section titled “See the component catalog”Run the complete Components quickstart ↓
| Content | Data | Canonical presentation |
|---|---|---|
| Ordered or nested entries | List<T> |
theme.list(&list) |
| Rows and columns with headers and rules | Table<Row> |
theme.table(&table) |
| A hierarchy | Tree<T> |
theme.tree(&tree) |
| Position inside finite content | Scrollbar |
theme.scrollbar(&scrollbar) |
How components become Views
Section titled “How components become Views”Every core component has three layers:
Component meaning and presentation policy are composed into the same renderer-neutral View used everywhere else.
- dataSemantic dataContent and semantic state
- plusdataPresentation policyFormatting, glyphs, spacing, borders, and styles
- applyprocessComposeSnapshot data and presentation together
- resultdataViewAn immutable renderer-neutral value
- The data value owns content and semantic state, such as list nesting or a scrollbar’s content and viewport lengths.
- The presentation owns formatting, glyphs, spacing, borders, and styles.
- Composition snapshots both into an ordinary renderer-neutral
View.
Theme supplies the canonical presentation for each component. Use it for the
ordinary case; construct or clone a presentation policy when one component
needs a different visual rule.
Components do not write output, read events, own focus, or retain an event loop. The caller owns interaction state and produces new component data when it changes.
List, Table, Tree, and Scrollbar presentations may use Canvas internally where intrinsic geometry or connected lines require it. That is an implementation of their presentation, not their meaning. Application code can also place the resulting View into Canvas when a semantic component needs explicit coordinates.
Quickstart
Section titled “Quickstart”cargo new component-democd component-democargo add urushiReplace src/main.rs with:
use std::io;
use urushi::{Table, ThemePreset};
fn main() -> io::Result<()> { let theme = ThemePreset::get("Catppuccin Mocha") .expect("built-in theme") .theme();
let table = Table::text() .headers(["Package", "Status"]) .row(["urushi", "ready"]) .row(["urushi-prompt", "ready"]);
urushi::println_view(&theme.table(&table))}Run it with cargo run:
┌───────────────┬────────┐│ Package │ Status │├───────────────┼────────┤│ urushi │ ready ││ urushi-prompt │ ready │└───────────────┴────────┘The table owns data, the theme owns its canonical border and role styles, and
theme.table returns the View that println_view resolves and writes.
Continue by task
Section titled “Continue by task”- Build lists
- Build tables
- Build trees
- Show viewport position with a scrollbar
- Customize component presentations
- Look up the complete Components API
Use Layout for one-off geometry without reusable meaning. Use Canvas for coordinates, overlap, or connected drawing.