Skip to content

Commit 9dda362

Browse files
committed
feat(html): add accessibility attributes to html rendering
1 parent 8927764 commit 9dda362

File tree

785 files changed

+23435
-21672
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

785 files changed

+23435
-21672
lines changed

packages/html/src/action-sheet/action-sheet.spec.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ export type KendoActionSheetProps = {
2222
overlay?: boolean;
2323
template?: React.JSX.Element | React.JSX.Element[];
2424
side?: 'top' | 'right' | 'bottom' | 'left';
25+
/**
26+
* Unique identifier for the ActionSheet. Used for aria-labelledby.
27+
* @aria aria-labelledby references ${id}-title
28+
*/
29+
id?: string;
2530
}
2631

2732
const defaultOptions = {
@@ -44,9 +49,12 @@ export const ActionSheet: KendoComponent<KendoActionSheetProps & React.HTMLAttri
4449
children,
4550
header,
4651
footer,
52+
id,
4753
...other
4854
} = props;
4955

56+
const titleId = id ? `${id}-title` : undefined;
57+
5058
return (
5159
<div className="k-actionsheet-container">
5260
{overlay && <Overlay />}
@@ -60,6 +68,9 @@ export const ActionSheet: KendoComponent<KendoActionSheetProps & React.HTMLAttri
6068
}}>
6169
<div
6270
{...other}
71+
role="dialog"
72+
aria-modal={overlay ? "true" : undefined}
73+
aria-labelledby={titleId}
6374
className={classNames(
6475
props.className,
6576
ACTIONSHEET_CLASSNAME,
@@ -70,7 +81,7 @@ export const ActionSheet: KendoComponent<KendoActionSheetProps & React.HTMLAttri
7081
},
7182
)}>
7283
{template ? template :
73-
<ActionSheetView header={header} footer={footer} adaptive={adaptive} {...props}>
84+
<ActionSheetView header={header} footer={footer} adaptive={adaptive} titleId={titleId} {...props}>
7485
{children}
7586
</ActionSheetView>
7687
}
@@ -87,4 +98,26 @@ ActionSheet.defaultOptions = defaultOptions;
8798
ActionSheet.moduleName = ACTION_SHEET_MODULE_NAME;
8899
ActionSheet.folderName = ACTION_SHEET_FOLDER_NAME;
89100

101+
/**
102+
* Accessibility specification for ActionSheet.
103+
*
104+
* @accessibility
105+
* - Has role="dialog" with aria-modal="true" when overlay is enabled
106+
* - aria-labelledby references the title element
107+
* - Content is arbitrary; components using ActionSheet in adaptive mode
108+
* are responsible for their internal content's ARIA attributes
109+
*
110+
* @wcag 4.1.2 Name, Role, Value - dialog pattern with labeled title
111+
*/
112+
ActionSheet.ariaSpec = {
113+
selector: '.k-actionsheet',
114+
rules: [
115+
{ selector: '.k-actionsheet', attribute: 'role=dialog', usage: 'Announces the dialog role of the component.' },
116+
{ selector: '.k-actionsheet', attribute: 'aria-labelledby (when has title)', usage: 'Associates the title of the action sheet.' },
117+
{ selector: '.k-actionsheet', attribute: 'aria-hidden=true/false', usage: 'Announces the hidden state of the ActionSheet container.' },
118+
{ selector: '.k-actionsheet', attribute: 'aria-modal=true (when modal)', usage: 'Announces that the action sheet is modal.' },
119+
{ selector: '.k-actionsheet .k-actionsheet-title', attribute: 'id', usage: 'Used to associate the title with the action sheet wrapper element.' },
120+
]
121+
};
122+
90123
export default ActionSheet;

packages/html/src/action-sheet/actionsheet-header.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export type KendoActionSheetHeaderProps = {
1414
inputValue?: string;
1515
inputPlaceholder?: string;
1616
adaptive?: boolean;
17+
/**
18+
* ID for the title element, used by aria-labelledby on the ActionSheet.
19+
* @aria Referenced by aria-labelledby on the ActionSheet dialog
20+
*/
21+
titleId?: string;
1722
}
1823

