This checklist captures the baseline rules we enforce in profile section markup and verify with axe.
- Use semantic sectioning and heading elements (
section,header,h2,h3, etc.) where appropriate. - Do not skip heading levels within a section hierarchy.
- Do not render empty headings. If text is optional, render a non-heading element (for example
p) or do not render the element.
- Only use ARIA attributes that are valid for the element role.
- Do not put
aria-labelon a generic element unless it has an appropriate role. - If labeling a grouped region of plain elements, add a semantic role such as
role="group"and then apply the label. - Prefer native semantics first; add ARIA only when native HTML does not provide the needed meaning.
- All meaningful images must have accurate
alttext. - Decorative icons should use
aria-hidden="true". - Fallback avatar blocks should expose an accessible name when no photo exists.
- Buttons and links must have a clear accessible name.
- Icon-only buttons must include an
aria-labelor visible text. - Interactive controls must remain keyboard reachable and operable.
- For optional data, use null-safe access and sensible fallback values.
- Avoid rendering empty semantic containers that can trigger accessibility violations.
- For list content, use proper list semantics (
ul/ol+li). - For grouped non-list content, use a semantic wrapper and only add ARIA where needed.
- Run the focused accessibility test after markup changes:
npm test -- test/profile-view.accessibility.test.ts
- Run the short manual accessibility smoke test for accessibility-sensitive changes:
- see
docs/accessibility-smoke-test.md
- see
- For interaction changes, manually test keyboard-only behavior:
- tab order reaches all controls
- visible focus remains clear
- dialogs can be opened, operated, and closed from the keyboard
- focus returns to a sensible element after closing a dialog
- Manually test with VoiceOver on macOS for:
- landmark and heading navigation
- button and link names
- dialog title and description announcement
- inline error, alert, and saving/status message announcement
- Check reflow at 200% and 400% zoom for the main profile flows.
- Until browser-level accessibility audits are automated in this repo, do not treat the axe test as sufficient by itself for accessibility-sensitive changes.
- If violations appear, fix semantic/ARIA issues before adding test exceptions.
- Keep fixes in source markup, not in test-only workarounds.
aria-labelon adivwithout role.- Rendering optional heading tags with empty content.
- Skipping heading levels by introducing
h4where no preceding heading level exists. - Assuming optional profile fields always exist during render.