️(frontend) replace ARIA grid pattern with list in docs grid

Use list/listitem roles, mark column headers as aria-hidden
This commit is contained in:
Cyril
2026-03-25 18:03:33 +01:00
parent cbe6a67704
commit 0f49230231
2 changed files with 50 additions and 44 deletions
@@ -140,36 +140,30 @@ export const DocsGrid = ({
$overflow="auto"
$padding={{ vertical: 'sm', horizontal: isDesktop ? 'md' : 'xs' }}
>
<Box role="grid" aria-label={t('Documents grid')}>
<Box role="rowgroup">
<Box
$direction="row"
$padding={{ horizontal: 'xs' }}
$gap="10px"
data-testid="docs-grid-header"
role="row"
>
<Box $flex={flexLeft} $padding="3xs" role="columnheader">
<Text $size="xs" $variation="secondary" $weight="500">
{t('Name')}
<Box aria-label={t('Documents grid')}>
<Box
$direction="row"
$padding={{ horizontal: 'xs' }}
$gap="10px"
data-testid="docs-grid-header"
aria-hidden="true"
>
<Box $flex={flexLeft} $padding="3xs">
<Text $size="xs" $variation="secondary" $weight="500">
{t('Name')}
</Text>
</Box>
{isDesktop && (
<Box $flex={flexRight} $padding={{ vertical: '3xs' }}>
<Text $size="xs" $weight="500" $variation="secondary">
{DocDefaultFilter.TRASHBIN === target
? t('Days remaining')
: t('Updated at')}
</Text>
</Box>
{isDesktop && (
<Box
$flex={flexRight}
$padding={{ vertical: '3xs' }}
role="columnheader"
>
<Text $size="xs" $weight="500" $variation="secondary">
{DocDefaultFilter.TRASHBIN === target
? t('Days remaining')
: t('Updated at')}
</Text>
</Box>
)}
</Box>
)}
</Box>
<Box role="rowgroup">
<Box role="list">
<DocGridContentList docs={docs} />
</Box>
</Box>
@@ -32,6 +32,7 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
const { isDesktop } = useResponsiveStore();
const { flexLeft, flexRight } = useResponsiveDocGrid();
const { spacingsTokens } = useCunninghamTheme();
const dateToDisplay = useDateToDisplay(doc, isInTrashbin);
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -46,7 +47,7 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
$direction="row"
$width="100%"
$align="center"
role="row"
role="listitem"
$gap="20px"
$padding={{ vertical: '4xs', horizontal: isDesktop ? 'base' : 'xs' }}
$css={css`
@@ -65,7 +66,6 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
>
<Box
$flex={flexLeft}
role="gridcell"
$css={css`
align-items: center;
min-width: 0;
@@ -90,9 +90,15 @@ export const DocsGridItem = ({ doc, dragMode = false }: DocsGridItemProps) => {
$align="center"
$justify={isDesktop ? 'space-between' : 'flex-end'}
$gap="32px"
role="gridcell"
>
<StyledLink href={`/docs/${doc.id}`} tabIndex={-1}>
<StyledLink
href={`/docs/${doc.id}`}
tabIndex={-1}
aria-label={t('{{title}}, updated {{date}}', {
title: doc.title || untitledDocument,
date: dateToDisplay,
})}
>
<DocsGridItemDate
doc={doc}
isDesktop={isDesktop}
@@ -196,23 +202,11 @@ const IconPublic = ({ isPublic }: { isPublic: boolean }) => {
);
};
export const DocsGridItemDate = ({
doc,
isDesktop,
isInTrashbin,
}: {
doc: Doc;
isDesktop: boolean;
isInTrashbin: boolean;
}) => {
const useDateToDisplay = (doc: Doc, isInTrashbin: boolean) => {
const { data: config } = useConfig();
const { t } = useTranslation();
const { relativeDate, calculateDaysLeft } = useDate();
if (!isDesktop) {
return null;
}
let dateToDisplay = relativeDate(doc.updated_at);
if (isInTrashbin && config?.TRASHBIN_CUTOFF_DAYS && doc.deleted_at) {
@@ -224,6 +218,24 @@ export const DocsGridItemDate = ({
dateToDisplay = `${daysLeft} ${t('days', { count: daysLeft })}`;
}
return dateToDisplay;
};
export const DocsGridItemDate = ({
doc,
isDesktop,
isInTrashbin,
}: {
doc: Doc;
isDesktop: boolean;
isInTrashbin: boolean;
}) => {
const dateToDisplay = useDateToDisplay(doc, isInTrashbin);
if (!isDesktop) {
return null;
}
return (
<Text
$size="xs"