Skip to content

Commit dddc45c

Browse files
authored
feat: support aria-labelledby and aria-describedby for dialog in Panel (#425)
* feat: support aria-labelledby and aria-describedby for dialog The DrawerPanel has a dialog role which should support aria-labelledby and aria-describedby attributes. * Allowing all aria-* props * Removing custom method to pick aria props
1 parent 4629910 commit dddc45c

File tree

5 files changed

+47
-7
lines changed

5 files changed

+47
-7
lines changed

src/Drawer.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import Portal from '@rc-component/portal';
33
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
44
import * as React from 'react';
55
import { RefContext } from './context';
6-
import type { DrawerPanelEvents } from './DrawerPanel';
6+
import type {
7+
DrawerPanelAccessibility,
8+
DrawerPanelEvents,
9+
} from './DrawerPanel';
710
import type { DrawerPopupProps } from './DrawerPopup';
811
import DrawerPopup from './DrawerPopup';
912
import { warnCheck } from './util';
@@ -13,7 +16,8 @@ export type Placement = 'left' | 'top' | 'right' | 'bottom';
1316

1417
export interface DrawerProps
1518
extends Omit<DrawerPopupProps, 'prefixCls' | 'inline' | 'scrollLocker'>,
16-
DrawerPanelEvents {
19+
DrawerPanelEvents,
20+
DrawerPanelAccessibility {
1721
prefixCls?: string;
1822
open?: boolean;
1923
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;

src/DrawerPanel.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import classNames from 'classnames';
22
import { useComposeRef } from 'rc-util';
33
import * as React from 'react';
44
import { RefContext } from './context';
5+
import pickAttrs from 'rc-util/lib/pickAttrs';
56

67
export interface DrawerPanelRef {
78
focus: VoidFunction;
@@ -16,7 +17,14 @@ export interface DrawerPanelEvents {
1617
onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;
1718
}
1819

19-
export interface DrawerPanelProps extends DrawerPanelEvents {
20+
export type DrawerPanelAccessibility = Pick<
21+
React.DialogHTMLAttributes<HTMLDivElement>,
22+
keyof React.AriaAttributes
23+
>;
24+
25+
export interface DrawerPanelProps
26+
extends DrawerPanelEvents,
27+
DrawerPanelAccessibility {
2028
prefixCls: string;
2129
className?: string;
2230
id?: string;
@@ -63,9 +71,10 @@ const DrawerPanel = (props: DrawerPanelProps) => {
6371
style={{
6472
...style,
6573
}}
66-
aria-modal="true"
6774
role="dialog"
6875
ref={mergedRef}
76+
{...pickAttrs(props, { aria: true })}
77+
aria-modal="true"
6978
{...eventHandlers}
7079
>
7180
{children}

src/DrawerPopup.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import pickAttrs from 'rc-util/lib/pickAttrs';
66
import * as React from 'react';
77
import type { DrawerContextProps } from './context';
88
import DrawerContext from './context';
9-
import type { DrawerPanelEvents } from './DrawerPanel';
9+
import type {
10+
DrawerPanelAccessibility,
11+
DrawerPanelEvents,
12+
} from './DrawerPanel';
1013
import DrawerPanel from './DrawerPanel';
1114
import { parseWidthHeight } from './util';
1215
import type { DrawerClassNames, DrawerStyles } from './inter';
@@ -25,7 +28,9 @@ export interface PushConfig {
2528
distance?: number | string;
2629
}
2730

28-
export interface DrawerPopupProps extends DrawerPanelEvents {
31+
export interface DrawerPopupProps
32+
extends DrawerPanelEvents,
33+
DrawerPanelAccessibility {
2934
prefixCls: string;
3035
open?: boolean;
3136
inline?: boolean;
@@ -315,6 +320,7 @@ function DrawerPopup(props: DrawerPopupProps, ref: React.Ref<HTMLDivElement>) {
315320
...style,
316321
...styles?.content,
317322
}}
323+
{...pickAttrs(props, { aria: true })}
318324
{...eventHandlers}
319325
>
320326
{children}

src/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ export function warnCheck(props: DrawerProps) {
2424
canUseDom() || !props.open,
2525
`Drawer with 'open' in SSR is not work since no place to createPortal. Please move to 'useEffect' instead.`,
2626
);
27-
}
27+
}

tests/index.spec.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,27 @@ describe('rc-drawer-menu', () => {
396396
unmount();
397397
});
398398

399+
it('passes aria-describedby to the Panel', () => {
400+
const description = 'some meaningful description';
401+
const { unmount, getByRole } = render(<Drawer open aria-describedby={description} />);
402+
expect(getByRole('dialog')).toHaveAttribute('aria-describedby', description);
403+
unmount();
404+
});
405+
406+
it('passes aria-labelledby to the Panel', () => {
407+
const titleId = 'some-id';
408+
const { unmount, getByRole } = render(
409+
<Drawer open aria-labelledby={titleId}>
410+
<h1 id={titleId}>Some Title</h1>
411+
</Drawer>
412+
);
413+
expect(getByRole('dialog')).toHaveAttribute('aria-labelledby', titleId);
414+
expect(getByRole('dialog', {
415+
name: 'Some Title'
416+
})).toBeVisible();
417+
unmount();
418+
});
419+
399420
it('should support classNames', () => {
400421
const { unmount } = render(
401422
<Drawer classNames={{

0 commit comments

Comments
 (0)