Plushie.Type.A11y (Plushie v0.6.0)

Copy Markdown View Source

Accessibility annotation type for widget nodes.

When attached to a widget via the a11y prop, these attributes override the auto-inferred accessibility semantics on the renderer side. The renderer automatically derives roles and labels from widget types and props (e.g. a button's label becomes the accessible name), so most widgets need no explicit a11y annotation. Use this for cases where auto-inference is insufficient.

Construction

Builder chain (like Border, Shadow, Font):

A11y.new()
|> A11y.role(:heading)
|> A11y.level(1)
|> A11y.label("Page title")

Bare map via cast/1 (convenience for inline props):

Button.new("btn", "Go", a11y: %{label: "Go forward"})

DSL do-block via from_opts/1:

button "btn", "Go" do
  a11y do
    label "Go forward"
  end
end

Override semantics

Most fields are optional overrides. When nil (the default), the renderer uses its auto-inferred value. When set, the SDK value wins.

Some widgets auto-manage certain fields based on their interaction state. For example, sliders set busy: true during drag so that assistive technology suppresses rapid value announcements and announces only the final value on release. Setting busy explicitly from the SDK overrides this auto-detected state.

Busy and live regions

busy maps to WAI-ARIA aria-busy. When true on a node (or a parent of a live region), assistive technology suppresses announcements until busy clears, then announces the final state.

Widgets that own continuous interactions (sliders) set this automatically. For app-managed live regions that reflect another widget's state (e.g. a text display showing a color value during canvas drag), set busy explicitly based on the interaction state:

text("hex", hex_value,
  a11y: %{live: :polite, busy: model.drag != :none}
)

Fields

  • role -- overrides the inferred accesskit role (e.g. :heading, :alert)
  • label -- accessible name announced by screen readers
  • description -- longer description (maps to accesskit description)
  • live -- live region semantics: :polite or :assertive
  • hidden -- if true, node is excluded from the accessibility tree
  • expanded -- expanded/collapsed state for disclosure widgets
  • required -- marks a form field as required
  • level -- heading level (1-6)
  • busy -- suppresses AT announcements until cleared (auto-managed by sliders during drag; set explicitly for custom continuous interactions)
  • invalid -- form validation failure
  • modal -- dialog is modal
  • read_only -- can be read but not edited
  • mnemonic -- Alt+letter keyboard shortcut (single character)
  • toggled -- toggled/checked state (for custom toggle widgets)
  • selected -- selected state (for custom selectable widgets)
  • value -- current value as a string (for custom value-displaying widgets)
  • orientation -- :horizontal or :vertical (for custom oriented widgets)
  • labelled_by -- ID of the widget that labels this one
  • described_by -- ID of the widget that describes this one
  • error_message -- ID of the widget showing the error message for this one
  • disabled -- override disabled state for AT
  • position_in_set -- 1-based position within a set (lists, radio groups, tabs)
  • size_of_set -- total items in the set
  • has_popup -- popup type: "listbox", "menu", "dialog", "tree", "grid"

Summary

Functions

Suppresses AT announcements until cleared.

Normalizes a struct, map, or keyword list into an A11y struct.

Sets the ID of the widget that describes this one.

Sets the longer accessible description.

Overrides the disabled state for assistive technology.

Sets the ID of the widget showing the error message.

Sets the expanded/collapsed state.

Constructs an A11y struct from a keyword list.

Sets the popup type ("listbox", "menu", "dialog", "tree", "grid").

Sets whether the node is hidden from the accessibility tree.

Sets the form validation failure state.

Sets the accessible label (name announced by screen readers).

Sets the ID of the widget that labels this one.

Sets the heading level (1-6).

Sets the live region semantics (:polite or :assertive).

Sets the Alt+letter keyboard shortcut (single character).

Sets whether a dialog is modal.

Creates an empty A11y struct with all fields nil.

Sets the orientation (:horizontal or :vertical).

Sets the 1-based position within a set.

Sets the read-only state.

Marks a form field as required.

Sets the accessibility role.

Sets the selected state.

Sets the total number of items in the set.

Sets the toggled/checked state.

Sets the current value as a string.

Types

has_popup()

@type has_popup() :: String.t() | nil

live()

@type live() :: :polite | :assertive

orientation()

@type orientation() :: :horizontal | :vertical

role()

@type role() ::
  :window
  | :tree_item
  | :tree
  | :tooltip
  | :toolbar
  | :text_input
  | :column_header
  | :table_cell
  | :table_row
  | :table
  | :tab_panel
  | :tab_list
  | :tab
  | :switch
  | :status
  | :static_text
  | :slider
  | :separator
  | :search
  | :scroll_view
  | :scroll_bar
  | :region
  | :radio_group
  | :radio_button
  | :progress_indicator
  | :navigation
  | :multiline_text_input
  | :meter
  | :menu_item
  | :menu_bar
  | :menu
  | :list_item
  | :list
  | :link
  | :label
  | :image
  | :heading
  | :group
  | :generic_container
  | :document
  | :dialog
  | :combo_box
  | :check_box
  | :canvas
  | :button
  | :alert_dialog
  | :alert

role_input()

@type role_input() ::
  role()
  | :text_editor
  | :row
  | :radio
  | :progress_bar
  | :generic
  | :container
  | :checkbox
  | :cell

t()

@type t() :: %Plushie.Type.A11y{
  busy: boolean() | nil,
  described_by: String.t() | nil,
  description: String.t() | nil,
  disabled: boolean() | nil,
  error_message: String.t() | nil,
  expanded: boolean() | nil,
  has_popup: has_popup(),
  hidden: boolean() | nil,
  invalid: boolean() | nil,
  label: String.t() | nil,
  labelled_by: String.t() | nil,
  level: pos_integer() | nil,
  live: live() | nil,
  mnemonic: String.t() | nil,
  modal: boolean() | nil,
  orientation: orientation() | nil,
  position_in_set: non_neg_integer() | nil,
  read_only: boolean() | nil,
  required: boolean() | nil,
  role: role() | nil,
  selected: boolean() | nil,
  size_of_set: non_neg_integer() | nil,
  toggled: boolean() | nil,
  value: String.t() | nil
}

Functions

busy(a, busy)

@spec busy(a11y :: t(), busy :: boolean()) :: t()

Suppresses AT announcements until cleared.

Sliders set this automatically during drag. For custom continuous interactions, set explicitly to prevent rapid-fire announcements on live regions.

cast(a11y)

@spec cast(a11y :: t() | map() | keyword()) :: t()

Normalizes a struct, map, or keyword list into an A11y struct.

Accepts an A11y struct, a bare map with atom keys, or a keyword list. Unknown keys are silently ignored. Role aliases like :checkbox and :radio are normalized to their canonical forms.

Examples

iex> Plushie.Type.A11y.cast(%{role: :heading, level: 1})
%Plushie.Type.A11y{role: :heading, level: 1}

iex> Plushie.Type.A11y.cast(role: :heading, level: 1)
%Plushie.Type.A11y{role: :heading, level: 1}

iex> a11y = %Plushie.Type.A11y{label: "Close"}
iex> Plushie.Type.A11y.cast(a11y)
%Plushie.Type.A11y{label: "Close"}

described_by(a, id)

@spec described_by(a11y :: t(), id :: String.t()) :: t()

Sets the ID of the widget that describes this one.

description(a, desc)

@spec description(a11y :: t(), description :: String.t()) :: t()

Sets the longer accessible description.

disabled(a, disabled)

@spec disabled(a11y :: t(), disabled :: boolean()) :: t()

Overrides the disabled state for assistive technology.

error_message(a, id)

@spec error_message(a11y :: t(), id :: String.t() | nil) :: t()

Sets the ID of the widget showing the error message.

expanded(a, expanded)

@spec expanded(a11y :: t(), expanded :: boolean()) :: t()

Sets the expanded/collapsed state.

from_opts(opts)

@spec from_opts(opts :: keyword()) :: t()

Constructs an A11y struct from a keyword list.

has_popup(a, popup)

@spec has_popup(a11y :: t(), popup :: String.t()) :: t()

Sets the popup type ("listbox", "menu", "dialog", "tree", "grid").

hidden(a, hidden)

@spec hidden(a11y :: t(), hidden :: boolean()) :: t()

Sets whether the node is hidden from the accessibility tree.

invalid(a, invalid)

@spec invalid(a11y :: t(), invalid :: boolean()) :: t()

Sets the form validation failure state.

label(a, label)

@spec label(a11y :: t(), label :: String.t()) :: t()

Sets the accessible label (name announced by screen readers).

labelled_by(a, id)

@spec labelled_by(a11y :: t(), id :: String.t()) :: t()

Sets the ID of the widget that labels this one.

level(a, level)

@spec level(a11y :: t(), level :: pos_integer()) :: t()

Sets the heading level (1-6).

live(a, live)

@spec live(a11y :: t(), live :: live()) :: t()

Sets the live region semantics (:polite or :assertive).

mnemonic(a, mnemonic)

@spec mnemonic(a11y :: t(), mnemonic :: String.t()) :: t()

Sets the Alt+letter keyboard shortcut (single character).

modal(a, modal)

@spec modal(a11y :: t(), modal :: boolean()) :: t()

Sets whether a dialog is modal.

new()

@spec new() :: t()

Creates an empty A11y struct with all fields nil.

orientation(a, orientation)

@spec orientation(a11y :: t(), orientation :: orientation()) :: t()

Sets the orientation (:horizontal or :vertical).

position_in_set(a, pos)

@spec position_in_set(a11y :: t(), pos :: non_neg_integer()) :: t()

Sets the 1-based position within a set.

read_only(a, read_only)

@spec read_only(a11y :: t(), read_only :: boolean()) :: t()

Sets the read-only state.

required(a, required)

@spec required(a11y :: t(), required :: boolean()) :: t()

Marks a form field as required.

role(a, role)

@spec role(a11y :: t(), role :: role_input()) :: t()

Sets the accessibility role.

Supported aliases normalize to canonical roles: :checkbox -> :check_box, :radio -> :radio_button, :text_editor -> :multiline_text_input, :progress_bar -> :progress_indicator, :generic / :container -> :generic_container, :row -> :table_row, and :cell -> :table_cell.

selected(a, selected)

@spec selected(a11y :: t(), selected :: boolean()) :: t()

Sets the selected state.

size_of_set(a, size)

@spec size_of_set(a11y :: t(), size :: non_neg_integer()) :: t()

Sets the total number of items in the set.

toggled(a, toggled)

@spec toggled(a11y :: t(), toggled :: boolean()) :: t()

Sets the toggled/checked state.

value(a, value)

@spec value(a11y :: t(), value :: String.t()) :: t()

Sets the current value as a string.