Selkie--Widget--Checkbox

NAME

Selkie::Widget::Checkbox - Focusable boolean toggle

SYNOPSIS

use Selkie::Widget::Checkbox;
use Selkie::Sizing;

my $cb = Selkie::Widget::Checkbox.new(
    label  => 'Enable notifications',
    sizing => Sizing.fixed(1),
);
$cb.on-change.tap: -> Bool $checked {
    $app.store.dispatch('settings/notifications', value => $checked);
};

DESCRIPTION

Renders as [x] label when checked, [ ] label when unchecked. Space or Enter toggles the state, as does a primary mouse click on any cell of the checkbox row. User activation is debounced by default so duplicate terminal press events from one physical click do not flip the checkbox twice.

set-checked is idempotent — passing the current value is a no-op and doesn't emit on on-change. Safe to call from a store subscription without causing feedback loops.

GLYPHS

The [x]/[ ] indicator is configurable via checked-glyph and unchecked-glyph (constructor args, both is rw) or the set-glyphs method. Defaults are byte-identical to the historical hardcoded pair, so existing code renders exactly as before.

Keep both glyphs the same .chars length. The indicator is rendered directly before the label with no fixed-width padding between them — if checked-glyph and unchecked-glyph differ in length, the label visibly shifts left or right every time the checkbox toggles. Mismatched widths aren't rejected (a narrower "off" glyph paired with a wrapped/bracketed "on" glyph is a legitimate design choice), but the jitter is the tradeoff.

Avoid ā˜‘/☐ (U+2611/U+2610). These render as ambiguous-width in many terminal/font combinations — some environments draw them as a single column, others as two, and the mismatch between the two glyphs compounds the jitter problem above. That ambiguity is why the ASCII [x]/[ ] pair remains the default rather than a Unicode checkbox glyph.

Tested alternatives that render consistently:

  • [x] / [ ] — the default, plain ASCII.

  • [āœ“] / [ ] — checkmark inside brackets; U+2713 is single-width almost everywhere.

  • (•) / ( ) — bullet radio-style indicator.

  • ā˜’ / ☐ — ballot box with X (U+2612) paired with empty ballot box (U+2610); both single-width in practice, unlike the ā˜‘ pairing above.

my $cb = Selkie::Widget::Checkbox.new(label => 'Enable notifications');
$cb.set-glyphs(checked => '[āœ“]', unchecked => '[ ]');

Selkie::Widget::RadioGroup has the same [x]/[ ] hardcoding and is a natural follow-up for the same treatment, but that widget is out of scope here.

EXAMPLES

Syncing with the store

