Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions core/src/components/alert/alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,6 @@ export class Alert implements ComponentInterface, OverlayInterface {
onKeydown(ev: any) {
const inputTypes = new Set(this.processedInputs.map((i) => i.type));

/**
* Based on keyboard navigation requirements, the
* checkbox should not respond to the enter keydown event.
*/
if (inputTypes.has('checkbox') && ev.key === 'Enter') {
ev.preventDefault();
return;
}

/**
* Ensure when alert container is being focused, and the user presses the tab + shift keys, the focus will be set to the last alert button.
*/
Expand Down Expand Up @@ -525,6 +516,15 @@ export class Alert implements ComponentInterface, OverlayInterface {
forceUpdate(this);
}

/**
* Prevent Enter from toggling the checkbox, which only Space should do.
*/
private onCheckboxKeydown = (ev: KeyboardEvent) => {
if (ev.key === 'Enter') {
ev.preventDefault();
}
};

private async buttonClick(button: AlertButton) {
const role = button.role;
const values = this.getValues();
Expand Down Expand Up @@ -625,6 +625,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
<button
type="button"
onClick={() => this.cbClick(i)}
onKeyDown={this.onCheckboxKeydown}
aria-checked={`${i.checked}`}
id={i.id}
disabled={i.disabled}
Expand Down
63 changes: 63 additions & 0 deletions core/src/components/alert/test/a11y/alert.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,69 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
});
});

/**
* This behavior does not vary across modes/directions
*/
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('alert: Enter key with checkbox inputs'), () => {
test('should not block Enter in elements outside of the alert', async ({ page }, testInfo) => {
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/30811',
});

await page.setContent(
`
<textarea></textarea>
<ion-alert header="Alert"></ion-alert>

<script>
const alert = document.querySelector('ion-alert');
alert.inputs = [{ type: 'checkbox', label: 'Checkbox', value: 'checkbox' }];
</script>
`,
config
);

// The alert isn't presented since it would trap focus away from the textarea
const textarea = page.locator('textarea');
await textarea.click();
await textarea.press('a');
await textarea.press('Enter');
await textarea.press('b');

await expect(textarea).toHaveValue('a\nb');
});

test('should dismiss the alert when pressing Enter on a button', async ({ page }) => {
await page.setContent(
`
<ion-alert header="Alert"></ion-alert>

<script>
const alert = document.querySelector('ion-alert');
alert.inputs = [{ type: 'checkbox', label: 'Checkbox', value: 'checkbox' }];
alert.buttons = ['OK'];
</script>
`,
config
);

const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
const alert = page.locator('ion-alert');

await alert.evaluate((el: HTMLIonAlertElement) => el.present());
await ionAlertDidPresent.next();

await alert.locator('.alert-button').press('Enter');
await ionAlertDidDismiss.next();

await expect(alert).toBeHidden();
});
});
});

/**
* This behavior does not vary across directions
*/
Expand Down
Loading