Form controls need to be properly labeled so users understand their purpose. Associating a label with a form control is best done using `
aria-required="true" indicates that a field must be filled in before submission, and aria-invalid="true" marks a field as failing validation; when set, the screen reader announces the field's name together with "invalid entry" along with the error message. The standard error-handling pattern is to set aria-invalid="true" on bad fields on submit (or after the user leaves the field), associate each with an error message via aria-describedby, add an alert live region summarizing errors at the top of the form, and keep focus on the first error or the summary.
Choosing between a button and a link follows a clear rule: use a link (``) when activation navigates to a new URL or fragment, and use a button for actions that do not navigate, such as submitting a form, opening a dialog, or toggling state. A toggle button such as Bold uses a `
role="group" wraps a set of related controls that should be perceived as a unit, paired with aria-label or aria-labelledby to give the group a name (for example, a "Font size" radio group). The standard radio group uses role="radiogroup" containing role="radio" children, each with aria-checked indicating the selected option; one radio must have aria-checked="true" at all times, and arrow keys move between radios. role="menuitemradio" is similar but lives inside a menu, where arrow keys move and Space toggles. role="progressbar" announces a numeric value that changes (via aria-valuenow, aria-valuemin, and aria-valuemax), and aria-valuetext conveys non-numeric values such as "Loading 45%"; omitting aria-valuenow altogether produces an indeterminate progress indicator.