Skip to content

Commit

Permalink
fix: DataGrid reformatted to table and aria-sort added
Browse files Browse the repository at this point in the history
Refactors the DataTable + DataList components to properly be semantic HTML tables and adds `aria-sort` to the appropriate controls
  • Loading branch information
dreamwasp authored Jan 29, 2025
1 parent 132126b commit 9903099
Show file tree
Hide file tree
Showing 19 changed files with 295 additions and 182 deletions.
2 changes: 1 addition & 1 deletion packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ exports[`Gamut Exported Keys 1`] = `
"LayoutGrid",
"List",
"ListCol",
"ListHeader",
"ListRow",
"Logo",
"LogoDefault",
Expand Down Expand Up @@ -99,6 +98,7 @@ exports[`Gamut Exported Keys 1`] = `
"submitSuccessStatus",
"Tab",
"TabButton",
"TableHeader",
"TabList",
"TabNav",
"TabNavLink",
Expand Down
1 change: 0 additions & 1 deletion packages/gamut/src/DataList/Controls/FilterControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export const FilterControl: React.FC<FilterProps> = ({
{menuOpen && (
<PopoverContainer
isOpen
inline
targetRef={target as any}
offset={0}
alignment={justify === 'left' ? 'bottom-right' : 'bottom-left'}
Expand Down
7 changes: 7 additions & 0 deletions packages/gamut/src/DataList/Controls/SortControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ export const SortControl: React.FC<SortControlProps> = ({

return (
<SortAnchor
aria-sort={
direction === 'none'
? 'none'
: direction === 'asc'
? 'ascending'
: 'descending'
}
variant="interface"
onClick={() =>
onSort?.({
Expand Down
5 changes: 3 additions & 2 deletions packages/gamut/src/DataList/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { List } from '../List';
import { EmptyRows } from './EmptyRows';
import { ListControlContext, useListControls } from './hooks/useListControls';
import { ListStateContext } from './hooks/useListState';
import { HeaderRow } from './Rows/HeaderRow';
import { DataRow, MarshaledColProps } from './Rows/Row';
import { HeaderRow } from './Tables/Rows/TableHeaderRow';
import { DataRow, MarshaledColProps } from './Tables/Rows/TableRow';
import { ColumnConfig, DataListControls, IdentifiableKeys } from './types';

export interface DataGridProps<
Expand Down Expand Up @@ -97,6 +97,7 @@ export function DataGrid<
<ListControlContext.Provider value={listControls}>
<List
{...rest}
as="table"
emptyMessage={emptyMessage ?? <EmptyRows />}
header={
header ? (
Expand Down
43 changes: 21 additions & 22 deletions packages/gamut/src/DataList/EmptyRows.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { DotLoose } from '@codecademy/gamut-patterns';

import { FlexBox } from '../Box';
import { FillButton } from '../Button';
import { Text } from '../Typography';
Expand All @@ -9,26 +7,27 @@ export const EmptyRows = () => {
const { onResetQuery } = useControlContext();

return (
<>
<FlexBox
bg="background-current"
center
column
gap={16}
left="calc(50% - 160px)"
p={32}
position="sticky"
top="calc(50% - 92px)"
width="320px"
zIndex={1}
>
<Text variant="title-sm">No Results Found</Text>
<Text variant="p-base">Remove filters to view</Text>
<FillButton onClick={onResetQuery}>Reset Filters</FillButton>
</FlexBox>
<FlexBox height={409} center width={1}>
<DotLoose position="absolute" inset={0} top={-2} />
<FlexBox
as="tbody"
bg="background-current"
left="calc(50% - 160px)"
p={32}
position="sticky"
top="calc(50% - 66px)"
width="320px"
zIndex={1}
>
<FlexBox as="tr" center column gap={16} width="100%">
<th>
<Text variant="title-sm">No Results Found</Text>
</th>
<th>
<Text variant="p-base">Remove filters to view</Text>
</th>
<th>
<FillButton onClick={onResetQuery}>Reset Filters</FillButton>
</th>
</FlexBox>
</>
</FlexBox>
);
};
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { memo, ReactElement } from 'react';

import { FlexBox } from '../..';
import { ListCol, ListHeader } from '../../List';
import { FlexBox } from '../../..';
import { ListCol, TableHeader } from '../../../List';
import {
ExpandControl,
FilterControl,
SelectControl,
SortControl,
} from '../Controls';
import { useControlContext } from '../hooks/useListControls';
import { ColumnConfig, Query } from '../types';
} from '../../Controls';
import { useControlContext } from '../../hooks/useListControls';
import { ColumnConfig, Query } from '../../types';

interface HeaderComponent {
<Row>(props: {
Expand All @@ -21,23 +21,17 @@ interface HeaderComponent {
}): ReactElement<any, any>;
}

export const Header: HeaderComponent = ({
export const TableHeaderRow: HeaderComponent = ({
columns,
selected = false,
empty = false,
hideSelectAll,
}) => {
const {
expandable,
selectable,
onSelect,
onFilter,
onSort,
prefixId,
} = useControlContext();
const { expandable, selectable, onSelect, onFilter, onSort, prefixId } =
useControlContext();

return (
<ListHeader>
<TableHeader>
<>
{selectable && (
<ListCol size="content">
Expand Down Expand Up @@ -86,8 +80,8 @@ export const Header: HeaderComponent = ({
</ListCol>
)}
</>
</ListHeader>
</TableHeader>
);
};

export const HeaderRow = memo(Header) as HeaderComponent;
export const HeaderRow = memo(TableHeaderRow) as HeaderComponent;
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { memo, ReactElement, ReactNode, useCallback } from 'react';
import {
isValidElement,
memo,
ReactElement,
useCallback,
useMemo,
} from 'react';

import { Text } from '../..';
import { ListCol, ListRow } from '../../List';
import { ColProps } from '../../List/elements';
import { Shimmer } from '../../Loading/Shimmer';
import { ExpandControl, SelectControl } from '../Controls';
import { useControlContext } from '../hooks/useListControls';
import { ColumnConfig, IdentifiableKeys } from '../types';
import { Text } from '../../..';
import { ListCol, ListRow } from '../../../List';
import { ColProps } from '../../../List/elements';
import { Shimmer } from '../../../Loading/Shimmer';
import { ExpandControl, SelectControl } from '../../Controls';
import { useControlContext } from '../../hooks/useListControls';
import { ColumnConfig, IdentifiableKeys } from '../../types';

export type MarshaledColProps = Partial<Pick<ColProps, 'showOverflow'>>;

Expand All @@ -23,7 +29,7 @@ interface DataRow {
): ReactElement<any, any>;
}

export const Row: DataRow = ({
export const TableRow: DataRow = ({
id,
columns,
row,
Expand All @@ -50,8 +56,24 @@ export const Row: DataRow = ({
});
}, [onExpand, expandedContent, id, row]);

const numberOfColumns = useMemo(() => {
return columns.length;
}, [columns]);

const listRowProps = expandable
? {
expanded,
renderExpanded: renderExpandedContent,
}
: {};

return (
<ListRow expanded={expanded} renderExpanded={renderExpandedContent}>
<ListRow
as="tr"
numOfColumns={numberOfColumns}
selectable={selectable}
{...listRowProps}
>
{selectable && (
<ListCol
{...listColProps}
Expand All @@ -70,18 +92,18 @@ export const Row: DataRow = ({
</ListCol>
)}
{columns.map(({ key, render, size, justify, fill, type }) => {
const newKey = prefixId(`${id}-col-${String(key)}`);
const colProps = {
...listColProps,
size,
justify,
fill,
type,
key: prefixId(`${id}-col-${String(key)}`),
};

if (loading) {
return (
<ListCol {...colProps}>
<ListCol {...colProps} key={newKey}>
<Shimmer
minHeight={24}
height="calc(100% - 1rem)"
Expand All @@ -92,22 +114,24 @@ export const Row: DataRow = ({
}

return (
<ListCol {...colProps}>
<>
{render ? (
render(row)
) : typeof row[key] === 'string' ? (
<Text
truncate="ellipsis"
truncateLines={1}
textAlign={justify ?? 'left'}
>
{row[key] as ReactNode}
</Text>
) : (
row[key]
)}
</>
<ListCol {...colProps} key={newKey}>
{render ? (
render(row)
) : typeof row[key] === 'string' || typeof row[key] === 'number' ? (
<Text
truncate="ellipsis"
truncateLines={1}
textAlign={justify ?? 'left'}
>
{row[key] as string}
</Text>
) : isValidElement(row[key]) ? (
(row[key] as ReactElement)
) : !row[key] ? (
''
) : (
'Invalid data type'
)}
</ListCol>
);
})}
Expand All @@ -125,4 +149,4 @@ export const Row: DataRow = ({
);
};

export const DataRow = memo(Row) as DataRow;
export const DataRow = memo(TableRow) as DataRow;
Loading

0 comments on commit 9903099

Please sign in to comment.