fix(core): set aria-disabled and tabindex on Button when disabled #213

Merged
rawdaGastan merged 1 commit from development_button_disabled_attribute into development 2026-05-07 12:18:14 +00:00
Member

Summary

The shared Button and IconButton components rendered the hero-btn-disabled class but no a11y/keyboard semantics, so disabled buttons stayed in the tab order, were not announced as disabled by screen readers, and programmatic btn.click() was only stopped by the in-handler guard. This PR adds aria-disabled and tabindex driven by the same state used for the disabled CSS class.

The HTML disabled attribute is still intentionally not set, per the existing design constraint in the component (UA grey would override the variant background colors).

Closes #184

Changes

  • Button component: emit aria_disabled and tabindex attributes that flip with the existing is_disabled = props.disabled || props.loading local. Existing comment updated to mention the new a11y attributes.
  • IconButton component: same aria_disabled and tabindex wiring tied to props.disabled. Existing comment retained.
  • Existing hero-btn-disabled / hero-icon-btn-disabled CSS class logic is unchanged, so visual styling is preserved.
  • Existing onclick guard if !is_disabled { props.onclick.call(e); } is preserved as defense-in-depth and continues to block programmatic clicks when disabled.

No CSS changes were needed because the HTML disabled attribute is intentionally not set — variant background and color rules continue to apply.

Test Results

  • cargo test -p hero_archipelagos_core — 8/8 unit tests + 1 doctest passing.
  • cargo check --workspace — clean (no new warnings).
  • Browser smoke test against the live messaging chat (port 8886):
    • Whitespace input → send button has aria-disabled="true", tabindex="-1", hero-btn-disabled class.
    • "hello" input → send button flips to aria-disabled="false", tabindex="0", no disabled class.
    • btn.click() while disabled → onclick guard prevents handle_send from firing (chat input remains untouched).
## Summary The shared `Button` and `IconButton` components rendered the `hero-btn-disabled` class but no a11y/keyboard semantics, so disabled buttons stayed in the tab order, were not announced as disabled by screen readers, and programmatic `btn.click()` was only stopped by the in-handler guard. This PR adds `aria-disabled` and `tabindex` driven by the same state used for the disabled CSS class. The HTML `disabled` attribute is still intentionally not set, per the existing design constraint in the component (UA grey would override the variant background colors). ## Related Issue Closes https://forge.ourworld.tf/lhumina_code/hero_archipelagos/issues/184 ## Changes - `Button` component: emit `aria_disabled` and `tabindex` attributes that flip with the existing `is_disabled = props.disabled || props.loading` local. Existing comment updated to mention the new a11y attributes. - `IconButton` component: same `aria_disabled` and `tabindex` wiring tied to `props.disabled`. Existing comment retained. - Existing `hero-btn-disabled` / `hero-icon-btn-disabled` CSS class logic is unchanged, so visual styling is preserved. - Existing onclick guard `if !is_disabled { props.onclick.call(e); }` is preserved as defense-in-depth and continues to block programmatic clicks when disabled. No CSS changes were needed because the HTML `disabled` attribute is intentionally not set — variant background and color rules continue to apply. ## Test Results - `cargo test -p hero_archipelagos_core` — 8/8 unit tests + 1 doctest passing. - `cargo check --workspace` — clean (no new warnings). - Browser smoke test against the live messaging chat (port 8886): - Whitespace input → send button has `aria-disabled="true"`, `tabindex="-1"`, `hero-btn-disabled` class. - `"hello"` input → send button flips to `aria-disabled="false"`, `tabindex="0"`, no disabled class. - `btn.click()` while disabled → onclick guard prevents `handle_send` from firing (chat input remains untouched).
fix(core): set aria-disabled and tabindex on Button when disabled
All checks were successful
Build and Test / build (pull_request) Successful in 7m52s
ca986a90f4
The shared Button and IconButton components rendered the
hero-btn-disabled class but no a11y/keyboard semantics, so disabled
buttons stayed in the tab order, were not announced as disabled by
screen readers, and programmatic btn.click() was only stopped by the
in-handler guard. Add aria-disabled and tabindex driven by the same
state used for the disabled CSS class. The HTML disabled attribute is
still intentionally not set, since UA grey would override the variant
background colors.

#184
rawdaGastan merged commit ce789f135f into development 2026-05-07 12:18:14 +00:00
rawdaGastan deleted branch development_button_disabled_attribute 2026-05-07 12:18:20 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_archipelagos!213
No description provided.