Skip to content

Commit 12ede4b

Browse files
authored
fix(input-password-toggle): improve screen reader announcements (#30885)
Issue number: resolves internal --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? The `ion-input-password-toggle` button uses `role="switch"` with `aria-checked`, causing screen readers like VoiceOver to announce both a state ("On/Off") and an action ("Show/Hide password"). This results in confusing, redundant output such as "On, Hide Password" or "Off, Show Password". ## What is the new behavior? The password toggle button now uses `aria-pressed` instead of `role="switch"` with `aria-checked`. Screen readers announce the action-based label ("Show password" or "Hide password") along with the pressed state, and properly announce state changes when the button is activated. ## Does this introduce a breaking change? - [ ] Yes - [X] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> [Old Preview](https://ionic-framework-git-main-ionic1.vercel.app/src/components/input-password-toggle/test/basic) [New Preview](https://ionic-framework-git-fw-6920-ionic1.vercel.app/src/components/input-password-toggle/test/basic) Current dev build: ``` 8.7.15-dev.11766421552.180757ca ```
1 parent f83b000 commit 12ede4b

File tree

3 files changed

+6
-6
lines changed

3 files changed

+6
-6
lines changed

core/src/components/button/button.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
170170
*/
171171
@Watch('aria-checked')
172172
@Watch('aria-label')
173+
@Watch('aria-pressed')
173174
onAriaChanged(newValue: string, _oldValue: string, propName: string) {
174175
this.inheritedAttributes = {
175176
...this.inheritedAttributes,

core/src/components/input-password-toggle/input-password-toggle.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,8 @@ export class InputPasswordToggle implements ComponentInterface {
126126
color={color}
127127
fill="clear"
128128
shape="round"
129-
aria-checked={isPasswordVisible ? 'true' : 'false'}
130129
aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
131-
role="switch"
130+
aria-pressed={isPasswordVisible ? 'true' : 'false'}
132131
type="button"
133132
onPointerDown={(ev) => {
134133
/**

core/src/components/input-password-toggle/test/a11y/input-password-toggle.e2e.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
2222
});
2323

2424
test.describe(title('input password toggle: aria attributes'), () => {
25-
test('should inherit aria attributes to inner button on load', async ({ page }) => {
25+
test('should have correct aria attributes on load', async ({ page }) => {
2626
await page.setContent(
2727
`
2828
<ion-input label="input" type="password">
@@ -35,9 +35,9 @@ configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
3535
const nativeButton = page.locator('ion-input-password-toggle button');
3636

3737
await expect(nativeButton).toHaveAttribute('aria-label', 'Show password');
38-
await expect(nativeButton).toHaveAttribute('aria-checked', 'false');
38+
await expect(nativeButton).toHaveAttribute('aria-pressed', 'false');
3939
});
40-
test('should inherit aria attributes to inner button after toggle', async ({ page }) => {
40+
test('should update aria attributes after toggle', async ({ page }) => {
4141
await page.setContent(
4242
`
4343
<ion-input label="input" type="password">
@@ -51,7 +51,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
5151
await nativeButton.click();
5252

5353
await expect(nativeButton).toHaveAttribute('aria-label', 'Hide password');
54-
await expect(nativeButton).toHaveAttribute('aria-checked', 'true');
54+
await expect(nativeButton).toHaveAttribute('aria-pressed', 'true');
5555
});
5656
});
5757
});

0 commit comments

Comments
 (0)