Skip to content

Commit 6f42bcc

Browse files
authored
feat(SelectDialog): add SR announcement for number of selected items (#7598)
Fixes #7592
1 parent 251e20a commit 6f42bcc

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

packages/main/src/components/SelectDialog/SelectDialog.cy.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,4 +303,24 @@ describe('SelectDialog', () => {
303303
cy.findByTestId('confirmBtn').should('be.visible').and('have.attr', 'disabled');
304304
cy.findByTestId('confirmBtn').should('have.attr', 'design', 'Emphasized');
305305
});
306+
307+
it('invisible messaging', () => {
308+
cy.mount(
309+
<SelectDialog open selectionMode={ListSelectionMode.Multiple}>
310+
<ListItemStandard text={'ListItem 1'} data-testid="1" />
311+
<ListItemStandard text={'ListItem 2'} data-testid="2" />
312+
<ListItemStandard text={'ListItem 3'} data-testid="3" />
313+
<ListItemStandard text={'ListItem 4'} data-testid="4" />
314+
</SelectDialog>,
315+
);
316+
cy.findByTestId('1').click();
317+
cy.findByText('Selected Items 1').should('exist');
318+
cy.findByTestId('1').click();
319+
cy.findByText('Selected Items 1').should('not.exist');
320+
cy.findByTestId('1').click();
321+
cy.findByTestId('2').click();
322+
cy.findByTestId('3').click();
323+
cy.findByTestId('4').click();
324+
cy.findByText('Selected Items 4').should('exist');
325+
});
306326
});

packages/main/src/components/SelectDialog/index.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
'use client';
22

3+
import type ListItemBase from '@ui5/webcomponents/dist/ListItemBase.js';
34
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
45
import IconMode from '@ui5/webcomponents/dist/types/IconMode.js';
56
import InputType from '@ui5/webcomponents/dist/types/InputType.js';
67
import ListSelectionMode from '@ui5/webcomponents/dist/types/ListSelectionMode.js';
78
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
9+
import InvisibleMessageMode from '@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js';
10+
import announce from '@ui5/webcomponents-base/dist/util/InvisibleMessage.js';
811
import iconSearch from '@ui5/webcomponents-icons/dist/search.js';
912
import { enrichEventWithDetails, useI18nBundle, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base';
1013
import { clsx } from 'clsx';
1114
import type { ReactNode } from 'react';
1215
import { forwardRef, useEffect, useState } from 'react';
13-
import { CANCEL, CLEAR, SEARCH, SELECT, SELECTED } from '../../i18n/i18n-defaults.js';
16+
// todo: remove comment once translations are available
17+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
18+
import { CANCEL, CLEAR, SEARCH, SELECT, SELECTED, SELECTED_ITEMS } from '../../i18n/i18n-defaults.js';
1419
import { Button, Dialog, FlexBox, FlexBoxAlignItems, Icon, Input, List, Text, Title } from '../../index.js';
1520
import type { Ui5CustomEvent } from '../../types/index.js';
1621
import type {
@@ -135,9 +140,8 @@ export interface SelectDialogPropTypes
135140
/**
136141
* This event will be fired when the dialog is confirmed by selecting an item in single selection mode or by pressing the confirmation button in multi selection mode.
137142
*/
138-
onConfirm?:
139-
| ((event: Ui5CustomEvent<ListDomRef, { selectedItems: ListItemStandardDomRef[] }>) => void)
140-
| ((event: Ui5CustomEvent<ButtonDomRef, { selectedItems: ListItemStandardDomRef[] }>) => void);
143+
onConfirm?: (event: Ui5CustomEvent<ListDomRef | ButtonDomRef, { selectedItems: ListItemBase[] }>) => void;
144+
141145
/**
142146
* This event will be fired when the cancel button is clicked or ESC key is pressed.
143147
*/
@@ -232,12 +236,18 @@ const SelectDialog = forwardRef<DialogDomRef, SelectDialogPropTypes>((props, ref
232236
setSearchValue('');
233237
};
234238

235-
const handleSelectionChange = (e) => {
239+
const handleSelectionChange: ListPropTypes['onSelectionChange'] = (e) => {
240+
const { selectedItems } = e.detail;
236241
if (typeof listProps?.onSelectionChange === 'function') {
237242
listProps.onSelectionChange(e);
238243
}
239244
if (selectionMode === ListSelectionMode.Multiple) {
240-
setSelectedItems(e.detail.selectedItems);
245+
setSelectedItems(selectedItems);
246+
if (selectedItems.length) {
247+
announce('Selected Items ' + selectedItems.length, InvisibleMessageMode.Polite);
248+
//todo: uncomment this, once translations are available
249+
// announce(i18nBundle.getText(SELECTED_ITEMS, selectedItems.length), InvisibleMessageMode.Polite);
250+
}
241251
} else {
242252
if (typeof onConfirm === 'function') {
243253
onConfirm(e);

packages/main/src/i18n/messagebundle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,5 +378,7 @@ HAS_DETAILS=Has Details
378378
#XACT: Message Item counter label
379379
COUNTER=Counter
380380

381+
#ACT: Screen reader announcement text for selection in the SelectDialog component when multi-selection mode is active. The placeholder represents a number.
382+
SELECTED_ITEMS=Selected Items {0}
381383

382384

0 commit comments

Comments
 (0)