feat(toggle): add required prop (#30156)

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?
- Currently, the screen reader do not announce the component as required
when `required={true}`.

## What is the new behavior?
- Added a new `required` prop to be used for accessibility purposes that
adds the `required` attribute to toggle's inner native input.

## 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.
-->
This commit is contained in:
Giuliana Silva
2025-02-04 09:59:01 +00:00
committed by GitHub
parent 166e43554e
commit 0bbb9f37b4
6 changed files with 52 additions and 3 deletions

View File

@ -75,3 +75,33 @@ describe('ion-toggle: disabled', () => {
expect(toggle.checked).toBe(false);
});
});
describe('ion-toggle: required', () => {
it('should have a required attribute in inner input when true', async () => {
const page = await newSpecPage({
components: [Toggle],
html: `
<ion-toggle required="true">Toggle</ion-toggle>
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const nativeInput = toggle.shadowRoot?.querySelector('input[role=switch]')!;
expect(nativeInput.hasAttribute('required')).toBeTruthy();
});
it('should not have a required attribute in inner input when false', async () => {
const page = await newSpecPage({
components: [Toggle],
html: `
<ion-toggle required="false">Toggle</ion-toggle>
`,
});
const toggle = page.body.querySelector('ion-toggle')!;
const nativeInput = toggle.shadowRoot?.querySelector('input[role=switch]')!;
expect(nativeInput.hasAttribute('required')).toBeFalsy();
});
});

View File

@ -108,6 +108,13 @@ export class Toggle implements ComponentInterface {
*/
@Prop() alignment?: 'start' | 'center';
/**
* If true, screen readers will announce it as a required field. This property
* works only for accessibility purposes, it will not prevent the form from
* submitting if the value is invalid.
*/
@Prop() required = false;
/**
* Emitted when the user switches the toggle on or off.
*
@ -290,7 +297,8 @@ export class Toggle implements ComponentInterface {
}
render() {
const { activated, color, checked, disabled, el, justify, labelPlacement, inputId, name, alignment } = this;
const { activated, color, checked, disabled, el, justify, labelPlacement, inputId, name, alignment, required } =
this;
const mode = getIonMode(this);
const value = this.getValue();
@ -327,6 +335,7 @@ export class Toggle implements ComponentInterface {
onFocus={() => this.onFocus()}
onBlur={() => this.onBlur()}
ref={(focusEl) => (this.focusEl = focusEl)}
required={required}
{...this.inheritedAttributes}
/>
<div