diff --git a/CHANGELOG.md b/CHANGELOG.md index e99909c003..a756e11238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add `Popup` styles to Teams Dark and High Contrast themes @kuzhelov ([#1121](https://github.com/stardust-ui/react/pull/1121)) - export `flag` icon in Teams theme @jaanus03 ([#1133](https://github.com/stardust-ui/react/pull/1133)) - Make `MenuItem`'s submenu open state controlled @sophieH29 ([#1125](https://github.com/stardust-ui/react/pull/1125)) +### Features +- Add behaviors for `Alert` component @jurokapsiar ([#1119](https://github.com/stardust-ui/react/pull/1119)) + ### BREAKING CHANGES - `color` and `backgroundColor` variables were moved from `PopupContent` to `popup` slot of `Popup` component @kuzhelov ([#1121](https://github.com/stardust-ui/react/pull/1121)) diff --git a/packages/react/src/components/Alert/Alert.tsx b/packages/react/src/components/Alert/Alert.tsx index ce09948537..b412c64938 100644 --- a/packages/react/src/components/Alert/Alert.tsx +++ b/packages/react/src/components/Alert/Alert.tsx @@ -11,7 +11,7 @@ import { rtlTextContainer, } from '../../lib' import { RenderResultConfig } from 'src/lib/renderComponent' -import { defaultBehavior } from '../../lib/accessibility' +import { alertBehavior } from '../../lib/accessibility' import { Accessibility } from '../../lib/accessibility/types' import { ReactProps, ShorthandValue } from '../../types' import Box from '../Box/Box' @@ -25,7 +25,8 @@ export interface AlertSlotClassNames { export interface AlertProps extends UIComponentProps, ContentComponentProps { /** * Accessibility behavior if overridden by the user. - * @default defaultBehavior + * @default alertBehavior + * @available alertWarningBehavior */ accessibility?: Accessibility @@ -52,6 +53,7 @@ export interface AlertProps extends UIComponentProps, ContentComponentProps> { @@ -73,9 +75,9 @@ class Alert extends UIComponent> { warning: PropTypes.bool, } - static defaultProps = { accessibility: defaultBehavior } + static defaultProps = { accessibility: alertBehavior } - renderContent = ({ styles }: RenderResultConfig) => { + renderContent = ({ styles, accessibility }: RenderResultConfig) => { const { action, content } = this.props return ( @@ -84,6 +86,7 @@ class Alert extends UIComponent> { defaultProps: { className: Alert.slotClassNames.content, styles: styles.content, + ...accessibility.attributes.content, }, })} {Button.create(action, { diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index a60c53f318..5606ccbf97 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -189,6 +189,10 @@ export { } from './lib/accessibility/Behaviors/Popup/popupAutoFocusBehavior' export { default as dialogBehavior } from './lib/accessibility/Behaviors/Dialog/dialogBehavior' export { default as statusBehavior } from './lib/accessibility/Behaviors/Status/statusBehavior' +export { default as alertBehavior } from './lib/accessibility/Behaviors/Alert/alertBehavior' +export { + default as alertWarningBehavior, +} from './lib/accessibility/Behaviors/Alert/alertWarningBehavior' // // Utilities diff --git a/packages/react/src/lib/accessibility/Behaviors/Alert/alertBehavior.ts b/packages/react/src/lib/accessibility/Behaviors/Alert/alertBehavior.ts new file mode 100644 index 0000000000..bf89d810de --- /dev/null +++ b/packages/react/src/lib/accessibility/Behaviors/Alert/alertBehavior.ts @@ -0,0 +1,13 @@ +import { Accessibility } from '../../types' +import alertWarningBehavior from './alertWarningBehavior' +import defaultBehavior from '../defaultBehavior' + +/** + * @description + * Uses 'alertWarningBehavior` for 'danger' and 'warning' variants. + * Uses 'defaultBehavior` for 'success' and 'info' variants. + */ +const alertBehavior: Accessibility = (props: any) => + props.warning || props.danger ? alertWarningBehavior(props) : defaultBehavior(props) + +export default alertBehavior diff --git a/packages/react/src/lib/accessibility/Behaviors/Alert/alertWarningBehavior.ts b/packages/react/src/lib/accessibility/Behaviors/Alert/alertWarningBehavior.ts new file mode 100644 index 0000000000..cbf70712fd --- /dev/null +++ b/packages/react/src/lib/accessibility/Behaviors/Alert/alertWarningBehavior.ts @@ -0,0 +1,18 @@ +import { Accessibility } from '../../types' + +/** + * @specification + * Adds role 'alert' to 'content' component's part. + * Adds Adds attribute 'aria-live=polite' to 'content' component's part. + */ + +const alertWarningBehavior: Accessibility = (props: any) => ({ + attributes: { + content: { + role: 'alert', + 'aria-live': 'polite', + }, + }, +}) + +export default alertWarningBehavior diff --git a/packages/react/src/lib/accessibility/index.ts b/packages/react/src/lib/accessibility/index.ts index af7bcc5d0c..ccc04b9ebd 100644 --- a/packages/react/src/lib/accessibility/index.ts +++ b/packages/react/src/lib/accessibility/index.ts @@ -1,4 +1,6 @@ export { default as defaultBehavior } from './Behaviors/defaultBehavior' +export { default as alertBehavior } from './Behaviors/Alert/alertBehavior' +export { default as alertWarningBehavior } from './Behaviors/Alert/alertWarningBehavior' export { default as attachmentBehavior } from './Behaviors/Attachment/attachmentBehavior' export { default as buttonBehavior } from './Behaviors/Button/buttonBehavior' export { default as toggleButtonBehavior } from './Behaviors/Button/toggleButtonBehavior' diff --git a/packages/react/test/specs/behaviors/alertBehavior-test.tsx b/packages/react/test/specs/behaviors/alertBehavior-test.tsx new file mode 100644 index 0000000000..4e51dcda7b --- /dev/null +++ b/packages/react/test/specs/behaviors/alertBehavior-test.tsx @@ -0,0 +1,23 @@ +import { alertBehavior } from 'src/lib/accessibility' + +describe('AlertBehavior.ts', () => { + test('use alertWarningBehavior if warning prop is defined', () => { + const expectedResult = alertBehavior({ warning: true }) + expect(expectedResult.attributes.content.role).toEqual('alert') + }) + + test('use alertWarningBehavior if danger prop is defined', () => { + const expectedResult = alertBehavior({ danger: true }) + expect(expectedResult.attributes.content.role).toEqual('alert') + }) + + test('use defaultBehavior if success prop is defined', () => { + const expectedResult = alertBehavior({ success: true }) + expect(expectedResult.attributes.content).toBeUndefined() + }) + + test('use defaultBehavior if info prop is defined', () => { + const expectedResult = alertBehavior({ info: true }) + expect(expectedResult.attributes.content).toBeUndefined() + }) +}) diff --git a/packages/react/test/specs/behaviors/behavior-test.tsx b/packages/react/test/specs/behaviors/behavior-test.tsx index b586bed109..111b68e53a 100644 --- a/packages/react/test/specs/behaviors/behavior-test.tsx +++ b/packages/react/test/specs/behaviors/behavior-test.tsx @@ -33,6 +33,7 @@ import { treeTitleBehavior, gridBehavior, statusBehavior, + alertWarningBehavior, } from 'src/lib/accessibility' import { TestHelper } from './testHelper' import definitions from './testDefinitions' @@ -70,5 +71,6 @@ testHelper.addBehavior('treeTitleBehavior', treeTitleBehavior) testHelper.addBehavior('gridBehavior', gridBehavior) testHelper.addBehavior('dialogBehavior', dialogBehavior) testHelper.addBehavior('statusBehavior', statusBehavior) +testHelper.addBehavior('alertWarningBehavior', alertWarningBehavior) testHelper.run(behaviorMenuItems) diff --git a/packages/react/test/specs/behaviors/testHelper.tsx b/packages/react/test/specs/behaviors/testHelper.tsx index b051a8a3c3..0ac0454e51 100644 --- a/packages/react/test/specs/behaviors/testHelper.tsx +++ b/packages/react/test/specs/behaviors/testHelper.tsx @@ -22,6 +22,7 @@ const skipSpecChecksForFiles = [ 'chatMessageBehavior.ts', // issue https://github.com/stardust-ui/react/issues/476 'listBehavior.ts', // tests are written in listBehavior-test.tsx 'listItemBehavior.ts', // tests are written in listItemBehavior-test.tsx + 'alertBehavior.ts', // tests are written in alertBehavior-test.tsx ] export class TestHelper { diff --git a/packages/react/test/specs/components/Alert/Alert-test.tsx b/packages/react/test/specs/components/Alert/Alert-test.tsx index 91956a688f..a78451c5a1 100644 --- a/packages/react/test/specs/components/Alert/Alert-test.tsx +++ b/packages/react/test/specs/components/Alert/Alert-test.tsx @@ -1,4 +1,11 @@ -import { isConformant, implementsShorthandProp } from 'test/specs/commonTests' +import * as React from 'react' + +import { + isConformant, + implementsShorthandProp, + handlesAccessibility, + htmlIsAccessibilityCompliant, +} from 'test/specs/commonTests' import Alert from 'src/components/Alert/Alert' import Box from 'src/components/Box/Box' @@ -8,7 +15,24 @@ const alertImplementsShorthandProp = implementsShorthandProp(Alert) describe('Alert', () => { isConformant(Alert) + handlesAccessibility(Alert, { defaultRootRole: undefined, requiredProps: { content: 'test' } }) + handlesAccessibility(Alert, { + defaultRootRole: undefined, + partSelector: `.${Alert.slotClassNames.content}`, + requiredProps: { content: 'test' }, + }) + handlesAccessibility(Alert, { + defaultRootRole: 'alert', + partSelector: `.${Alert.slotClassNames.content}`, + requiredProps: { content: 'test', warning: true }, + }) alertImplementsShorthandProp('action', Button, { mapsValueToProp: 'content' }) alertImplementsShorthandProp('content', Box, { mapsValueToProp: 'children' }) + + describe('compliance', () => { + test('default', async () => await htmlIsAccessibilityCompliant()) + + test('danger', async () => await htmlIsAccessibilityCompliant()) + }) })