Skip to content

Commit

Permalink
fix: [Table] Pagination input label's 'for' property needs to align w…
Browse files Browse the repository at this point in the history
…ith the input id (#356)

Accessibility improvement

## Changes
- [Table] Propagate Table id to Pagination component
- [Pagination] Utilize `tableId` to uniquely identify and label
Pagination's input element

## How to test this PR

1. Load paginated table in an application (couldn't get ANDI to
recognize the error in Storybook)
2. Run [ANDI](https://www.ssa.gov/accessibility/andi/help/install.html)
accessibility tool
3. Verify that it doesn't identify the following error
- `Element nested in <label> but label[for=m-pagination_current-page]
does not match element [id=m-pagination_current-page-default`

## Screenshots
|ANDI Before|ANDI After|
|---|---|
|![Screenshot 2024-05-24 at 3 32
30 PM](https://github.com/cfpb/design-system-react/assets/2592907/cab51fd4-d9ae-467f-be96-78fcb006d434)|![Screenshot
2024-05-24 at 3 29
22 PM](https://github.com/cfpb/design-system-react/assets/2592907/ef31e63c-fa18-472f-ade8-8337965bcf4b)|
  • Loading branch information
meissadia authored May 30, 2024
1 parent 9b8daba commit 026da89
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
20 changes: 13 additions & 7 deletions src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import classNames from 'classnames';
import type { EventHandler, ReactElement, SyntheticEvent } from 'react';
import { useEffect, useState } from 'react';
import { useEffect, useId, useState } from 'react';
import { noOp } from '../../utils/noOp';
import { Icon } from '../Icon/Icon';
import { Label } from '../Label/Label';
import './pagination.less';
import { MIN_PAGE } from './paginationConstants';

export interface PaginationProperties {
/** Identifier of the table this element controls */
tableId?: string;
/** Currently displayed page number */
page: number;
/** Total number of available pages */
Expand Down Expand Up @@ -79,12 +81,14 @@ const PaginationNavButton = ({
};

interface PaginationInputProperties {
tableId: string;
page: number;
pageCount: number;
onChange: (value: number) => void;
}

const PaginationInput = ({
tableId,
page,
pageCount,
onChange
Expand All @@ -93,17 +97,15 @@ const PaginationInput = ({
onChange(Number.parseInt(event.currentTarget.value, 10));
};

const inputId = `${tableId}-pagination_current-page`;

return (
<Label
className='m-pagination_label'
htmlFor='m-pagination_current-page'
inline
>
<Label className='m-pagination_label' htmlFor={inputId} inline>
Page
<span className='u-visually-hidden'>number {page} out</span>
<input
className='m-pagination_current-page'
id='m-pagination_current-page-default'
id={inputId}
name='page'
type='number'
min='1'
Expand All @@ -124,6 +126,7 @@ const PaginationInput = ({
* Source: https://cfpb.github.io/design-system/components/pagination
*/
export const Pagination = ({
tableId,
page,
pageCount,
onClickPrevious = noOp,
Expand All @@ -143,6 +146,8 @@ export const Pagination = ({
onClickGo(targetPage);
};

const paginationId = useId();

const onInputChange = setPageNumber;

return (
Expand All @@ -168,6 +173,7 @@ export const Pagination = ({
onSubmit={onSubmit}
>
<PaginationInput
tableId={tableId ?? paginationId}
page={pageNumber}
pageCount={pageCount}
onChange={onInputChange}
Expand Down
10 changes: 8 additions & 2 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import classNames from 'classnames';
import type { ForwardedRef, HTMLProps } from 'react';
import { forwardRef, type ReactNode } from 'react';
import { forwardRef, useId, type ReactNode } from 'react';
import type { JSXElement } from '~/src/types/jsxElement';
import { type WidthPercent } from '../../types/WidthPercent';
import { Pagination } from '../Pagination/Pagination';
Expand Down Expand Up @@ -28,6 +28,8 @@ export interface TableColumnConfiguration {
export type TableColumn = TableColumnConfiguration | string;

export interface TableProperties {
// Unique identifier
id?: string;
// Table description, displayed atop the table
caption?: ReactNode;
// Array of column headers or column configurations
Expand Down Expand Up @@ -66,6 +68,7 @@ export const Table = forwardRef<
>(
(
{
id,
caption,
columns,
rows,
Expand All @@ -90,6 +93,8 @@ export const Table = forwardRef<
perPage
});

const tableId = useId();

const tableClassnames = [];

if (isResponsive || isDirectory)
Expand All @@ -105,13 +110,14 @@ export const Table = forwardRef<
data-testid='table-testid'
className={classNames(tableClassnames)}
ref={tableRef}
id={id ?? tableId}
{...others}
>
<Caption>{caption}</Caption>
{buildColumnHeaders(columns)}
{buildRows(visibleRows, columns)}
</table>
{isPaginated ? <Pagination {...paginationProperties} /> : null}
{isPaginated ? <Pagination {...paginationProperties} tableId={id ?? tableId}/> : null}
</>
);

Expand Down

0 comments on commit 026da89

Please sign in to comment.