Skip to content

Commit a5ec2c2

Browse files
author
Kubit
committed
Include arias for content on Drawer component
1 parent bee2b1d commit a5ec2c2

File tree

6 files changed

+112
-33
lines changed

6 files changed

+112
-33
lines changed

src/components/drawer/drawerControlled.tsx

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { STYLES_NAME } from '@/constants';
44
import {
55
useDeviceHeight,
66
useMediaDevice,
7+
useScrollDetectionWithAutoFocus,
78
useScrollEffect,
89
useStylesV2,
910
useZoomEffect,
@@ -29,6 +30,33 @@ const DrawerControlledComponent = React.forwardRef(
2930
{ portalId, ...props }: IDrawerControlled<V>,
3031
ref: React.ForwardedRef<HTMLDivElement> | undefined | null
3132
): JSX.Element => {
33+
const innerRef = React.useRef<HTMLDivElement | null>(null);
34+
35+
const handleInnerRef = React.useCallback(node => {
36+
innerRef.current = node;
37+
const drawerTitle = innerRef.current?.querySelector('[data-drawer-title]') as
38+
| HTMLElement
39+
| null
40+
| undefined;
41+
const drawerContent = innerRef.current?.querySelector('[data-drawer-content]') as
42+
| HTMLElement
43+
| null
44+
| undefined;
45+
const drawerFooter = innerRef.current?.querySelector('[data-drawer-footer]') as
46+
| HTMLElement
47+
| null
48+
| undefined;
49+
50+
handleTitleShadowEffect(drawerTitle);
51+
handleContentScrollEffect(drawerContent);
52+
handleFooterZoomEffect(drawerFooter);
53+
handleContentScrollDetection(drawerContent);
54+
}, []);
55+
56+
React.useImperativeHandle(ref, () => {
57+
return innerRef?.current as HTMLDivElement;
58+
}, []);
59+
3260
useDeviceHeight();
3361

3462
const handleScroll = (e: Event) => {
@@ -43,22 +71,26 @@ const DrawerControlledComponent = React.forwardRef(
4371
const device = useMediaDevice();
4472
const stylesByDevice = styles?.[device];
4573

46-
const { scrollableRef, shadowRef } = useScrollEffect({
47-
shadowStyles: stylesByDevice.titleContainer?.box_shadow,
48-
shadowVisible: SCROLL_DISTANCE,
49-
scrollCallback: handleScroll,
50-
});
74+
const { scrollableRef: handleContentScrollEffect, shadowRef: handleTitleShadowEffect } =
75+
useScrollEffect({
76+
shadowStyles: stylesByDevice.titleContainer?.box_shadow,
77+
shadowVisible: SCROLL_DISTANCE,
78+
scrollCallback: handleScroll,
79+
});
80+
81+
const handleFooterZoomEffect = useZoomEffect(FOOTER_EDIT_STYLES, MAX_ZOOM);
5182

52-
const footerRef = useZoomEffect(FOOTER_EDIT_STYLES, MAX_ZOOM);
83+
const { hasScroll: contentHasScroll, handleScrollDetection: handleContentScrollDetection } =
84+
useScrollDetectionWithAutoFocus({
85+
parentElementRef: innerRef,
86+
});
5387

5488
const drawerStructure = (
5589
<DrawerStandAlone
5690
{...props}
57-
ref={ref}
58-
contentRef={scrollableRef}
91+
ref={handleInnerRef}
92+
contentHasScroll={contentHasScroll}
5993
device={device}
60-
footerRef={footerRef}
61-
shadowRef={shadowRef}
6294
styles={stylesByDevice}
6395
/>
6496
);

src/components/drawer/drawerStandAlone.tsx

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import * as React from 'react';
22

33
import { ElementOrIcon } from '@/components/elementOrIcon';
44
import { Footer } from '@/components/footer/footer';
5-
import { PopoverControlled as Popover } from '@/components/popover';
5+
import { PopoverControlled as Popover, PopoverComponentType } from '@/components/popover';
66
import { Text } from '@/components/text/text';
77
import { TextComponentType } from '@/components/text/types/component';
88
import { useId } from '@/hooks';
9+
import { ROLES } from '@/types';
910

1011
import {
1112
DrawerContentStyled,
@@ -18,14 +19,7 @@ import {
1819
import { IDrawerStandAlone } from './types';
1920

2021
const DrawerStandAloneComponent = (
21-
{
22-
blocked = false,
23-
shadowRef,
24-
footerRef,
25-
contentRef,
26-
titleComponent = TextComponentType.H3,
27-
...props
28-
}: IDrawerStandAlone,
22+
{ blocked = false, titleComponent = TextComponentType.H3, ...props }: IDrawerStandAlone,
2923
ref: React.ForwardedRef<HTMLDivElement> | undefined | null
3024
): JSX.Element => {
3125
const uniqueTitleId = useId('drawer-title');
@@ -34,13 +28,14 @@ const DrawerStandAloneComponent = (
3428

3529
return (
3630
<Popover
37-
aria-label={!props.title?.content ? `${props.popover?.['aria-label']}` : undefined}
3831
aria-labelledby={props.title?.content ? titleIdFinal : undefined}
3932
aria-modal={props.open}
4033
clickOverlayClose={!blocked}
34+
component={PopoverComponentType.DIV}
4135
dataTestId={`${props.dataTestId}Popover`}
4236
hasBackDrop={true}
4337
open={props.open}
38+
role={ROLES.DIALOG}
4439
trapFocusInsideModal={true}
4540
variant={position}
4641
{...props.popover}
@@ -62,8 +57,8 @@ const DrawerStandAloneComponent = (
6257
)}
6358
<DrawerTitleContentFooterContainerStyled blocked={blocked} styles={props.styles}>
6459
<DrawerTitleStyled
65-
ref={shadowRef}
66-
as={Text as unknown as React.ElementType}
60+
data-drawer-title
61+
as={Text}
6762
component={titleComponent as unknown as TextComponentType}
6863
customTypography={props.styles.title}
6964
dataTestId={`${titleIdFinal}Title`}
@@ -72,13 +67,24 @@ const DrawerStandAloneComponent = (
7267
>
7368
{props.title?.content}
7469
</DrawerTitleStyled>
75-
<DrawerContentStyled ref={contentRef} styles={props.styles}>
70+
<DrawerContentStyled
71+
data-drawer-content
72+
aria-label={
73+
props.contentHasScroll ? props.contentScrollArias?.['aria-label'] : undefined
74+
}
75+
aria-labelledby={
76+
props.contentHasScroll ? props.contentScrollArias?.['aria-labelledby'] : undefined
77+
}
78+
role={props.contentHasScroll ? ROLES.REGION : undefined}
79+
styles={props.styles}
80+
tabIndex={props.contentHasScroll ? 0 : undefined}
81+
>
7682
{props.children}
7783
</DrawerContentStyled>
78-
{props.footer?.content && props.styles.footer?.variant && (
84+
{props.footer?.content && (props.styles.footer?.variant || props.footer.variant) && (
7985
<DrawerFooterStyled
80-
ref={footerRef}
81-
as={Footer as unknown as React.ElementType}
86+
data-drawer-footer
87+
as={Footer}
8288
customFooterStyles={props.styles}
8389
variant={props.styles.footer?.variant}
8490
{...props.footer}

src/components/drawer/stories/controlledArgtypes.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ export const argtypes = (variants: IThemeObjectVariants, themeSelected: string):
5757
category: CATEGORY_CONTROL.CONTENT,
5858
},
5959
},
60+
contentScrollArias: {
61+
description: 'Aria label for content when scroll',
62+
type: { name: 'object' },
63+
control: { type: 'object' },
64+
table: {
65+
type: {
66+
summary: 'DrawerContentScrollAriasType',
67+
detail:
68+
'DrawerContentScrollAriasType: { ["aria-label"]?: string; ["aria-labelledby"]?: string; }',
69+
},
70+
category: CATEGORY_CONTROL.ACCESIBILITY,
71+
},
72+
},
6073
footer: {
6174
description: 'Footer of the Drawer',
6275
type: { name: 'object' },

src/components/drawer/stories/drawerControlled.stories.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ const StoryWithHooks = args => {
5656
>
5757
Open Drawer
5858
</Button>
59-
<Story {...args} level={level} open={open} onClickBackFirstLevel={onClickBackFirstLevel} />
59+
<Story
60+
{...args}
61+
closeIcon={{ ...args.closeIcon, onClick: () => setOpen(false) }}
62+
level={level}
63+
open={open}
64+
popover={{ ...args.popover, onCloseInternally: () => setOpen(false) }}
65+
onClickBackFirstLevel={onClickBackFirstLevel}
66+
/>
6067
</>
6168
);
6269
};
@@ -80,6 +87,9 @@ export const DrawerControlled: Story = {
8087
<ReplaceContent />
8188
</>
8289
),
90+
contentScrollArias: {
91+
'aria-label': 'Drawer content scroll',
92+
},
8393
blocked: false,
8494
popover: {
8595
blockBack: true,
@@ -106,6 +116,9 @@ export const DrawerControlledWithCtv: Story = {
106116
level: DrawerLevelPositionTypes.FIRST_LEVEL,
107117
open: false,
108118
children: <ReplaceContent />,
119+
contentScrollArias: {
120+
'aria-label': 'Drawer content scroll',
121+
},
109122
blocked: false,
110123
popover: {
111124
blockBack: true,

src/components/drawer/stories/uncontrolledArgTypes.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,19 @@ export const argtypes = (variants: IThemeObjectVariants, themeSelected: string):
6666
category: CATEGORY_CONTROL.CONTENT,
6767
},
6868
},
69+
contentScrollArias: {
70+
description: 'Aria label for content when scroll',
71+
type: { name: 'object' },
72+
control: { type: 'object' },
73+
table: {
74+
type: {
75+
summary: 'DrawerContentScrollAriasType',
76+
detail:
77+
'DrawerContentScrollAriasType: { ["aria-label"]?: string; ["aria-labelledby"]?: string; }',
78+
},
79+
category: CATEGORY_CONTROL.ACCESIBILITY,
80+
},
81+
},
6982
footer: {
7083
description: 'Footer of the Drawer',
7184
type: { name: 'object' },

src/components/drawer/types/drawer.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ export type DrawerFooterType = Omit<IFooter, 'children' | 'variant'> & {
2121

2222
export type DrawerPopoverType = Omit<IPopoverControlled, 'children' | 'open'>;
2323

24+
export type DrawerContentScrollAriasType = {
25+
['aria-label']?: string;
26+
['aria-labelledby']?: string;
27+
};
28+
2429
export interface IDrawerStandAlone {
2530
styles: DrawerDeviceStyleType;
2631
children: ReactNode;
32+
contentScrollArias?: DrawerContentScrollAriasType;
33+
contentHasScroll: boolean;
2734
footer?: DrawerFooterType;
2835
closeIcon?: IElementOrIcon;
2936
title?: DrawerTextType;
@@ -37,15 +44,10 @@ export interface IDrawerStandAlone {
3744
device?: DeviceBreakpointsType;
3845
blocked?: boolean;
3946
popover?: DrawerPopoverType;
40-
/* To useScrollableEffect */
41-
shadowRef: (node) => void;
42-
/* To useZoomEffect */
43-
footerRef?: (node) => void;
44-
contentRef?: (node) => void;
4547
onContentScroll?: (e: Event) => void;
4648
}
4749

48-
type OmitProps = 'styles' | 'device' | 'shadowRef' | 'footerRef' | 'contentRef';
50+
type OmitProps = 'styles' | 'device' | 'contentHasScroll';
4951

5052
export interface IDrawerControlled<V = undefined extends string ? unknown : string>
5153
extends Omit<IDrawerStandAlone, OmitProps>,

0 commit comments

Comments
 (0)