InputGroup
Layer: molecule · Path:
src/molecules/input_group.rs· Exports:input_group::{InputGroup, Slot}
A text input (or multi-line Textarea) with addons sharing one muted Surface. Addons — icons, text, or buttons — sit in four slots: leading/trailing inline (on the field’s centerline) and block start/end (their own rows above/below). .multiline(rows) switches the editing substrate to a Textarea. Models shadcn’s InputGroupAddon / InputGroupText / InputGroupButton.
Design
- Purpose / when to use — Inputs that need affordances: a leading search icon, a trailing clear button, a
$/unit prefix, or a labeled block addon over a textarea. - Anatomy —
Surface::muted().pad(SPACE_1).radius(RADIUS_MD)→ vertical stack: aBlockStartrow (if any) → the field → aBlockEndrow (if any). In single-line mode the field is a fixed-height (CONTROL_MD) center-aligned row ofLeadingInlineaddons + a framelessTextEdit::singleline(placeholder + text styled from typography) +TrailingInlineaddons. In multiline mode it’s aTextarea(inline addons ignored). - Slots (
Slot) —LeadingInline,TrailingInline,BlockStart,BlockEnd. - Addon kinds — icon (muted
Icon), text (mutedText), button (ghost icon-onlyButton, runs anFnMuton click). - Tokens / layout consumed —
core::SPACE_1(surface pad / block gaps),SPACE_2(addon spacing + trailing reserve),CONTROL_MD(inline row height),RADIUS_MD. See tokens.
API
| Method | Effect |
|---|---|
InputGroup::new(buf: &'a mut String) -> Self | Bind the text buffer. |
.placeholder(text: impl Into<String>) -> Self | Hint text shown when empty. |
.multiline(rows: usize) -> Self | Switch to a Textarea of rows rows (≥1; inline addons ignored). |
.id_source(id: impl std::hash::Hash) -> Self | Stable id for the editor. |
.icon(slot: Slot, glyph: &'static str) -> Self | Add an icon addon in slot. |
.text(slot: Slot, text: impl Into<String>) -> Self | Add a text addon in slot. |
.button(slot: Slot, glyph: &'static str, action: impl FnMut() + 'a) -> Self | Add a clickable icon-button addon; action runs on click. |
.leading_icon(glyph: &'static str) -> Self | Sugar — icon in LeadingInline. |
.trailing_icon(glyph: &'static str) -> Self | Sugar — icon in TrailingInline. |
.leading_text(text: impl Into<String>) -> Self | Sugar — text in LeadingInline. |
.show(self, ui: &mut Ui) -> Response | Render; returns the field Response (.changed() on edit). |
Slot — LeadingInline, TrailingInline, BlockStart, BlockEnd.
Usage
#![allow(unused)]
fn main() {
use ouroboros_ui::molecules::{InputGroup, Slot};
use ouroboros_ui::egui_phosphor::light;
// minimal — leading search icon + trailing clear button
InputGroup::new(&mut query)
.leading_icon(light::MAGNIFYING_GLASS)
.button(Slot::TrailingInline, light::X, || { query.clear(); })
.placeholder("Search…")
.id_source("ig_search")
.show(ui);
}
#![allow(unused)]
fn main() {
use ouroboros_ui::molecules::{InputGroup, Slot};
// text prefix/suffix
InputGroup::new(&mut price)
.leading_text("$")
.text(Slot::TrailingInline, "USD")
.placeholder("0.00")
.id_source("ig_price")
.show(ui);
// block addon over a multiline textarea
InputGroup::new(&mut note)
.text(Slot::BlockStart, "Description")
.multiline(3)
.placeholder("Markdown supported…")
.id_source("ig_note")
.show(ui);
}
Composition
Composes Surface + Textarea + Icon + Text + Button. The single-line editor is an egui::TextEdit::singleline (the editing substrate, not a paint call), styled from typography. It never paints primitives — see the guards.
Notes
InputGroup<'a>carries a lifetime — the buttonactionisBox<dyn FnMut() + 'a>and may capture/mutate surrounding state (and even the bound buffer, as in the clear example).- In single-line mode, trailing-inline addons reserve
(CONTROL_MD + SPACE_2)width each so the text doesn’t run under them. .multiline(rows)ignores inline addons — only block addons apply to a textarea.- The returned
Responseis the field’s;.changed()is true when the text was edited this frame. SearchFieldis a thin preset over this molecule.