Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve a11y of autofill assessment table #1019

Merged
merged 55 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
05d57ed
Update Project Enrollment tables
martha Dec 4, 2024
3ca2844
fix a11y
martha Dec 4, 2024
d4f8372
More accessibility fixes
martha Dec 4, 2024
3fac8a7
Simplify and resolve todos
martha Dec 5, 2024
9aad6be
Add storybook story
martha Dec 5, 2024
32c4da4
Remove errant comment
martha Dec 5, 2024
6f0c3ad
Add comments
martha Dec 5, 2024
8368350
Update api of TableRowActions
martha Dec 11, 2024
d744d24
Fix issue with fulColSpan
martha Dec 11, 2024
8b51bd4
Merge branch 'release-144' into martha/6825-hh-member-row
martha Dec 11, 2024
89b582e
Implement Table Actions pattern and default columns
martha Dec 16, 2024
50b472b
Add random comment
martha Dec 16, 2024
bb38721
Merge branch 'release-145' into martha/6761-tables
martha Dec 18, 2024
3a3cf64
Merge branch 'release-145' into martha/6825-hh-member-row
martha Dec 18, 2024
e47d030
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Dec 18, 2024
7a4dd51
Add storybook for table actions and fix cde story
martha Dec 18, 2024
4c6d640
Merge branch 'release-146' into martha/6825-hh-member-row
gigxz Dec 20, 2024
7211ab2
Merge branch 'release-146' into martha/6825-hh-member-row
martha Dec 30, 2024
e26a57e
Right-align table row actions
martha Dec 30, 2024
ae6b49a
Remove comment
martha Dec 30, 2024
3586e74
Replace overrideTableBody with more understandable API
martha Dec 31, 2024
401f777
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Dec 31, 2024
5c4d33a
Implement PR suggestion of moving table row to column def
martha Dec 31, 2024
2d2d133
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Dec 31, 2024
a3b888a
Implement PR suggestion of moving table row to column def
martha Dec 31, 2024
197e12b
Cleanup and add comments
martha Dec 31, 2024
8b6a383
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Dec 31, 2024
2feec78
add todo
martha Dec 31, 2024
f96f87d
Port over relevant changes from other PR
martha Dec 31, 2024
359c9b8
Refactor to use renderCellContents
martha Dec 31, 2024
2da7754
Revert out-of-scope change
martha Dec 31, 2024
39eab24
Add todo
martha Dec 31, 2024
e919970
Remove circular dependency
martha Dec 31, 2024
5026d48
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Dec 31, 2024
0c67ce0
Clean up
martha Jan 2, 2025
39ce9ce
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Jan 2, 2025
8613a8d
Centralize action column base attrs
martha Jan 2, 2025
f91ea56
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Jan 2, 2025
0380e2b
Merge branch 'release-147' into martha/6825-hh-member-row
martha Jan 2, 2025
0605c2a
Finish refactor to use column def instead of getTableAction
martha Jan 2, 2025
d5bd5aa
Fix bulk services loading
martha Jan 2, 2025
e316ed0
Provide a visually hidden header when header isnt provided
martha Jan 2, 2025
7686543
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Jan 2, 2025
004ea99
Keep existing behavior of individual/household assessment viewing
martha Jan 2, 2025
9ffaa63
PR feedback
martha Jan 3, 2025
cee0dbf
Fix typescript problems
martha Jan 3, 2025
5bc2ea6
Merge branch 'martha/6825-hh-member-row' into martha/6761-tables
martha Jan 3, 2025
bdde162
Fix typescript
martha Jan 3, 2025
7339f04
Add accessible text for RelativeDateDisplay
martha Jan 3, 2025
eee782f
implement one possible approach for client ID typescript
martha Jan 6, 2025
d2c8fc4
Improve a11y of autofill assessment table
martha Jan 6, 2025
732dc47
Improve and clean up
martha Jan 6, 2025
edaf95e
PR feedback
martha Jan 6, 2025
42f9eef
Merge branch 'deploy/6761-table-actions' into martha/a11y-139-autofil…
martha Jan 14, 2025
848691a
Revert unneeded
martha Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions src/components/elements/table/GenericTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface Props<T> {
actionRow?: ReactNode;
tableProps?: TableProps;
vertical?: boolean;
verticalHiddenHeader?: string; // For vertically oriented tables, this is the hidden header of the first column
noHead?: boolean;
renderVerticalHeaderCell?: RenderFunction<T>;
rowSx?: (row: T) => SxProps<Theme>;
Expand All @@ -80,24 +81,16 @@ const clickableRowStyles = {
cursor: 'pointer',
};

const HeaderCell = ({
children,
sx,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really part of this diff, but maybe we can get rid of headerCellSx as we are standardizing tables - started thread https://www.figma.com/design/bsw8CX4UOq6SIdXYorZDWV?node-id=2424-868&m=dev#1081881485

padding,
}: {
children: ReactNode;
padding?: TableCellProps['padding'];
sx?: SxProps<Theme>;
}) => (
const HeaderCell = ({ children, sx, ...rest }: TableCellProps) => (
<TableCell
padding={padding}
sx={{
borderBottomColor: 'borders.dark',
borderBottomWidth: 2,
borderBottomStyle: 'solid',
pb: 1,
...sx,
}}
{...rest}
>
{children}
</TableCell>
Expand All @@ -115,6 +108,17 @@ export const renderCellContents = <T extends { id: string }>(
return null;
};

export const renderHeaderCellContents = <T extends { id: string }>(
def: ColumnDef<T>
) => {
return def.header ? (
<strong>{def.header}</strong>
) : (
// If header isn't provided, add a visually hidden header with the column key for accessibility
<Box sx={visuallyHidden}>{def.key}</Box>
);
};

const GenericTable = <T extends { id: string }>({
rows,
handleRowClick,
Expand All @@ -123,6 +127,7 @@ const GenericTable = <T extends { id: string }>({
paginated = false,
loading = false,
vertical = false,
verticalHiddenHeader,
renderVerticalHeaderCell,
tablePaginationProps,
tableContainerProps,
Expand Down Expand Up @@ -203,7 +208,12 @@ const GenericTable = <T extends { id: string }>({
<TableHead sx={{ '.MuiTableCell-head': { verticalAlign: 'bottom' } }}>
{renderVerticalHeaderCell && (
<TableRow>
<TableCell key='empty' sx={{ backgroundColor: 'background.paper' }} />
<TableCell
key='empty'
sx={{ ...verticalCellSx(0), backgroundColor: 'background.paper' }}
>
<Box sx={visuallyHidden}>{verticalHiddenHeader}</Box>
</TableCell>
{rows.map((row, idx) => (
<TableCell key={row.id} sx={verticalCellSx(idx)}>
{renderVerticalHeaderCell(row)}
Expand Down Expand Up @@ -243,12 +253,7 @@ const GenericTable = <T extends { id: string }>({
width: def.width,
}}
>
{def.header ? (
<strong>{def.header}</strong>
) : (
// If header isn't provided, add a visually hidden header with the column key for accessibility
<Box sx={visuallyHidden}>{def.key}</Box>
)}
{renderHeaderCellContents(def)}
</HeaderCell>
))}
</TableRow>
Expand Down Expand Up @@ -308,9 +313,9 @@ const GenericTable = <T extends { id: string }>({
<HeaderCell
sx={{ ...verticalCellSx(1), width: '350px' }}
key={key(def)}
role='rowheader'
>
{' '}
<strong>{def.header}</strong>
{renderHeaderCellContents(def)}
</HeaderCell>
{rows.map((row, idx) => (
<TableCell key={row.id} sx={{ ...verticalCellSx(idx) }}>
Expand Down
50 changes: 33 additions & 17 deletions src/modules/assessments/components/RecordPickerDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Stack } from '@mui/material';
import { Box } from '@mui/material';
import Button from '@mui/material/Button';
import { DialogProps } from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import { visuallyHidden } from '@mui/utils';
import { startCase } from 'lodash-es';
import { ReactNode, useMemo } from 'react';

Expand All @@ -16,7 +17,10 @@ import {
getFieldOnAssessment,
getPopulatableChildren,
} from '@/modules/form/util/formUtil';
import { assessmentColumns } from '@/modules/form/util/recordPickerUtil';
import {
ASSESSMENT_COLUMNS,
assessmentColumns,
} from '@/modules/form/util/recordPickerUtil';
import HmisField from '@/modules/hmis/components/HmisField';
import { AssessmentRole, FormItem, FormRole } from '@/types/gqlTypes';

Expand All @@ -40,10 +44,28 @@ const RecordPickerDialog = ({
clientId,
...other
}: Props) => {
const actionColumnDef: ColumnDef<AssessmentForPopulation> = useMemo(() => {
return {
key: 'Action',
render: (record: AssessmentForPopulation) => (
<Button
onClick={() => onSelected(record)}
variant='outlined'
size='small'
sx={{ backgroundColor: 'white' }}
fullWidth
aria-label={`Select record from ${record.assessmentDate}`}
>
Select
</Button>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the ticket only specified to address accessibility issues, but not adjust the overall UI of the table. This seems relatively minor, but it does lead to the user needing to scroll down within the modal to find the select buttons. Is it necessary to have the button in a separate cell for accessibility reasons? (If so maybe it can remain at the top in another row?). I think unless we have a strong reason to update it, we should probably leave it the same to reduce the impact on users.

Screenshot 2025-01-06 at 4 11 40 PM Screenshot 2025-01-06 at 4 11 46 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! Yes, I think to fix the accessibility issue, it does need to be moved out of the column header. Otherwise, the screenreader will read out the select button every time the user navigates from column to column. But, good idea to move it back to the top in order to reduce user impact.

),
};
}, [onSelected]);

const columns: ColumnDef<AssessmentForPopulation>[] = useMemo(() => {
// If no item was passed, that means we're pre-filling the entire assessment.
// Only metadata columns are shown in that case.
if (!item) return assessmentColumns;
if (!item) return [actionColumnDef, ...assessmentColumns];

// Select additional fields to show in table based on child items in the group
const dataColumns = getPopulatableChildren(item)
Expand All @@ -69,8 +91,8 @@ const RecordPickerDialog = ({
);
},
}));
return [...assessmentColumns, ...dataColumns];
}, [item]);
return [actionColumnDef, ...assessmentColumns, ...dataColumns];
}, [actionColumnDef, item]);

const hudRoles = [
AssessmentRole.Intake,
Expand Down Expand Up @@ -123,7 +145,11 @@ const RecordPickerDialog = ({
}}
renderVerticalHeaderCell={(record) => {
return (
<Stack spacing={2} sx={{ py: 1 }}>
<>
<Box sx={visuallyHidden}>
{/* Additional visually hidden info about this assessment to help with accessibility when navigating the table */}
{ASSESSMENT_COLUMNS.CollectionStage.render(record)}
</Box>
<RelativeDate
dateString={record.assessmentDate}
dateUpdated={record.dateUpdated || undefined}
Expand All @@ -133,17 +159,7 @@ const RecordPickerDialog = ({
withTooltip
prefix='Assessment Date: '
/>
<Button
onClick={() => onSelected(record)}
variant='outlined'
size='small'
sx={{ backgroundColor: 'white' }}
fullWidth
aria-label={`Select record from ${record.assessmentDate}`}
>
Select
</Button>
</Stack>
</>
);
}}
/>
Expand Down
12 changes: 11 additions & 1 deletion src/modules/dataFetching/components/GenericTableWithData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ export interface Props<
SortOptionsType = Record<string, string>,
> extends Omit<
GenericTableProps<RowDataType>,
'rows' | 'tablePaginationProps' | 'loading' | 'paginated' | 'noData'
| 'rows'
| 'tablePaginationProps'
| 'loading'
| 'paginated'
| 'noData'
| 'verticalHiddenHeader'
> {
getColumnDefs?: (
rows: RowDataType[],
Expand Down Expand Up @@ -130,6 +135,7 @@ const GenericTableWithData = <
onCompleted,
paginationItemName,
filterRows,
vertical,
...props
}: Props<
Query,
Expand Down Expand Up @@ -333,6 +339,10 @@ const GenericTableWithData = <
}
columns={showColumnDefs}
noData={loading ? 'Loading...' : noDataValue}
vertical={vertical}
verticalHiddenHeader={
vertical ? `${recordType} attributes` : undefined
}
filterToolbar={
showTopToolbar && (
<>
Expand Down
11 changes: 8 additions & 3 deletions src/modules/form/util/recordPickerUtil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const dataCollectionVerb = {
const COLLECTION_DATE = 'Date Collected';
const COLLECTION_STAGE = 'Collection Point';

export const assessmentColumns = [
{
export const ASSESSMENT_COLUMNS = {
CollectionDate: {
header: COLLECTION_DATE,
render: (record: AssessmentForPopulation) =>
[parseAndFormatDate(record.assessmentDate), record.user?.name]
.filter((s) => !!s)
.join(' by '),
},
{
CollectionStage: {
header: COLLECTION_STAGE,
render: (record: AssessmentForPopulation) =>
[
Expand All @@ -34,4 +34,9 @@ export const assessmentColumns = [
.filter((s) => !!s)
.join(' '),
},
};

export const assessmentColumns = [
ASSESSMENT_COLUMNS.CollectionDate,
ASSESSMENT_COLUMNS.CollectionStage,
];