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
Selkie::Widget::RadioGroup ā one-of-many selection
Selkie::Widget::Button ā plain action button
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 BoolCurrent state.
method set-checked
method set-checked(
Bool:D $v
) returns MuSet 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 MuFlip the state and emit on-change unconditionally.
method on-change
method on-change() returns SupplySupply emitting Bool each time the state changes.
method set-focused
method set-focused(
Bool $f
) returns MuSet focus state. Called by Selkie::App's focus dispatcher; the focused-styling palette flips on/off accordingly.
method is-focused
method is-focused() returns BoolWhether the checkbox currently has keyboard focus.
method set-glyphs
method set-glyphs(
Str:D :$checked!,
Str:D :$unchecked!
) returns NilSet both indicator glyphs at once. See GLYPHS for guidance on keeping $checked and $unchecked the same width.