From 3f65934ebc694c95dc0494cef5d75a08d2415496 Mon Sep 17 00:00:00 2001 From: PiyushKashyapHCL Date: Mon, 21 Oct 2024 12:07:15 +0530 Subject: [PATCH 1/6] added keyboard accessibility to the header in datagrid --- CHANGELOG.md | 1 + src/DataGrid/DataGrid.tsx | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58f4005..262d0aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ - Added `tooltipPlacement` prop to the `MultipleSelectChip`, `Autocomplete` and `Panel` component. - Updated icon button spacing in Snackbar - Adjusted checkbox alignment in `DataGrid` component +- Added keyboard accessibility to the header in `DataGrid` component ### Breaking changes diff --git a/src/DataGrid/DataGrid.tsx b/src/DataGrid/DataGrid.tsx index 370756d..5917ea7 100644 --- a/src/DataGrid/DataGrid.tsx +++ b/src/DataGrid/DataGrid.tsx @@ -285,6 +285,11 @@ const StyledDataGrid = styled(MuiDataGrid)((props) => { marginTop: '0!important', }, }, + ...(props.hideFooter) && { + '& .MuiDataGrid-virtualScroller': { + borderBottom: `1px ${theme.palette.border.secondary} solid`, + }, + }, ...(props.totalCount <= 0) && { '& .MuiDataGrid-footerContainer': { borderTop: 'none', @@ -430,6 +435,7 @@ const DataGrid = ({ components, componentsProps, ...props }: DataGridProps) => { const rowCheckbox: HTMLElement | undefined = findTargetElement(target, 'PrivateSwitchBase-input', false); // find column header title element that contains column title and sorting icon as we are supporting click for whole space of title and icon in header title const columnHeaderTitle: HTMLElement | undefined = findTargetElement(target, 'MuiDataGrid-columnHeaderTitle', false); + const columnHeader: HTMLElement | undefined = findTargetElement(target, 'MuiDataGrid-columnHeader', false); // this is for us to navigate to the first row of the table body if (target && (event.key === 'Tab' || event.key === 'ArrowDown')) { // to find the first row in order to focus @@ -454,26 +460,37 @@ const DataGrid = ({ components, componentsProps, ...props }: DataGridProps) => { if (rowCheckbox) { rowCheckbox.focus(); } + if (!rowCheckbox && columnHeader) { + columnHeader.focus(); + } } }; - // this function handles when user use keydown on datagrid it will change focus from select all checkbox to column header row - const handleOnBaseCheckFocus = (event: React.FocusEvent) => { + /** + * Handles the focus event on the header of the DataGrid. + * @param event - The keyboard event triggered when the header is focused. + * This function prevents the default focus behavior, finds the column header row, + * and sets it to be focusable by adding a `tabindex` attribute. It then focuses + * on the column header row and adds a keydown event listener for keyboard navigation. + * Additionally, it removes the focus from the row when the header is focused. + */ + const handleOnHeaderFocus = (event: KeyboardEvent) => { event.preventDefault(); // need to get coloumn header row to so that we can focus on it. - const parentElem = findTargetElement(event.target, 'MuiDataGrid-columnHeaders', true); - if (parentElem && !parentElem.hasAttribute('tabindex')) { + const parentElem = findTargetElement(event.target, 'MuiDataGrid-root', true); + const columnHeaderRow = parentElem?.querySelector('.MuiDataGrid-columnHeaders') as HTMLDivElement; + if (columnHeaderRow && !columnHeaderRow.hasAttribute('tabindex')) { // add tabindex so that we can are able to focus on it. - parentElem.setAttribute('tabindex', '0'); + columnHeaderRow.setAttribute('tabindex', '0'); // need some wait to set attribute to take effect window.setTimeout(() => { - parentElem.focus(); + columnHeaderRow.focus(); }, 0); // add keydown event to coloumn header row for some keyboard navigation - parentElem.addEventListener('keydown', (e) => { + columnHeaderRow.addEventListener('keydown', (e) => { return handleOnColumnHeaderRowKeyDown(e); }); - parentElem.addEventListener('focus', () => { + columnHeaderRow.addEventListener('focus', () => { setFocusRow(''); // remove focus on the row when we focus on the header }, { once: true }); } @@ -639,10 +656,13 @@ const DataGrid = ({ components, componentsProps, ...props }: DataGridProps) => { baseCheckbox: { 'data-testid': DataGridTestIds.DATAGRID_CHECKBOX, onClick: onCheckboxClick, - onFocus: handleOnBaseCheckFocus, onKeyDown: handleOnCheckboxKeydown, }, }, + header: { + tabIndex: 0, + onFocus: handleOnHeaderFocus, + }, row: { tabIndex: 0, onKeyDown: handleOnRowKeyDown, From d5b86803bed6f273580a8306cb338bb3386180da Mon Sep 17 00:00:00 2001 From: PiyushKashyapHCL Date: Mon, 21 Oct 2024 12:36:48 +0530 Subject: [PATCH 2/6] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 262d0aa..982a22e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixed ### Changed +- Added keyboard accessibility to the header in `DataGrid` component ### Breaking changes @@ -53,7 +54,6 @@ - Added `tooltipPlacement` prop to the `MultipleSelectChip`, `Autocomplete` and `Panel` component. - Updated icon button spacing in Snackbar - Adjusted checkbox alignment in `DataGrid` component -- Added keyboard accessibility to the header in `DataGrid` component ### Breaking changes From 8bdf9e890db5335f63cf27797e94f869e907cd84 Mon Sep 17 00:00:00 2001 From: PiyushKashyapHCL Date: Mon, 21 Oct 2024 20:56:44 +0530 Subject: [PATCH 3/6] Fixed pagination spacing --- src/Pagination/Pagination.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pagination/Pagination.tsx b/src/Pagination/Pagination.tsx index f7b745a..96abc5e 100644 --- a/src/Pagination/Pagination.tsx +++ b/src/Pagination/Pagination.tsx @@ -84,7 +84,7 @@ export const getMuiTablePaginationThemeOverrides = (): Components .autocomplete-container': { - margin: '0 12px 0 4px', + margin: '0 4px', }, }, 'div[data-testid=tablePaginationActionsPageDiv]': { From d20f9d70717d56f547a30e844b375794b18817b1 Mon Sep 17 00:00:00 2001 From: PiyushKashyapHCL Date: Tue, 29 Oct 2024 16:11:12 +0530 Subject: [PATCH 4/6] Added focus to the input label of TextField and SelectMultiple components --- CHANGELOG.md | 1 + src/Select/SelectMultiple.stories.tsx | 2 - src/TextField/TextField.tsx | 39 +++++++++++++++---- .../InputLabelAndAction.tsx | 7 ++-- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 982a22e..5ed5f88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed - Added keyboard accessibility to the header in `DataGrid` component +- Added focus to the input label in `TextField` and `SelectMultiple` components ### Breaking changes diff --git a/src/Select/SelectMultiple.stories.tsx b/src/Select/SelectMultiple.stories.tsx index c6f0589..808d7b3 100644 --- a/src/Select/SelectMultiple.stories.tsx +++ b/src/Select/SelectMultiple.stories.tsx @@ -15,7 +15,6 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; -import OutlinedInput from '@mui/material/OutlinedInput/OutlinedInput'; import { userEvent, within } from '@storybook/testing-library'; import Select, { SelectChangeEvent } from './Select'; @@ -128,7 +127,6 @@ const Template: StoryFn = (args) => { {...args} value={values} onChange={handleChange} - input={} renderValue={(selected) => { if ((selected as string[]).length === 0) { return {args.placeholder}; diff --git a/src/TextField/TextField.tsx b/src/TextField/TextField.tsx index 6bc414c..7e4ea4f 100644 --- a/src/TextField/TextField.tsx +++ b/src/TextField/TextField.tsx @@ -23,6 +23,7 @@ import { } from '@mui/material'; import { unstable_useId as useId } from '@mui/utils'; +import { styled } from '@mui/material/styles'; import Typography from '../Typography'; import InputLabelAndAction, { InputLabelAndActionProps, ActionProps } from '../prerequisite_components/InputLabelAndAction/InputLabelAndAction'; import { ThemeDirectionType } from '../theme'; @@ -264,6 +265,14 @@ export const getMuiTextFieldThemeOverrides = (): Components { + return { + '.MuiAutocomplete--label--focused': { + color: theme.theme.palette.primary.main, + }, + }; +}); + const getEndAdornment = (props: TextFieldProps, isComboBox: boolean) => { // This is workaround until proper Search component has already been implemented // This hides the endAdornment when startAdornment is present and it's a simple Textfield (NOT affecting Autocomplete / Multiselect) @@ -282,7 +291,7 @@ const getEndAdornment = (props: TextFieldProps, isComboBox: boolean) => { ); }; -const getInputLabelAndActionProps = (props: TextFieldProps): InputLabelAndActionProps => { +const getInputLabelAndActionProps = (props: TextFieldProps, isFocus: boolean): InputLabelAndActionProps => { const inputLabelId = props.label && props.id ? `${props.id}-label` : undefined; const inputLabelProps: InputLabelAndActionProps = { color: props.color, @@ -297,6 +306,7 @@ const getInputLabelAndActionProps = (props: TextFieldProps): InputLabelAndAction actionProps: props.actionProps, hiddenLabel: props.hiddenLabel, fullWidth: props.fullWidth, + isFocus, }; return inputLabelProps; }; @@ -348,7 +358,7 @@ const renderNonEditInput = (props: TextFieldProps, muiTextFieldProps: OutlinedTe return {muiTextFieldProps.value ? muiTextFieldProps.value : null}; }; -const renderInput = (props: TextFieldProps) => { +const renderInput = (props: TextFieldProps, setIsFocus: React.Dispatch>) => { const muiTextFieldProps = getMuiTextFieldProps(props); const helperTextId = props.helperText && props.id ? `${props.id}-helper-text` : undefined; if (props.nonEdit) { @@ -359,21 +369,34 @@ const renderInput = (props: TextFieldProps) => { ); } - return ; + return ( + { + setIsFocus(true); + }} + onBlur={() => { + setIsFocus(false); + }} + /> + ); }; const TextField = React.forwardRef(({ ...props }: TextFieldProps, forwardRef: React.ForwardedRef) => { - const muiInputLabelProps = getInputLabelAndActionProps(props); + const [isFocus, setIsFocus] = React.useState(false); + const muiInputLabelProps = getInputLabelAndActionProps(props, isFocus); if (!props.id) { const id = useId(); props.id = id; } const muiFormControlProps = getMuiFormControlProps(props, forwardRef); return ( - - - {renderInput(props)} - + + + + {renderInput(props, setIsFocus)} + + ); }) as React.FC; diff --git a/src/prerequisite_components/InputLabelAndAction/InputLabelAndAction.tsx b/src/prerequisite_components/InputLabelAndAction/InputLabelAndAction.tsx index 5aec782..eb90d44 100644 --- a/src/prerequisite_components/InputLabelAndAction/InputLabelAndAction.tsx +++ b/src/prerequisite_components/InputLabelAndAction/InputLabelAndAction.tsx @@ -214,7 +214,9 @@ const renderInputLabelAndAction = (props: InputLabelAndActionProps) => { > { limitedActionProps && limitedActionProps.map((actionProp, index) => { return ( - + // eslint-why index is not the sole key definition, it is prefixed by other identifiers + // eslint-disable-next-line react/no-array-index-key + { onClick={actionProp.handleClick} underline="none" sx={{ display: 'inline' }} - // eslint-why index is not the sole key definition, it is prefixed by other identifiers - // eslint-disable-next-line react/no-array-index-key - key={`${actionProp.label}-${index}`} > {actionProp.label} From c4bd0c49e83d8a576df0a610f2ea1dbda5ffe442 Mon Sep 17 00:00:00 2001 From: PiyushKashyapHCL Date: Wed, 30 Oct 2024 19:19:08 +0530 Subject: [PATCH 5/6] Fixed width of Tile action menu and corrected the focus of nested-level accordion --- CHANGELOG.md | 1 + src/Accordion/Accordion.tsx | 1 - src/composite_components/Tile/TileActionMenu.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed5f88..8f35730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Changed - Added keyboard accessibility to the header in `DataGrid` component - Added focus to the input label in `TextField` and `SelectMultiple` components +- Fixed the width of the `Tile` action menu and corrected the focus of nested-level `Accordion` ### Breaking changes diff --git a/src/Accordion/Accordion.tsx b/src/Accordion/Accordion.tsx index 13de560..31df565 100644 --- a/src/Accordion/Accordion.tsx +++ b/src/Accordion/Accordion.tsx @@ -41,7 +41,6 @@ const StyledAccordion = styled(MuiAccordion)((props) => { ...(hasNested ? { padding: '8px 0px 8px 8px' } : { padding: '8px 8px 8px 8px' }), }, '&.MuiAccordion-root': { - overflow: 'hidden', '&:focus': { boxShadow: `0 0 0 2px ${theme.palette.primary.main}`, zIndex: 1, diff --git a/src/composite_components/Tile/TileActionMenu.tsx b/src/composite_components/Tile/TileActionMenu.tsx index 4e99fce..cf89d1f 100644 --- a/src/composite_components/Tile/TileActionMenu.tsx +++ b/src/composite_components/Tile/TileActionMenu.tsx @@ -96,7 +96,7 @@ const TileActionMenu: React.FC = (props: ITileActionMenuPr Date: Mon, 4 Nov 2024 15:21:48 +0530 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f35730..ca250eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ ### Changed - Added keyboard accessibility to the header in `DataGrid` component - Added focus to the input label in `TextField` and `SelectMultiple` components -- Fixed the width of the `Tile` action menu and corrected the focus of nested-level `Accordion` +- Fixed the width of the `Tile` action menu and corrected the focus of nested-level `Accordion` component ### Breaking changes