ARIA Widget Patterns

ARIA widget patterns define the roles, states, properties, keyboard behavior, and focus management expected for custom interactive controls. They help assistive technologies understand controls that native HTML elements do not fully represent.

A widget pattern describes how a custom control should behave, not merely which ARIA role to add. A pattern typically specifies the widget's semantic role, relevant states and properties, supported keyboard interactions, and how focus moves between elements.

Native HTML should be the starting point whenever it provides the required behavior. For example, a native `button` already has semantics, keyboard support, and focus behavior, so replacing it with a `div` plus `role="button"` creates extra accessibility work without adding value.

For custom widgets, ARIA roles communicate what the control is, while states and properties communicate its current condition or configuration. Examples include `aria-expanded` for disclosure state, `aria-selected` for selection state, and `aria-controls` when a control identifies the region it operates.

Keyboard and focus behavior are essential parts of a widget pattern. A widget that has correct ARIA attributes but cannot be operated with an appropriate keyboard interaction is still inaccessible. Composite widgets such as tabs, listboxes, and grids may use roving `tabindex` or `aria-activedescendant` to manage which item is treated as active.

ARIA does not create interaction behavior automatically. JavaScript must implement the required interaction and keep ARIA state synchronized with the actual UI state. Testing should include keyboard-only operation and at least one relevant assistive technology in addition to checking the DOM.

Key points

Interview questions

What is an ARIA widget pattern?

An ARIA widget pattern is a specification for how a custom interactive control should expose semantics and behave for keyboard and assistive-technology users. It defines the appropriate role, states and properties, keyboard interactions, and focus behavior. The pattern is more than assigning a role to an element. The implementation must keep the accessibility state synchronized with the actual UI.

Why is native HTML usually preferred over recreating a widget with ARIA?

Native HTML elements already provide many accessibility behaviors, including semantics, keyboard interaction, focus handling, and browser integration. Replacing a native button with a generic element and ARIA can require manually reproducing those behaviors. Native elements also reduce the amount of accessibility-specific code that must remain correct. ARIA is most useful when the required semantics or interaction model cannot be expressed adequately with native HTML.

How would you implement keyboard and focus behavior for a tab widget?

I would first follow the tabs pattern for the roles, relationships, states, and keyboard interactions. The active tab would expose `aria-selected`, and each tab would be associated with its corresponding tab panel. I would define how arrow keys move between tabs and how focus is managed, commonly using roving `tabindex` for the tab elements. The implementation would also keep selection, focus, and visible panel state synchronized.

What is the difference between `aria-expanded` and `aria-selected`?

`aria-expanded` communicates whether a control's associated expandable content is currently open or closed. `aria-selected` communicates selection state within widgets that support selectable items, such as tabs or listboxes. They represent different concepts even though both use Boolean-like state values. The implementation should update the appropriate attribute whenever the underlying state changes.

What makes focus management difficult in composite ARIA widgets?

Composite widgets contain multiple logical items but often expose a single entry point in the normal tab sequence. The implementation therefore needs a consistent model for moving focus or tracking the active descendant with the keyboard. Roving `tabindex` physically moves DOM focus among items, while `aria-activedescendant` can keep focus on a container and expose which descendant is active. Either approach requires careful synchronization between keyboard state, visual state, and accessibility state.