From 45f7d2fea873ae1018a8b079efb21a999aaca2ea Mon Sep 17 00:00:00 2001 From: Gethin Webster Date: Wed, 9 Aug 2023 15:32:54 +0200 Subject: [PATCH] feat: Use i18nStrings as fallback flash icon labels (#1426) --- .../__snapshots__/documenter.test.ts.snap | 1 + src/flashbar/__tests__/collapsible.test.tsx | 25 +++++++++++++ src/flashbar/__tests__/flashbar.test.tsx | 35 ++++++++++++++++--- src/flashbar/collapsible-flashbar.tsx | 1 + src/flashbar/flash.tsx | 7 +++- src/flashbar/interfaces.ts | 1 + src/flashbar/non-collapsible-flashbar.tsx | 8 +++++ 7 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/__tests__/__snapshots__/documenter.test.ts.snap b/src/__tests__/__snapshots__/documenter.test.ts.snap index ac1d459185..23aa3af98d 100644 --- a/src/__tests__/__snapshots__/documenter.test.ts.snap +++ b/src/__tests__/__snapshots__/documenter.test.ts.snap @@ -6522,6 +6522,7 @@ A flash message object contains the following properties: When a user clicks on this button the \`onDismiss\` handler is called. * \`dismissLabel\` (string) - Specifies an \`aria-label\` for to the dismiss icon button for improved accessibility. * \`statusIconAriaLabel\` (string) - Specifies an \`aria-label\` for to the status icon for improved accessibility. +If not provided, \`i18nStrings.{type}IconAriaLabel\` will be used as a fallback. * \`ariaRole\` (string) - For flash messages added after page load, specifies how this message is communicated to assistive technology. Use \\"status\\" for status updates or informational content. Use \\"alert\\" for important messages that need the user's attention. diff --git a/src/flashbar/__tests__/collapsible.test.tsx b/src/flashbar/__tests__/collapsible.test.tsx index 486ac1ecc5..f236c6e7ad 100644 --- a/src/flashbar/__tests__/collapsible.test.tsx +++ b/src/flashbar/__tests__/collapsible.test.tsx @@ -301,6 +301,31 @@ describe('Collapsible Flashbar', () => { expect(innerCounter!.querySelector(`[title="${ariaLabel}"]`)).toBeTruthy(); } }); + + test.each([['success'], ['error'], ['info'], ['warning'], ['in-progress']] as FlashbarProps.Type[][])( + 'item icon has aria-label from i18nStrings when no statusIconAriaLabel provided: type %s', + type => { + const wrapper = renderFlashbar({ + i18nStrings: { + successIconAriaLabel: 'success', + errorIconAriaLabel: 'error', + infoIconAriaLabel: 'info', + warningIconAriaLabel: 'warning', + inProgressIconAriaLabel: 'in-progress', + }, + items: [ + { + header: 'The header', + content: 'The content', + type: type === 'in-progress' ? 'info' : type, + loading: type === 'in-progress', + }, + ], + }); + + expect(wrapper.findItems()[0].find('[role="img"]')?.getElement()).toHaveAccessibleName(type); + } + ); }); describe('Sticky', () => { diff --git a/src/flashbar/__tests__/flashbar.test.tsx b/src/flashbar/__tests__/flashbar.test.tsx index 88fcff7dd6..3f93a94a9e 100644 --- a/src/flashbar/__tests__/flashbar.test.tsx +++ b/src/flashbar/__tests__/flashbar.test.tsx @@ -343,7 +343,7 @@ describe('Flashbar component', () => { }); test('icon has an aria-label when statusIconAriaLabel is provided', () => { - const iconLabel = 'Warning'; + const iconLabel = 'Info'; const wrapper = createFlashbarWrapper( { /> ); - expect(wrapper.findItems()[0].find(`:scope [aria-label]`)?.getElement()).toHaveAttribute( - 'aria-label', - iconLabel - ); + expect(wrapper.findItems()[0].find('[role="img"]')?.getElement()).toHaveAccessibleName(iconLabel); }); + test.each([['success'], ['error'], ['info'], ['warning'], ['in-progress']] as FlashbarProps.Type[][])( + 'icon has aria-label from i18nStrings when no statusIconAriaLabel provided: type %s', + type => { + const wrapper = createFlashbarWrapper( + Click me, + type: type === 'in-progress' ? 'info' : type, + loading: type === 'in-progress', + }, + ]} + /> + ); + + expect(wrapper.findItems()[0].find('[role="img"]')?.getElement()).toHaveAccessibleName(type); + } + ); + describe('Accessibility', () => { test('renders items in an unordered list', () => { const flashbar = createFlashbarWrapper( diff --git a/src/flashbar/collapsible-flashbar.tsx b/src/flashbar/collapsible-flashbar.tsx index 14935e9121..a32edc599d 100644 --- a/src/flashbar/collapsible-flashbar.tsx +++ b/src/flashbar/collapsible-flashbar.tsx @@ -277,6 +277,7 @@ export default function CollapsibleFlashbar({ items, ...restProps }: FlashbarPro key={getItemId(item)} ref={shouldUseStandardAnimation(item, index) ? transitionRootElement : undefined} transitionState={shouldUseStandardAnimation(item, index) ? state : undefined} + i18nStrings={iconAriaLabels} {...item} /> )} diff --git a/src/flashbar/flash.tsx b/src/flashbar/flash.tsx index 086328fa51..9807326718 100644 --- a/src/flashbar/flash.tsx +++ b/src/flashbar/flash.tsx @@ -68,6 +68,7 @@ export const focusFlashById = throttle( export interface FlashProps extends FlashbarProps.MessageDefinition { className: string; transitionState?: string; + i18nStrings?: FlashbarProps.I18nStrings; } export const Flash = React.forwardRef( @@ -87,6 +88,7 @@ export const Flash = React.forwardRef( className, transitionState, ariaRole, + i18nStrings, type = 'info', }: FlashProps, ref: React.Ref @@ -153,7 +155,10 @@ export const Flash = React.forwardRef(
{icon}
diff --git a/src/flashbar/interfaces.ts b/src/flashbar/interfaces.ts index c5cc389b41..ed6837ff0f 100644 --- a/src/flashbar/interfaces.ts +++ b/src/flashbar/interfaces.ts @@ -50,6 +50,7 @@ export interface FlashbarProps extends BaseComponentProps { * When a user clicks on this button the `onDismiss` handler is called. * * `dismissLabel` (string) - Specifies an `aria-label` for to the dismiss icon button for improved accessibility. * * `statusIconAriaLabel` (string) - Specifies an `aria-label` for to the status icon for improved accessibility. + * If not provided, `i18nStrings.{type}IconAriaLabel` will be used as a fallback. * * `ariaRole` (string) - For flash messages added after page load, specifies how this message is communicated to assistive * technology. Use "status" for status updates or informational content. Use "alert" for important messages that need the * user's attention. diff --git a/src/flashbar/non-collapsible-flashbar.tsx b/src/flashbar/non-collapsible-flashbar.tsx index c7cbabc2e6..bd8bbf0c92 100644 --- a/src/flashbar/non-collapsible-flashbar.tsx +++ b/src/flashbar/non-collapsible-flashbar.tsx @@ -22,6 +22,13 @@ export default function NonCollapsibleFlashbar({ items, i18nStrings, ...restProp const i18n = useInternalI18n('flashbar'); const ariaLabel = i18n('i18nStrings.ariaLabel', i18nStrings?.ariaLabel); + const iconAriaLabels = { + errorIconAriaLabel: i18n('i18nStrings.errorIconAriaLabel', i18nStrings?.errorIconAriaLabel), + inProgressIconAriaLabel: i18n('i18nStrings.inProgressIconAriaLabel', i18nStrings?.inProgressIconAriaLabel), + infoIconAriaLabel: i18n('i18nStrings.infoIconAriaLabel', i18nStrings?.infoIconAriaLabel), + successIconAriaLabel: i18n('i18nStrings.successIconAriaLabel', i18nStrings?.successIconAriaLabel), + warningIconAriaLabel: i18n('i18nStrings.warningIconAriaLabel', i18nStrings?.warningIconAriaLabel), + }; /** * All the flash items should have ids so we can identify which DOM element is being @@ -99,6 +106,7 @@ export default function NonCollapsibleFlashbar({ items, i18nStrings, ...restProp key={key} ref={transitionRootElement} transitionState={transitionState} + i18nStrings={iconAriaLabels} {...item} /> );