[ Widgets ]
Button
koto::Button renders a filled, bordered button with a centered label and optionally registers a click and keyboard (Key::Enter / space) target in FocusManager (Header: koto/button.hpp).
Quick example
Section titled “Quick example”Button("Deploy") .id(Id("btn_deploy")) .border_style(BorderStyle::Rounded) .fg(Color::Cyan) .draw(frame, button_area);╭──────────────────╮│ Deploy │╰──────────────────╯Behavior
Section titled “Behavior”- Automatic
FocusManagerregistration duringdraw(): When both.focus(fm)and a non-empty.id(Id(...))are set on aButton:- If
.on_click(callback)is also set,Button::draw()constructs aFocusTargetwith.id = fm.scoped_id(m_id),.bounds = area,.modal_scope = fm.active_modal_scope(), and key/mouse closures, and callsfm.register_target(std::move(target))(src/button.cpp:116-149). - Unless
.focused(bool)was called manually on theButton,m_is_focusedis queried automatically viafm.is_focused(m_id)(src/button.cpp:151-154).
- If
- Background and border rendering:
Button::draw()delegates its box frame toBox().border_style(m_border_style).fg(border_col).bg(bg_col).id(m_id).focused(m_is_focused).focused_border_fg(m_focused_border_fg).filled(true).draw(frame, area). - Label centering and clipping: When
m_labelis non-empty,Buttoncomputes a 1-rowtext_areaat vertical centerarea.row + (area.height - 1) / 2(inset horizontally by 1 column on each side whenarea.height > 2 && area.width > 2 && m_border_style != BorderStyle::None) and drawsText(m_label).fg(text_col).bg(bg_col).clip().align(TextAlign::Center). - Color propagation in
.fg()and.focused_fg():- Calling
.fg(color)setsm_fg = color.valueand, if.label_fg()has not been called yet, also setsm_label_fg = color.value(src/button.cpp:29-38). - Calling
.focused_fg(color)setsm_focused_fg = color.valueand propagatescolor.valuetom_focused_label_fg(if.focused_label_fg()was not called) andm_focused_border_fg(if.focused_border_fg()was not called) (src/button.cpp:60-73).
- Calling
Keys and mouse
Section titled “Keys and mouse”These bindings are registered in FocusManager when .focus(fm), .id(Id(...)), and .on_click(callback) are all provided before draw():
| Input | Condition | Action |
|---|---|---|
Key::Enter (k.is(Key::Enter)) | Button is focused in FocusManager | Invokes on_click callback and returns true. |
Space (k.ch == ' ') | Button is focused in FocusManager | Invokes on_click callback and returns true. |
Left mouse press (m.is_left_press()) | Click lands on a cell tagged with m_id | Focuses the button in FocusManager, invokes on_click callback, and returns true. |
Methods
Section titled “Methods”| Method | Description | Default |
|---|---|---|
Button() | Default-constructs a button with an empty label. | m_label = "" |
Button(std::string_view label) | Explicit constructor setting m_label. | on_click = nullptr |
Button(std::string_view label, std::function<void()> on_click) | Constructs a button with label and on_click callback. | None |
label(std::string_view label) | Sets the button text label. | "" |
border_style(BorderStyle style) | Sets the surrounding border style. | BorderStyle::Rounded |
fg(Color color) | Sets unfocused border color (and unfocused label color if label_fg was not set). | Color::DarkGray |
bg(Color color) | Sets unfocused interior background color. | COLOR_DEFAULT |
label_fg(Color color) | Sets unfocused label text color explicitly. | Color::LightGray |
focused(bool is_foc) | Manually overrides focus state (disables querying fm.is_focused(m_id)). | false |
focused_fg(Color color) | Sets focused foreground and propagates to focused_label_fg and focused_border_fg if not explicitly set. | Color::Cyan |
focused_bg(Color color) | Sets interior background color used when focused. | Color::DarkGray (inactive unless focused_bg() is called) |
focused_border_fg(Color color) | Sets focused border color explicitly. | Color::Cyan |
focused_label_fg(Color color) | Sets focused label text color explicitly. | Color::White |
id(Id id) | Sets the id token for hit-testing and FocusManager registration. | Id::none() |
focus(FocusManager& fm) | Attaches FocusManager so draw() syncs focus state and registers on_click. | nullptr |
on_click(std::function<void()> callback) | Sets the action callback invoked on Key::Enter, ' ', or left click. | nullptr |
draw(Frame& frame, Area area) | Registers with FocusManager (if configured) and draws the button into frame. | None |
Gotchas
Section titled “Gotchas”- Minimum height for borders: A bordered
Buttonrequiresarea.height >= 3andarea.width >= 3to inset the label inside the top and bottom borders (src/button.cpp:174). In a 1-row or 2-row area with a border,text_areafalls back toareaand overwrites the border row.