# Subscribe: reflect store changes into the widget
$app.store.subscribe-with-callback(
    'sync-notif',
    -> $s { $s.get-in('settings', 'notifications') // True },
    -> Bool $v { $cb.set-checked($v) },   # no-op if unchanged — safe
    $cb,
);

# Emit: user toggle dispatches to the store
$cb.on-change.tap: -> Bool $v {
    $app.store.dispatch('settings/set', field => 'notifications', value => $v);
};

SEE ALSO

has Str $.label

The label displayed after the [x] / [ ] indicator. Required.

has UInt $.debounce-ms

Reject user toggles that arrive within this many milliseconds of the previous accepted user toggle. Defaults to 120ms to collapse duplicate mouse press events and repeat-key bursts. Set to 0 to allow every user activation. Direct toggle and set-checked calls remain immediate for programmatic state changes.

has Str $.checked-glyph

Glyph shown when checked is True. Defaults to [x] — see GLYPHS for alternatives and the equal-width caveat.

has Str $.unchecked-glyph

Glyph shown when checked is False. Defaults to [ ].

method checked

method checked() returns Bool

Current state.

method set-checked

method set-checked(
    Bool:D $v
) returns Mu

Set the state, emitting on-change only if the value actually changed. No-op on same-value assignments — safe to call from a store subscription.

method toggle

method toggle() returns Mu

Flip the state and emit on-change unconditionally.

method on-change

method on-change() returns Supply

Supply emitting Bool each time the state changes.

method set-focused

method set-focused(
    Bool $f
) returns Mu

Set focus state. Called by Selkie::App's focus dispatcher; the focused-styling palette flips on/off accordingly.

method is-focused

method is-focused() returns Bool

Whether the checkbox currently has keyboard focus.

method set-glyphs

method set-glyphs(
    Str:D :$checked!,
    Str:D :$unchecked!
) returns Nil

Set both indicator glyphs at once. See GLYPHS for guidance on keeping $checked and $unchecked the same width.

Selkie v0.11.1

High-level TUI framework built on Notcurses

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

Notcurses::Native:ver<0.4.1+>:auth<zef:apogee>

Test Dependencies

Provides

  • Selkie
  • Selkie::Align
  • Selkie::Alpha
  • Selkie::App
  • Selkie::App::Internal::Animation
  • Selkie::App::Internal::Dispatch
  • Selkie::App::Internal::ErrorLog
  • Selkie::App::Internal::FocusTree
  • Selkie::App::Internal::HitTest
  • Selkie::App::Internal::IdleBudget
  • Selkie::App::Internal::OverlayTree
  • Selkie::App::Internal::RenderLoop
  • Selkie::App::Internal::ScreenModalLifecycle
  • Selkie::App::Internal::Terminal
  • Selkie::App::Internal::TerminalSequences
  • Selkie::BorderStyle
  • Selkie::Container
  • Selkie::EffectiveBounds
  • Selkie::Event
  • Selkie::Gradient
  • Selkie::Layout::Allocate
  • Selkie::Layout::HBox
  • Selkie::Layout::Split
  • Selkie::Layout::VBox
  • Selkie::Plot::Palette
  • Selkie::Plot::Scaler
  • Selkie::Plot::Ticks
  • Selkie::ScreenManager
  • Selkie::Sizing
  • Selkie::Store
  • Selkie::Style
  • Selkie::Test::Focus
  • Selkie::Test::Keys
  • Selkie::Test::Snapshot
  • Selkie::Test::Snapshot::Harness
  • Selkie::Test::Store
  • Selkie::Test::Supply
  • Selkie::Test::Tree
  • Selkie::Theme
  • Selkie::Trace
  • Selkie::Tree
  • Selkie::Tween
  • Selkie::Widget
  • Selkie::Widget::Axis
  • Selkie::Widget::BarChart
  • Selkie::Widget::Border
  • Selkie::Widget::Button
  • Selkie::Widget::CardList
  • Selkie::Widget::Checkbox
  • Selkie::Widget::CommandPalette
  • Selkie::Widget::ConfirmModal
  • Selkie::Widget::FileBrowser
  • Selkie::Widget::FocusableByDefault
  • Selkie::Widget::GradientFill
  • Selkie::Widget::Heatmap
  • Selkie::Widget::HelpOverlay
  • Selkie::Widget::Histogram
  • Selkie::Widget::Image
  • Selkie::Widget::Legend
  • Selkie::Widget::LineChart
  • Selkie::Widget::ListView
  • Selkie::Widget::Modal
  • Selkie::Widget::MultiLineInput
  • Selkie::Widget::PasswordStrength
  • Selkie::Widget::Plot
  • Selkie::Widget::ProgressBar
  • Selkie::Widget::RadioGroup
  • Selkie::Widget::RichText
  • Selkie::Widget::RichText::Span
  • Selkie::Widget::ScatterPlot
  • Selkie::Widget::ScrollView
  • Selkie::Widget::Select
  • Selkie::Widget::Sparkline
  • Selkie::Widget::Spinner
  • Selkie::Widget::TabBar
  • Selkie::Widget::Table
  • Selkie::Widget::Text
  • Selkie::Widget::TextInput
  • Selkie::Widget::TextInput::HighlightSpan
  • Selkie::Widget::TextStream
  • Selkie::Widget::Toast
  • Selkie::Widget::ViewportedCardList

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.