Skip to content

[a11y] WCAG 4.1.2 — add label prop to Button primitive and enforce accessible names#3556

Open
rosanusi wants to merge 1 commit into
mainfrom
wcag/4.1.2-button-anchor-empty
Open

[a11y] WCAG 4.1.2 — add label prop to Button primitive and enforce accessible names#3556
rosanusi wants to merge 1 commit into
mainfrom
wcag/4.1.2-button-anchor-empty

Conversation

@rosanusi

Copy link
Copy Markdown
Contributor

Summary

  • Adds a label?: string prop to BaseProps in the Button primitive (src/lib/holocene/button.svelte) rendered as aria-label on both the <a> anchor branch and <button> branch
  • Adds a dev-time onMount check that throws (dev) or console.errors (prod) when a button is rendered without any accessible name (no label, aria-label, aria-labelledby, title, slot text, leading/trailing icon, or count badge)
  • Updates 7 consumer call-sites that were triggering the defect: Workflows List (per-row Start button + 3 toolbar buttons), Activities List (per-row Start button), Schedules List (toolbar configure-columns button), and Schedule Detail page (refresh button)
  • Adds configure-columns i18n key to src/lib/i18n/locales/en/common.ts

Affected files

  • src/lib/holocene/button.svelte
  • src/lib/i18n/locales/en/common.ts
  • src/lib/components/workflow/start-workflow-button.svelte
  • src/lib/components/standalone-activities/start-activity-button.svelte
  • src/lib/components/workflow/workflows-summary-configurable-table.svelte
  • src/lib/pages/schedule-view.svelte
  • src/lib/pages/schedules.svelte

Test plan

  • Visual regression: all 7 consumer buttons render and function identically; no visible change
  • Screen reader (NVDA/VoiceOver): each button announces its label before activation
  • Dev-mode enforcement: render a <Button> with no name source — confirm it throws; add label="…" — confirm no throw
  • Anchor branch: render <Button href="…"> with no name source — confirm same enforcement fires
  • Count badge: render <Button count={3}> — confirm enforcement does not fire (count provides a numeric name)
  • pnpm check passes (no new type errors beyond pre-existing $$_$$ slot interop errors on main)

A11y-Audit-Ref: 4.1.2-button-anchor-empty

🤖 Generated with Claude Code

…cessible names

Adds a `label` prop to the Button/anchor primitive that renders as
`aria-label`, plus a dev-time `onMount` check that warns (prod) or throws
(dev) when a button is rendered without any accessible name. Updates
seven consumer call-sites and adds the `configure-columns` i18n key.

A11y-Audit-Ref: 4.1.2-button-anchor-empty

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment Jun 12, 2026 2:18pm

Request Review

@temporal-cicd

temporal-cicd Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️

📊 Strict Mode: 25 errors in 2 files (2.8% of 904 total)

src/lib/holocene/button.svelte (6)
  • L111:13: Type 'null' is not assignable to type '"search" | "link" | "success" | "error" | "action" | "activity" | "add-square" | "add" | "apple" | "archives" | "arrow-down" | "arrow-left" | "arrow-up" | "arrow-right" | "ascending" | ... 141 more ... | "xmark-square"'.
  • L112:13: Type 'null' is not assignable to type '"search" | "link" | "success" | "error" | "action" | "activity" | "add-square" | "add" | "apple" | "archives" | "arrow-down" | "arrow-left" | "arrow-up" | "arrow-right" | "ascending" | ... 141 more ... | "xmark-square"'.
  • L114:13: Type 'null' is not assignable to type 'string'.
  • L115:13: Type 'null' is not assignable to type 'string'.
  • L116:13: Type 'null' is not assignable to type 'string'.
  • L104:7: Argument of type '$$Props' is not assignable to parameter of type '{ variant?: "primary" | "secondary" | "ghost" | "destructive" | "table-header" | null | undefined; size?: "xs" | "sm" | "md" | "lg" | null | undefined; disabled?: boolean | undefined; ... 10 more ...; class?: string | undefined; }'.
src/lib/pages/schedule-view.svelte (19)
  • L138:18: Property 'message' does not exist on type '{}'.
  • L300:20: 'schedule.schedule' is possibly 'undefined'.
  • L300:20: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L401:12: Type 'IScheduleActionResult[] | null | undefined' is not assignable to type 'IScheduleActionResult[] | undefined'.
  • L405:12: Type 'ITimestamp[] | null | undefined' is not assignable to type 'ITimestamp[] | undefined'.
  • L408:12: Type 'IScheduleSpec | null | undefined' is not assignable to type 'IScheduleSpec'.
  • L409:12: Type 'IScheduleState | null | undefined' is not assignable to type 'IScheduleState'.
  • L410:12: Type 'ISchedulePolicies | null | undefined' is not assignable to type 'ISchedulePolicies'.
  • L411:12: Type 'string | null | undefined' is not assignable to type 'string | undefined'.
  • L420:12: Type 'IPayloads | null | undefined' is not assignable to type 'IPayloads'.
  • L422:34: Type 'IScheduleSpec | null | undefined' is not assignable to type 'IScheduleSpec'.
  • L430:19: 'schedule.schedule' is possibly 'undefined'.
  • L430:19: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L439:9: 'schedule.schedule' is possibly 'undefined'.
  • L439:9: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L445:11: 'schedule.schedule' is possibly 'undefined'.
  • L445:11: 'schedule.schedule.state' is possibly 'null' or 'undefined'.
  • L454:11: 'schedule.schedule' is possibly 'undefined'.
  • L454:11: 'schedule.schedule.state' is possibly 'null' or 'undefined'.

Generated by 🚫 dangerJS against 6b18cab

@rosanusi rosanusi marked this pull request as ready for review June 12, 2026 14:26
@rosanusi rosanusi requested a review from a team as a code owner June 12, 2026 14:26
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.

1 participant