From da7955644a4bc48af524510096ca35b9b4a92ce2 Mon Sep 17 00:00:00 2001 From: Riley Pearce <54197972+rilrom@users.noreply.github.com> Date: Tue, 27 Feb 2024 03:47:13 +1030 Subject: [PATCH] [@mantine/core] Switch: Use `role="switch"` for better accessibility (#5746) Co-authored-by: Riley Pearce --- packages/@mantine-tests/core/src/index.ts | 4 +-- .../src/inputs/it-handles-checkbox-state.tsx | 32 ------------------- .../it-handles-switch-checkbox-state.tsx | 32 +++++++++++++++++++ .../components/InlineInput/InlineInput.tsx | 21 +++++++++--- .../src/components/Switch/Switch.test.tsx | 4 +-- .../core/src/components/Switch/Switch.tsx | 6 ++-- .../Switch/SwitchGroup/SwitchGroup.test.tsx | 14 ++++---- 7 files changed, 64 insertions(+), 49 deletions(-) delete mode 100644 packages/@mantine-tests/core/src/inputs/it-handles-checkbox-state.tsx create mode 100644 packages/@mantine-tests/core/src/inputs/it-handles-switch-checkbox-state.tsx diff --git a/packages/@mantine-tests/core/src/index.ts b/packages/@mantine-tests/core/src/index.ts index 739874c66ef..6a01a1b79ca 100644 --- a/packages/@mantine-tests/core/src/index.ts +++ b/packages/@mantine-tests/core/src/index.ts @@ -1,7 +1,7 @@ import userEvent from '@testing-library/user-event'; import { axe } from './axe'; import { itConnectsLabelAndInput } from './inputs/it-connects-label-and-input'; -import { itHandlesCheckboxState } from './inputs/it-handles-checkbox-state'; +import { itHandlesSwitchCheckboxState } from './inputs/it-handles-switch-checkbox-state'; import { itSupportsInputAsterisk } from './inputs/it-supports-input-asterisk'; import { itSupportsInputContainer } from './inputs/it-supports-input-container'; import { itSupportsInputProps } from './inputs/it-supports-input-props'; @@ -73,7 +73,7 @@ export const tests = { itSupportsInputAsterisk, itSupportsInputWrapperOrder, itSupportsInputWrapperElements, - itHandlesCheckboxState, + itHandlesSwitchCheckboxState, itConnectsLabelAndInput, itSupportsSystemProps, diff --git a/packages/@mantine-tests/core/src/inputs/it-handles-checkbox-state.tsx b/packages/@mantine-tests/core/src/inputs/it-handles-checkbox-state.tsx deleted file mode 100644 index ba233c5222a..00000000000 --- a/packages/@mantine-tests/core/src/inputs/it-handles-checkbox-state.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { render } from '../render'; - -interface Options { - component: React.ComponentType; - props: Props; -} - -export function itHandlesCheckboxState( - options: Options, - name = 'handles checkbox state' -) { - describe(name, () => { - it('correctly handles controlled checkbox state', async () => { - const spy = jest.fn(); - render(); - expect(screen.getByRole('checkbox')).not.toBeChecked(); - await userEvent.click(screen.getByRole('checkbox')); - expect(spy).toHaveBeenCalledTimes(1); - expect(screen.getByRole('checkbox')).not.toBeChecked(); - }); - - it('correctly handles uncontrolled checkbox state', async () => { - render(); - expect(screen.getByRole('checkbox')).not.toBeChecked(); - await userEvent.click(screen.getByRole('checkbox')); - expect(screen.getByRole('checkbox')).toBeChecked(); - }); - }); -} diff --git a/packages/@mantine-tests/core/src/inputs/it-handles-switch-checkbox-state.tsx b/packages/@mantine-tests/core/src/inputs/it-handles-switch-checkbox-state.tsx new file mode 100644 index 00000000000..9eba0a249ed --- /dev/null +++ b/packages/@mantine-tests/core/src/inputs/it-handles-switch-checkbox-state.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { render } from '../render'; + +interface Options { + component: React.ComponentType; + props: Props; +} + +export function itHandlesSwitchCheckboxState( + options: Options, + name = 'handles switch checkbox state' +) { + describe(name, () => { + it('correctly handles controlled switch checkbox state', async () => { + const spy = jest.fn(); + render(); + expect(screen.getByRole('switch')).not.toBeChecked(); + await userEvent.click(screen.getByRole('switch')); + expect(spy).toHaveBeenCalledTimes(1); + expect(screen.getByRole('switch')).not.toBeChecked(); + }); + + it('correctly handles uncontrolled switch checkbox state', async () => { + render(); + expect(screen.getByRole('switch')).not.toBeChecked(); + await userEvent.click(screen.getByRole('switch')); + expect(screen.getByRole('switch')).toBeChecked(); + }); + }); +} diff --git a/packages/@mantine/core/src/components/InlineInput/InlineInput.tsx b/packages/@mantine/core/src/components/InlineInput/InlineInput.tsx index 8e608439578..8f9add41db3 100644 --- a/packages/@mantine/core/src/components/InlineInput/InlineInput.tsx +++ b/packages/@mantine/core/src/components/InlineInput/InlineInput.tsx @@ -36,6 +36,8 @@ export interface InlineInputProps error: React.ReactNode; size: MantineSize | (string & {}) | undefined; labelPosition?: 'left' | 'right'; + bodyElement?: any; + labelElement?: any; } export type InlineInputFactory = Factory<{ @@ -60,6 +62,8 @@ export const InlineInput = forwardRef( error, size, labelPosition = 'left', + bodyElement = 'div', + labelElement = 'label', variant, style, vars, @@ -92,14 +96,23 @@ export const InlineInput = forwardRef( size={size} {...others} > -
+ {children}
{label && ( - + )} {description && ( @@ -114,7 +127,7 @@ export const InlineInput = forwardRef( )}
-
+ ); } diff --git a/packages/@mantine/core/src/components/Switch/Switch.test.tsx b/packages/@mantine/core/src/components/Switch/Switch.test.tsx index 0304679c915..1cf614f0452 100644 --- a/packages/@mantine/core/src/components/Switch/Switch.test.tsx +++ b/packages/@mantine/core/src/components/Switch/Switch.test.tsx @@ -12,7 +12,7 @@ const defaultProps: SwitchProps = { describe('@mantine/core/Switch', () => { tests.axe([, ]); tests.itSupportsFocusEvents({ component: Switch, props: defaultProps, selector: 'input' }); - tests.itHandlesCheckboxState({ component: Switch, props: defaultProps }); + tests.itHandlesSwitchCheckboxState({ component: Switch, props: defaultProps }); tests.itConnectsLabelAndInput({ component: Switch, props: defaultProps }); tests.itSupportsSystemProps({ component: Switch, @@ -59,7 +59,7 @@ describe('@mantine/core/Switch', () => { it('sets disabled attribute on input based on disabled prop', () => { render(); - expect(screen.getByRole('checkbox')).toBeDisabled(); + expect(screen.getByRole('switch')).toBeDisabled(); }); it('exposes SwitchGroup component', () => { diff --git a/packages/@mantine/core/src/components/Switch/Switch.tsx b/packages/@mantine/core/src/components/Switch/Switch.tsx index a8ec1c7d452..99e9268f023 100644 --- a/packages/@mantine/core/src/components/Switch/Switch.tsx +++ b/packages/@mantine/core/src/components/Switch/Switch.tsx @@ -187,6 +187,8 @@ export const Switch = factory((_props, ref) => { description={description} error={error} disabled={disabled} + bodyElement="label" + labelElement="span" classNames={classNames} styles={styles} unstyled={unstyled} @@ -208,12 +210,12 @@ export const Switch = factory((_props, ref) => { id={uuid} ref={ref} type="checkbox" + role="switch" {...getStyles('input')} />