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
This commit is contained in:
R Midhun Suresh
2025-01-27 15:05:28 +00:00
committed by GitHub
parent c0567fc5f4
commit 76485cfb17
4 changed files with 42 additions and 32 deletions
+7 -7
View File
@@ -7,14 +7,14 @@ Please see LICENSE files in the repository root for full details.
*/ */
import classNames from "classnames"; import classNames from "classnames";
import React, { useMemo } from "react"; import React, { ComponentProps, JSXElementConstructor, useMemo } from "react";
type FlexProps = { type FlexProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = {
/** /**
* The type of the HTML element * The type of the HTML element
* @default div * @default div
*/ */
as?: string; as?: T;
/** /**
* The CSS class name. * The CSS class name.
*/ */
@@ -30,7 +30,7 @@ type FlexProps = {
*/ */
direction?: "row" | "column" | "row-reverse" | "column-reverse"; direction?: "row" | "column" | "row-reverse" | "column-reverse";
/** /**
* The alingment of the flex children * The alignment of the flex children
* @default start * @default start
*/ */
align?: "start" | "center" | "end" | "baseline" | "stretch"; align?: "start" | "center" | "end" | "baseline" | "stretch";
@@ -48,12 +48,12 @@ type FlexProps = {
* the on click event callback * the on click event callback
*/ */
onClick?: (e: React.MouseEvent) => void; onClick?: (e: React.MouseEvent) => void;
}; } & ComponentProps<T>;
/** /**
* A flexbox container helper * A flexbox container helper
*/ */
export function Flex({ export function Flex<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any> = "div">({
as = "div", as = "div",
display = "flex", display = "flex",
direction = "row", direction = "row",
@@ -63,7 +63,7 @@ export function Flex({
className, className,
children, children,
...props ...props
}: React.PropsWithChildren<FlexProps>): JSX.Element { }: React.PropsWithChildren<FlexProps<T>>): JSX.Element {
const style = useMemo( const style = useMemo(
() => ({ () => ({
"--mx-flex-display": display, "--mx-flex-display": display,
@@ -21,6 +21,7 @@ import { ThreePidInviteTileView } from "./tiles/ThreePidInviteTileView";
import { MemberListHeaderView } from "./MemberListHeaderView"; import { MemberListHeaderView } from "./MemberListHeaderView";
import BaseCard from "../../right_panel/BaseCard"; import BaseCard from "../../right_panel/BaseCard";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import { RovingTabIndexProvider } from "../../../../accessibility/RovingTabIndex";
interface IProps { interface IProps {
roomId: string; roomId: string;
@@ -86,7 +87,14 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
header={_t("common|people")} header={_t("common|people")}
onClose={props.onClose} onClose={props.onClose}
> >
<Flex align="stretch" direction="column" className="mx_MemberListView_container"> <RovingTabIndexProvider handleUpDown scrollIntoView>
{({ onKeyDownHandler }) => (
<Flex
align="stretch"
direction="column"
className="mx_MemberListView_container"
onKeyDown={onKeyDownHandler}
>
<Form.Root> <Form.Root>
<MemberListHeaderView vm={vm} /> <MemberListHeaderView vm={vm} />
</Form.Root> </Form.Root>
@@ -104,6 +112,8 @@ const MemberListView: React.FC<IProps> = (props: IProps) => {
)} )}
</AutoSizer> </AutoSizer>
</Flex> </Flex>
)}
</RovingTabIndexProvider>
</BaseCard> </BaseCard>
); );
}; };
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
import React from "react"; import React from "react";
import AccessibleButton from "../../../../elements/AccessibleButton"; import { RovingAccessibleButton } from "../../../../../../accessibility/RovingTabIndex";
interface Props { interface Props {
avatarJsx: JSX.Element; avatarJsx: JSX.Element;
@@ -28,7 +28,7 @@ export function MemberTileView(props: Props): JSX.Element {
return ( return (
// The wrapping div is required to make the magic mouse listener work, for some reason. // The wrapping div is required to make the magic mouse listener work, for some reason.
<div> <div>
<AccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}> <RovingAccessibleButton className="mx_MemberTileView" title={props.title} onClick={props.onClick}>
<div className="mx_MemberTileView_left"> <div className="mx_MemberTileView_left">
<div className="mx_MemberTileView_avatar"> <div className="mx_MemberTileView_avatar">
{props.avatarJsx} {props.presenceJsx} {props.avatarJsx} {props.presenceJsx}
@@ -39,7 +39,7 @@ export function MemberTileView(props: Props): JSX.Element {
{userLabelJsx} {userLabelJsx}
{props.iconJsx} {props.iconJsx}
</div> </div>
</AccessibleButton> </RovingAccessibleButton>
</div> </div>
); );
} }
@@ -7,7 +7,7 @@ exports[`MemberTileView RoomMemberTileView should display an verified E2EIcon wh
aria-label="@userId:matrix.org (power 0)" aria-label="@userId:matrix.org (power 0)"
class="mx_AccessibleButton mx_MemberTileView" class="mx_AccessibleButton mx_MemberTileView"
role="button" role="button"
tabindex="0" tabindex="-1"
> >
<div <div
class="mx_MemberTileView_left" class="mx_MemberTileView_left"
@@ -76,7 +76,7 @@ exports[`MemberTileView RoomMemberTileView should display an warning E2EIcon whe
aria-label="@userId:matrix.org (power 0)" aria-label="@userId:matrix.org (power 0)"
class="mx_AccessibleButton mx_MemberTileView" class="mx_AccessibleButton mx_MemberTileView"
role="button" role="button"
tabindex="0" tabindex="-1"
> >
<div <div
class="mx_MemberTileView_left" class="mx_MemberTileView_left"
@@ -145,7 +145,7 @@ exports[`MemberTileView RoomMemberTileView should not display an E2EIcon when th
aria-label="@userId:matrix.org (power 0)" aria-label="@userId:matrix.org (power 0)"
class="mx_AccessibleButton mx_MemberTileView" class="mx_AccessibleButton mx_MemberTileView"
role="button" role="button"
tabindex="0" tabindex="-1"
> >
<div <div
class="mx_MemberTileView_left" class="mx_MemberTileView_left"
@@ -195,7 +195,7 @@ exports[`MemberTileView ThreePidInviteTileView renders ThreePidInvite correctly
<div <div
class="mx_AccessibleButton mx_MemberTileView" class="mx_AccessibleButton mx_MemberTileView"
role="button" role="button"
tabindex="0" tabindex="-1"
> >
<div <div
class="mx_MemberTileView_left" class="mx_MemberTileView_left"