Skip to content

Commit f62c1d1

Browse files
committed
fix(input-password-toggle, button): force update aria attributes
1 parent c3ad15b commit f62c1d1

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

core/src/components/button/button.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComponentInterface, EventEmitter } from '@stencil/core';
2-
import { Component, Element, Event, Host, Prop, Watch, State, h } from '@stencil/core';
2+
import { Component, Element, Event, Host, Prop, Watch, State, forceUpdate, h } from '@stencil/core';
33
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
44
import type { Attributes } from '@utils/helpers';
55
import { inheritAriaAttributes, hasShadowDom } from '@utils/helpers';
@@ -158,6 +158,26 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
158158
*/
159159
@Event() ionBlur!: EventEmitter<void>;
160160

161+
/**
162+
* This component is used within the `ion-input-password-toggle` component
163+
* to toggle the visibility of the password input.
164+
* These attributes need to update based on the state of the password input.
165+
* Otherwise, the values will be stale.
166+
*
167+
* @param newValue
168+
* @param _oldValue
169+
* @param propName
170+
*/
171+
@Watch('aria-checked')
172+
@Watch('aria-label')
173+
onAriaChanged(newValue: string, _oldValue: string, propName: string) {
174+
this.inheritedAttributes = {
175+
...this.inheritedAttributes,
176+
[propName]: newValue,
177+
};
178+
forceUpdate(this);
179+
}
180+
161181
/**
162182
* This is responsible for rendering a hidden native
163183
* button element inside the associated form. This allows

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class InputPasswordToggle implements ComponentInterface {
127127
fill="clear"
128128
shape="round"
129129
aria-checked={isPasswordVisible ? 'true' : 'false'}
130-
aria-label="show password"
130+
aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
131131
role="switch"
132132
type="button"
133133
onPointerDown={(ev) => {

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,38 @@ configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
2020
expect(results.violations).toEqual([]);
2121
});
2222
});
23+
24+
test.describe(title('input password toggle: aria attributes'), () => {
25+
test('should inherit aria attributes to inner button on load', async ({ page }) => {
26+
await page.setContent(
27+
`
28+
<ion-input label="input" type="password">
29+
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
30+
</ion-input>
31+
`,
32+
config
33+
);
34+
35+
const nativeButton = page.locator('ion-input-password-toggle button');
36+
37+
await expect(nativeButton).toHaveAttribute('aria-label', 'Show password');
38+
await expect(nativeButton).toHaveAttribute('aria-checked', 'false');
39+
});
40+
test('should inherit aria attributes to inner button after toggle', async ({ page }) => {
41+
await page.setContent(
42+
`
43+
<ion-input label="input" type="password">
44+
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
45+
</ion-input>
46+
`,
47+
config
48+
);
49+
50+
const nativeButton = page.locator('ion-input-password-toggle button');
51+
await nativeButton.click();
52+
53+
await expect(nativeButton).toHaveAttribute('aria-label', 'Hide password');
54+
await expect(nativeButton).toHaveAttribute('aria-checked', 'true');
55+
});
56+
});
2357
});

0 commit comments

Comments
 (0)