1924
const defaultOptions = {};
@@ -32,6 +37,7 @@ export const ActionSheetHeader = (
3237
inputValue,
3338
inputPlaceholder,
3439
adaptive,
40+
titleId,
3541
children,
3642
...other
3743
} = props;
@@ -50,12 +56,12 @@ export const ActionSheetHeader = (
5056
</div>
5157
)}
5258
{!children &&
53-
<div className="k-actionsheet-title">
59+
<div className="k-actionsheet-title" id={titleId}>
5460
{title && <div className="k-text-center">{title}</div>}
5561
{subtitle && <div className="k-actionsheet-subtitle k-text-center">{subtitle}</div>}
5662
</div>
5763
}
58-
{children && <div className="k-actionsheet-title">{children}</div>}
64+
{children && <div className="k-actionsheet-title" id={titleId}>{children}</div>}
5965
{actionsEnd && (
6066
<div className="k-actionsheet-actions">
6167
{actionsEnd}
@@ -65,9 +71,9 @@ export const ActionSheetHeader = (
6571
{(input || filter) && (
6672
<div className="k-actionsheet-titlebar-group k-actionsheet-filter">
6773
{input ? (
68-
<Textbox value={inputValue} placeholder={inputPlaceholder} size={adaptive ? "large" : "medium"} />
74+
<Textbox value={inputValue} placeholder={inputPlaceholder} size={adaptive ? "large" : "medium"} aria-label={title || inputPlaceholder || "Input"} />
6975
) : (
70-
<Searchbox placeholder="Filter" size={adaptive ? "large" : "medium"} />
76+
<Searchbox placeholder="Filter" size={adaptive ? "large" : "medium"} aria-label="Filter options" />
7177
)}
7278
</div>
7379
)}

packages/html/src/action-sheet/actionsheet-item.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,17 @@ const states = [
1111
];
1212

1313
export type KendoActionSheetItemProps = {
14+
/**
15+
* Primary text label for the action item.
16+
*/
1417
text?: string;
18+
/**
19+
* Secondary description text.
20+
*/
1521
description?: string;
22+
/**
23+
* Icon name to display.
24+
*/
1625
iconName?: string;
1726
}
1827

packages/html/src/action-sheet/actionsheet-items.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { classNames } from "../misc";
22

3+
/**
4+
* Container for ActionSheet items.
5+
*/
36
export const ActionSheetItems = (
47
props: React.HTMLAttributes<HTMLDivElement>
58
) => {

packages/html/src/action-sheet/actionsheet-view.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export type KendoActionSheetViewProps = {
1616
footer?: React.ReactElement<typeof ActionSheetFooter>;
1717
adaptive?: boolean;
1818
animated?: boolean;
19+
/**
20+
* ID for the title element, used by aria-labelledby on the ActionSheet.
21+
*/
22+
titleId?: string;
1923
}
2024

2125
export const ActionSheetView = (
@@ -28,10 +32,11 @@ export const ActionSheetView = (
2832
children,
2933
header,
3034
footer,
35+
titleId,
3136
...other
3237
} = props;
3338

34-
const _ActionSheetHeader = header?.type === ActionSheetHeader && <ActionSheetHeader adaptive={adaptive} {...header?.props} />;
39+
const _ActionSheetHeader = header?.type === ActionSheetHeader && <ActionSheetHeader adaptive={adaptive} titleId={titleId} {...header?.props} />;
3540
const _ActionSheetFooter = footer?.type === ActionSheetFooter && <ActionSheetFooter {...footer?.props} />;
3641

3742
return (

packages/html/src/action-sheet/templates/action-sheet-normal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { ActionSheet, ActionSheetHeader, ActionSheetItem, ActionSheetItems } from '../../action-sheet';
22

3-
export const ActionSheetNormal = ({ title = "Select item", ...other }) => (
3+
export const ActionSheetNormal = ({ title = "Select item", id = "actionsheet-1", ...other }) => (
44
<ActionSheet
5+
id={id}
56
header={
67
<ActionSheetHeader
78
title={title}

packages/html/src/action-sheet/tests/action-sheet-actions.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export default () => (
1919
<span className='k-colspan-3'>Header Actions - LTR</span>
2020

2121
<section>
22-
<ActionSheetNormal adaptive fullscreen
22+
<ActionSheetNormal id="actionsheet-actions-1" adaptive fullscreen
2323
header={
24-
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" />} title="Start" />
24+
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" aria-label="Back" />} title="Start" />
2525
}
2626
>
2727
<ActionSheetItems>
@@ -33,9 +33,9 @@ export default () => (
3333
</section>
3434

3535
<section>
36-
<ActionSheetNormal adaptive fullscreen
36+
<ActionSheetNormal id="actionsheet-actions-2" adaptive fullscreen
3737
header={
38-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="End" />
38+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="End" />
3939
}
4040
>
4141
<ActionSheetItems>
@@ -47,9 +47,9 @@ export default () => (
4747
</section>
4848

4949
<section>
50-
<ActionSheetNormal adaptive fullscreen
50+
<ActionSheetNormal id="actionsheet-actions-3" adaptive fullscreen
5151
header={
52-
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Start & End" />
52+
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" aria-label="Back" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Start & End" />
5353
}
5454
>
5555
<ActionSheetItems>
@@ -63,9 +63,9 @@ export default () => (
6363
<span className='k-colspan-3'>Header Actions - RTL</span>
6464

6565
<section className="k-rtl">
66-
<ActionSheetNormal adaptive fullscreen
66+
<ActionSheetNormal id="actionsheet-actions-4" adaptive fullscreen
6767
header={
68-
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" />} title="Start" />
68+
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" aria-label="Back" />} title="Start" />
6969
}
7070
>
7171
<ActionSheetItems>
@@ -77,9 +77,9 @@ export default () => (
7777
</section>
7878

7979
<section className="k-rtl">
80-
<ActionSheetNormal adaptive fullscreen
80+
<ActionSheetNormal id="actionsheet-actions-5" adaptive fullscreen
8181
header={
82-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="End" />
82+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="End" />
8383
}
8484
>
8585
<ActionSheetItems>
@@ -91,9 +91,9 @@ export default () => (
9191
</section>
9292

9393
<section className="k-rtl">
94-
<ActionSheetNormal adaptive fullscreen
94+
<ActionSheetNormal id="actionsheet-actions-6" adaptive fullscreen
9595
header={
96-
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Start & End" />
96+
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" aria-label="Back" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Start & End" />
9797
}
9898
>
9999
<ActionSheetItems>

packages/html/src/action-sheet/tests/action-sheet-adaptive.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ export default () => (
2626

2727
<section>
2828
<ActionSheetNormal
29+
id="actionsheet-adaptive-1"
2930
adaptive
3031
header={
31-
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Title" subtitle="Subtitle" />
32+
<ActionSheetHeader actionsStart={<Button icon="chevron-left" size="large" fillMode="flat" aria-label="Back" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Title" subtitle="Subtitle" />
3233
}
3334
footer={
3435
<ActionSheetFooter>
@@ -53,9 +54,10 @@ export default () => (
5354

5455
<section className="k-rtl">
5556
<ActionSheetNormal
57+
id="actionsheet-adaptive-2"
5658
adaptive
5759
header={
58-
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Title" subtitle="Subtitle" />
60+
<ActionSheetHeader actionsStart={<Button icon="chevron-right" size="large" fillMode="flat" aria-label="Back" />} actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Title" subtitle="Subtitle" />
5961
}
6062
footer={
6163
<ActionSheetFooter>

packages/html/src/action-sheet/tests/action-sheet-calendar-infinite.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ export default () =>(
2626
<span>full screen</span>
2727

2828
<section>
29-
<ActionSheet adaptive={true}
29+
<ActionSheet id="actionsheet-cal-inf-1" adaptive={true}
3030
header={
31-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Select date" />
31+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Select date" />
3232

3333
}>
3434
<CalendarInfiniteNormal size="large" showNavigation={false} />
3535
</ActionSheet>
3636
</section>
3737

3838
<section>
39-
<ActionSheet adaptive={true} fullscreen={true}
39+
<ActionSheet id="actionsheet-cal-inf-2" adaptive={true} fullscreen={true}
4040
header={
41-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Select date" />
41+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Select date" />
4242
}>
4343
<CalendarInfiniteNormal size="large" showNavigation={false} />
4444
</ActionSheet>

packages/html/src/action-sheet/tests/action-sheet-calendar.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,18 @@ export default () => (
2626
<span>full screen</span>
2727

2828
<section>
29-
<ActionSheet adaptive={true}
29+
<ActionSheet id="actionsheet-calendar-1" adaptive={true}
3030
header={
31-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Select date" />
31+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Select date" />
3232
}>
3333
<CalendarNormal size="large" />
3434
</ActionSheet>
3535
</section>
3636

3737
<section>
38-
<ActionSheet adaptive={true} fullscreen={true}
38+
<ActionSheet id="actionsheet-calendar-2" adaptive={true} fullscreen={true}
3939
header={
40-
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" />} title="Select date" />
40+
<ActionSheetHeader actionsEnd={<Button icon="x" size="large" fillMode="flat" aria-label="Close" />} title="Select date" />
4141
}>
4242
<CalendarNormal size="large" />
4343
</ActionSheet>

0 commit comments

Comments
 (0)