Components API
Components are reusable UI objects: they render like views, and interactive ones also receive key, mouse, and paste events and answer with a small set of conventional return values. Charming bundles a large set of ready-made components — inputs, lists, tables, modals, spinners, and more. This page covers the base class, the event/return protocol, and the bundled catalog; for usage guides with screenshots per component, see Components.
Charming::Component
Inherit from Charming::Component for reusable UI objects. Components inherit view helpers and assign readers.
class BadgeComponent < Charming::Component
def render
text label, style: theme.title
end
end
Event handling
Interactive components can implement:
handle_key(event)handle_mouse(event)handle_paste(event)for bracketed-paste textcaptures_text?— return true when the component accepts free-typed prose; the controller then routes printable characters (and Tab) to it before key bindings
class ConfirmComponent < Charming::Component
def handle_key(event)
case Charming.key_of(event)
when :y then [:submitted, true]
when :n, :escape then :cancelled
end
end
end
Return conventions
:handledmeans the event was consumed.[:selected, value]means a value was selected.[:submitted, value]means a value was submitted.:cancelledmeans the interaction was cancelled.nilmeans the event was not handled.
Focused component result hooks
When a focus-ring slot’s component returns one of the conventional results, the controller calls a matching hook if you define one:
[:submitted, values]calls<focus_slot>_submitted(values)when defined.[:selected, value]calls<focus_slot>_selected(value)when defined.:cancelledcalls<focus_slot>_cancelledwhen defined.
Bundled components
Text input and forms:
Charming::Components::TextInput— options includemasked:(password rendering) andhistory:(up/down recall)Charming::Components::TextArea— plain Enter inserts a newline by default (enter_newline: falseto opt out)Charming::Components::FormCharming::Components::Autocomplete
Lists, tables, and navigation:
Charming::Components::List—filter:/filter=narrow items by fuzzy match (best match first)Charming::Components::MultiSelectList—selected_indices:,max_selections:; Space toggles, Enter submits[:submitted, items]Charming::Components::Table—height:adds a scrolling window with page up/down;sort_by!(column, direction:)/toggle_sort(column)sort with a ▲/▼ header markerCharming::Components::Tree— collapsible node hashes ({label:, children:, expanded:})Charming::Components::Filepicker—root:,show_hidden:,height:; Enter descends or returns[:selected, path], Backspace ascends,toggle_hiddenCharming::Components::Paginator—total:,per_page:,format:(:dots/:arabic);page_items(items),next_page/prev_pageCharming::Components::TabBarCharming::Components::Breadcrumbs
Overlays and dialogs:
Charming::Components::Modal—max_body_height:makes the body scrollable;scroll_offsetexposes the positionCharming::Components::HelpOverlay—HelpOverlay.for_controller(controller_class)builds one from key bindingsCharming::Components::CommandPaletteCharming::Components::CommandPaletteModalCharming::Components::ErrorScreen— rendered by the runtime for unhandled exceptions
Status and progress:
Charming::Components::Toast—kind:of:info,:success,:warn,:errorCharming::Components::StatusBar—left:,center:,right:, orhints:pairsCharming::Components::BadgeCharming::Components::EmptyStateCharming::Components::Spinner—style:picks a named preset (:line,:dots,:mini_dot,:jump,:pulse,:points,:globe,:moon,:meter,:hamburger,:ellipsis);frames:overridesCharming::Components::Progressbar—gradient: ["#rrggbb", "#rrggbb"]colors the fill;percentreports completionCharming::Components::ActivityIndicatorCharming::Components::Timer—duration:,label:;tick,expired?,resetCharming::Components::Stopwatch—label:;start/stop/reset,tickaccumulates while running
Content and media:
Charming::Components::ViewportCharming::Components::MarkdownCharming::Components::Audio—▶/■playback indicator for aCharming::Audio::Player(player:,label:)
Mixins and utilities:
Charming::Components::KeyboardHandler(mixin)Charming::Components::FuzzyMatcher—score(query, candidate)andfilter(query, candidates) { |c| label }
ActivityIndicator constructor options include width:, label:, index:, seed:, chars:, gradient:, label_style:, max_width:, and fallback_label:.
Forms
Form component constructor:
fields:array of form field objects.state:mutable primitive state hash, usually fromsession[:forms].theme:optionalCharming::UI::Theme.
Form field classes:
Charming::Components::Form::InputCharming::Components::Form::TextareaCharming::Components::Form::SelectCharming::Components::Form::ConfirmCharming::Components::Form::Note
Controller helper:
form(:signup) do |f|
f.input :name, required: true
f.textarea :bio, height: 5
f.select :plan, options: ["Free", "Pro"]
f.confirm :terms, required: true
end
TextArea
TextArea component constructor:
value:current multiline string.placeholder:rendered when value is empty.width:optional visible columns per line.height:optional visible rows.cursor:absolute cursor offset intovalue.offset:first visible row.preferred_column:remembered column for up/down movement (in display columns — wide characters count as two).enter_newline:whether plain Enter inserts a newline (defaulttrue).
Textarea keys:
- Plain
Enterinserts a newline (press twice for a blank line). Shift+Enter,Ctrl+J, andCtrl+Nalso insert newlines (and keep working whenenter_newline: false).- In a form:
Tableaves the field,Ctrl+Ssubmits from any field.
Markdown
Markdown component constructor:
content:Markdown source string.width:optional terminal width used for paragraph wrapping.theme:optionalCharming::UI::Theme.syntax_highlighting:controls Rouge-backed code block highlighting, defaulting totrue.style:Markdown style name or style config, defaulting to:dark. Built-in styles are:dark,:light, and:notty.base_url:optional base URL used to resolve relative links and image targets.hyperlinks:wraps links in OSC 8 escapes for clickable terminals (defaultfalse; the `` suffix is dropped when enabled).
Markdown parsing uses Commonmarker with CommonMark/GFM support. Syntax highlighting uses Rouge. Charming maps parsed nodes and Rouge tokens to terminal text through a Glamour-inspired Markdown style config and ANSI theme styling. Supported GFM rendering includes tables, task lists, strikethrough, autolinks, links, terminal-friendly image labels, definition lists, and footnotes.