Skip to content

Commit 76485cf

Browse files
Allow navigating through the memberlist using up/down keys (#28949)
* Allow flex component to take child containers props So that we can set attributes on the container * Use Up/Down arrow keys to navigate through the list * Update snapshot
1 parent c0567fc commit 76485cf

File tree

4 files changed

+42
-32
lines changed

4 files changed

+42
-32
lines changed

src/components/utils/Flex.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import classNames from "classnames";
10-
import React, { useMemo } from "react";
10+
import React, { ComponentProps, JSXElementConstructor, useMemo } from "react";
1111

12-
type FlexProps = {
12+
type FlexProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = {
1313
/**
1414
* The type of the HTML element
1515
* @default div
1616
*/
17-
as?: string;
17+
as?: T;
1818
/**
1919
* The CSS class name.
2020
*/
@@ -30,7 +30,7 @@ type FlexProps = {
3030
*/
3131
direction?: "row" | "column" | "row-reverse" | "column-reverse";
3232
/**
33-
* The alingment of the flex children
33+
* The alignment of the flex children
3434
* @default start
3535
*/
3636
align?: "start" | "center" | "end" | "baseline" | "stretch";
@@ -48,12 +48,12 @@ type FlexProps = {
4848
* the on click event callback
4949
*/
5050
onClick?: (e: React.MouseEvent) => void;
51-
};
51+
} & ComponentProps<T>;
5252

5353
/**
5454
* A flexbox container helper
5555
*/
56-
export function Flex({
56+
export function Flex<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any> = "div">({
5757
as = "div",
5858
display = "flex",
5959
direction = "row",
@@ -63,7 +63,7 @@ export function Flex({
6363
className,
6464
children,
6565
...props
66-
}: React.PropsWithChildren<FlexProps>): JSX.Element {
66+
}: React.PropsWithChildren<FlexProps<T>>): JSX.Element {
6767
const style = useMemo(
6868
() => ({
6969
"--mx-flex-display": display,

src/components/views/rooms/MemberList/MemberListView.tsx

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ThreePidInviteTileView } from "./tiles/ThreePidInviteTileView";
2121
import { MemberListHeaderView } from "./MemberListHeaderView";
2222
import BaseCard from "../../right_panel/BaseCard";
2323
import { _t } from "../../../../languageHandler";
24+
import { RovingTabIndexProvider } from "../../../../accessibility/RovingTabIndex";
2425

2526
interface IProps {
2627
roomId: string;
@@ -86,24 +87,33 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
8687
header={_t("common|people")}
8788
onClose={props.onClose}
8889
>
89-
<Flex align="stretch" direction="column" className="mx_MemberListView_container">
90-
<Form.Root>
91-
<MemberListHeaderView vm={vm} />
92-
</Form.Root>
93-
<AutoSizer>
94-
{({ height, width }) => (
95-
<List
96-
rowRenderer={rowRenderer}
97-
rowHeight={getRowHeight}
98-
// The +1 refers to the additional empty div that we render at the end of the list.
99-
rowCount={totalRows + 1}
100-
// Subtract the height of MemberlistHeaderView so that the parent div does not overflow.
101-
height={height - 113}
102-
width={width}
103-
/>
104-
)}
105-
</AutoSizer>
106-
</Flex>
90+
<RovingTabIndexProvider handleUpDown scrollIntoView>
91+
{({ onKeyDownHandler }) => (
92+
<Flex
93+
align="stretch"
94+
direction="column"
95+
className="mx_MemberListView_container"
96+
onKeyDown={onKeyDownHandler}
97+
>
98+
<Form.Root>
99+
<MemberListHeaderView vm={vm} />
100+
</Form.Root>
101+
<AutoSizer>
102+
{({ height, width }) => (
103+
<List
104+
rowRenderer={rowRenderer}
105+
rowHeight={getRowHeight}
106+
// The +1 refers to the additional empty div that we render at the end of the list.
107+
rowCount={totalRows + 1}
108+
// Subtract the height of MemberlistHeaderView so that the parent div does not overflow.
109+
height={height - 113}
110+
width={width}
111+
/>
112+
)}
113+
</AutoSizer>
114+
</Flex>
115+
)}
116+
</RovingTabIndexProvider>
107117
</BaseCard>
108118
);
109119
};

src/components/views/rooms/MemberList/tiles/common/MemberTileView.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
77

88
import React from "react";
99

10-
import AccessibleButton from "../../../../elements/AccessibleButton";
10+
import { RovingAccessibleButton } from "../../../../../../accessibility/RovingTabIndex";
1111

1212
interface Props {
1313
avatarJsx: JSX.Element;
@@ -28,7 +28,7 @@ export function MemberTileView(props: Props): JSX.Element {
2828
return (
2929
// The wrapping div is required to make the magic mouse listener work, for some reason.
3030
<div>
31-
<AccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}>
31+
<RovingAccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}>
3232
<div className="mx_MemberTileView_left">
3333
<div className="mx_MemberTileView_avatar">
3434
{props.avatarJsx} {props.presenceJsx}
@@ -39,7 +39,7 @@ export function MemberTileView(props: Props): JSX.Element {
3939
{userLabelJsx}
4040
{props.iconJsx}
4141
</div>
42-
</AccessibleButton>
42+
</RovingAccessibleButton>
4343
</div>
4444
);
4545
}

test/unit-tests/components/views/rooms/memberlist/__snapshots__/MemberTileView-test.tsx.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ exports[`MemberTileView RoomMemberTileView should display an verified E2EIcon wh
77
aria-label="@userId:matrix.org (power 0)"
88
class="mx_AccessibleButton mx_MemberTileView"
99
role="button"
10-
tabindex="0"
10+
tabindex="-1"
1111
>
1212
<div
1313
class="mx_MemberTileView_left"
@@ -76,7 +76,7 @@ exports[`MemberTileView RoomMemberTileView should display an warning E2EIcon whe
7676
aria-label="@userId:matrix.org (power 0)"
7777
class="mx_AccessibleButton mx_MemberTileView"
7878
role="button"
79-
tabindex="0"
79+
tabindex="-1"
8080
>
8181
<div
8282
class="mx_MemberTileView_left"
@@ -145,7 +145,7 @@ exports[`MemberTileView RoomMemberTileView should not display an E2EIcon when th
145145
aria-label="@userId:matrix.org (power 0)"
146146
class="mx_AccessibleButton mx_MemberTileView"
147147
role="button"
148-
tabindex="0"
148+
tabindex="-1"
149149
>
150150
<div
151151
class="mx_MemberTileView_left"
@@ -195,7 +195,7 @@ exports[`MemberTileView ThreePidInviteTileView renders ThreePidInvite correctly
195195
<div
196196
class="mx_AccessibleButton mx_MemberTileView"
197197
role="button"
198-
tabindex="0"
198+
tabindex="-1"
199199
>
200200
<div
201201
class="mx_MemberTileView_left"

0 commit comments

Comments
 (0)