NAME
Clay::UI::Role::Style::HasStates - named states such as selected or loading on a Clay::UI widget
SYNOPSIS
use v5.22;
use Object::Pad;
use Clay::UI::Role::Core::Container;
use Clay::UI::Role::Style::HasStates;
class My::Item :strict(params)
:does(Clay::UI::Role::Core::Container)
:does(Clay::UI::Role::Style::HasStates)
{}
my $item = My::Item->new(id => 'item-1');
$item->add_state('loading');
$item->has_state('loading'); # 1
$item->remove_state('loading');
$item->toggle_state('selected'); # on
my @active = $item->states; # ('selected')
$item->clear_states;
DESCRIPTION
Clay::UI::Role::Style::HasStates gives a widget a set of state names, so that a theme or renderer has one place to ask what the widget is doing right now. There are two kinds of states:
- user states
-
Any name you choose, such as
selected,loadingorerror. You add and remove them; the set holds each name once and has no order. A name is a plain, non-empty string; anything else dies. - derived states
-
hovered,pressed,focusedanddisabled. They are never stored:has_stateandstatesask the widget each time (see "DERIVED STATES"), and they cannot be added, removed or toggled.
The interaction roles Clay::UI::Role::Interaction::Hoverable, Clay::UI::Role::Interaction::Pressable, Clay::UI::Role::Interaction::Focusable and Clay::UI::Role::Interaction::Disableable compose this role already; compose it yourself only for a widget that needs user states without any of them.
States do not change the declaration: Clay never sees them. A contribute method of your own (see "EXTENDING THE DECLARATION" in Clay::UI::Role::Core::Element) can turn them into colours, for example. Such a method must not set a value that another method of the class also sets: a widget that picks its background_color by state must leave the background_color attribute unset, or not compose Clay::UI::Role::Style::HasBackground at all. Every change bumps the revision (Clay::UI::Revision).
METHODS
add_state
$widget->add_state('selected');
Adds a user state. Adding a state that is already set changes nothing, but still bumps the revision. Returns the widget. Dies with Clay::UI: a state name must be a non-empty string for undef, a reference or the empty string, and with Clay::UI: state 'hovered' is derived and cannot be set for a derived state.
remove_state
$widget->remove_state('selected');
Removes a user state; removing one that is not set changes nothing. Bumps the revision and returns the widget. Dies for a derived state, like "add_state".
toggle_state
$widget->toggle_state('selected');
Adds the user state if it is not set, removes it if it is. Bumps the revision and returns the widget. Dies for a derived state.
has_state
if ($widget->has_state('selected')) { ... }
if ($widget->has_state('hovered')) { ... }
Returns true if the state is active: a user state that is set, or a derived state that currently applies. A name that is neither is false.
clear_states
$widget->clear_states;
Removes every user state. Derived states are not affected; they keep following the widget. Bumps the revision and returns the widget.
states
my @active = $widget->states;
Returns the names of all active states, user and derived, as a list in no particular order; in scalar context, how many there are.
DERIVED STATES
Each derived state is answered by a reader of the widget. A widget without that reader (it does not compose the matching role) never has the state.
hovered-
is_hoveredof Clay::UI::Role::Interaction::Hoverable: the pointer is over the widget. pressed-
is_pressedof Clay::UI::Role::Interaction::Pressable. focused-
is_focusedof Clay::UI::Role::Interaction::Focusable. disabled-
disabledof Clay::UI::Role::Interaction::Disableable.
is_hovered, is_pressed and is_focused ask the UI's Clay::UI::Interaction, which updates them during render.
SEE ALSO
Clay::UI::Interaction, Clay::UI::Role::Interaction::Hoverable, Clay::UI::Role::Interaction::Disableable.