toolbar Item Semantics
The single accessibility contract for every toolbar item (A11Y-1 / P1-6).
Applied at the leaf composable of each item by NutrientToolbarLayout; producers never call it directly. Centralizing it means a11y review is a one-time design exercise instead of per-PR vigilance, and it matches or exceeds the View toolbar's AppCompatImageButton baseline.
It sets, from item and its state:
Role —
Role.Switchfor a ToolbarItem.Toggle,Role.Buttonotherwise.contentDescription —
item.contentDescription(the label TalkBack reads).State via framework properties, never literal strings — a toggle exposes toggleableState (localized on/off announcement), everything else exposes selected when selected. Accessibility services derive their announcements from these in the device locale; a hand-rolled
stateDescriptionwould be English-only in an SDK shipping 32 languages.testTag — derived from
item.idvia toToolbarTestTag (closes P1-12: customers map per-buttonR.idEspresso matchers toonNodeWithTagmechanically).disabled() when not enabled (localized "disabled" announcement comes from the property); hidden from accessibility when not visible. The visual disabled treatment is the render leaf's tint (
MainToolbarColors.iconDisabledColor) — no alpha layer here, or the two would stack and disabled icons render twice as dim as the View toolbar's singleDISABLED_ITEM_ALPHApass.The click action itself comes from the host composable's
clickableand merges in; its default "double-tap to activate" hint is localized by the accessibility service, so no custom click label is set.
It's @Composable because the test tag is resolved from the R.id resource name, which needs a Context (LocalContext).
Note: ToolbarItem.Submenu expanded/collapsed announcement is deferred to the popup layer (it depends on transient expansion state not held by ToolbarItem).