Skip to content

a11y(webhooks): add table caption and header scopes#504

Open
Dedenwrg wants to merge 1 commit into
StableRoute-Org:mainfrom
Dedenwrg:a11y/webhooks-01-table-semantics
Open

a11y(webhooks): add table caption and header scopes#504
Dedenwrg wants to merge 1 commit into
StableRoute-Org:mainfrom
Dedenwrg:a11y/webhooks-01-table-semantics

Conversation

@Dedenwrg

@Dedenwrg Dedenwrg commented Jul 23, 2026

Copy link
Copy Markdown

Closes #480

Summary

Adds semantic table markup to the webhooks list so screen readers can navigate it as a proper data table.

Changes

ResourceList.tsx — new table mode (backward-compatible)

  • New optional props: caption, tableHeaders, renderCells
  • When all three are provided, renders a <table> with:
    • <caption class="sr-only"> — visually hidden, available to AT
    • <thead> with <th scope="col"> for each column
    • <tbody> with <th scope="row"> on the first cell of every row
  • Falls back to the original <ul> list when props are omitted — no breaking change for api-keys or other consumers

WebhooksClient.tsx

  • Passes caption="Registered webhooks", tableHeaders={["URL", "Events", "Registered", "Actions"]}, and renderCells to produce the four-column table
  • renderRow retained for backward-compat but unused in table mode

Tests

New a11y tests in webhooks/page.test.tsx (5 tests)

  • <caption> present with descriptive text
  • Column headers carry scope="col"
  • Row headers carry scope="row"
  • No <table> rendered when list is empty
  • Caption has sr-only class

New table-mode tests in ResourceList.test.tsx (12 tests)

  • Table renders when caption + renderCells provided
  • Caption text and sr-only class
  • scope="col" on column headers
  • scope="row" on first cell of each row
  • <td> for data cells
  • Fallback to <ul> when caption or renderCells missing
  • Loading/empty states still work in table mode
  • Remove dialog integration from table rows

Test output

Test Suites: 56 passed, 56 total
Tests:       632 passed, 632 total

Checklist

  • npm run lint — no warnings or errors
  • npm test — 632/632 pass
  • npm run build — clean
  • Structure/semantics only — no data or column changes
  • Edge cases covered: empty table, single-row table

- Add caption, tableHeaders, renderCells props to ResourceList for
  semantic table rendering with <caption>, scope="col" headers, and
  scope="row" on the first cell of each row.
- Convert webhooks list to a table with columns: URL, Events,
  Registered, Actions.
- Caption is visually hidden (sr-only) but available to assistive tech.
- Backward-compatible: ResourceList falls back to <ul> when caption or
  renderCells is not provided.
- Add 5 a11y tests to webhooks page (caption, scope attributes, empty
  state, sr-only).
- Add 12 table-mode tests to ResourceList (table render, caption, scopes,
  fallback, loading/empty states, remove dialog integration).
- All 632 tests pass. Lint and build clean.
@mikewheeleer

Copy link
Copy Markdown
Contributor

thanks @Dedenwrg! could you add a Closes #<issue> line to the PR description so it links to the issue it resolves? once it's linked we can review and merge. 🙏

@Dedenwrg

Dedenwrg commented Jul 23, 2026

Copy link
Copy Markdown
Author

thanks @Dedenwrg! could you add a Closes #<issue> line to the PR description so it links to the issue it resolves? once it's linked we can review and merge. 🙏

Done edited
Closes #480

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Give the webhooks table a caption and scope-annotated headers

2 participants