Fix accessibility around the room list treeview and new search beta (#7856)
This commit is contained in:
parent
c6b8574dcb
commit
e2827b4082
6 changed files with 60 additions and 45 deletions
|
@ -52,6 +52,8 @@ interface IProps extends IDialogProps {
|
|||
|
||||
// Title for the dialog.
|
||||
title?: JSX.Element | string;
|
||||
// Specific aria label to use, if not provided will set aria-labelledBy to mx_Dialog_title
|
||||
"aria-label"?: string;
|
||||
|
||||
// Path to an icon to put in the header
|
||||
headerImage?: string;
|
||||
|
@ -121,23 +123,30 @@ export default class BaseDialog extends React.Component<IProps> {
|
|||
headerImage = <img className="mx_Dialog_titleImage" src={this.props.headerImage} alt="" />;
|
||||
}
|
||||
|
||||
const lockProps = {
|
||||
"onKeyDown": this.onKeyDown,
|
||||
"role": "dialog",
|
||||
// This should point to a node describing the dialog.
|
||||
// If we were about to completely follow this recommendation we'd need to
|
||||
// make all the components relying on BaseDialog to be aware of it.
|
||||
// So instead we will use the whole content as the description.
|
||||
// Description comes first and if the content contains more text,
|
||||
// AT users can skip its presentation.
|
||||
"aria-describedby": this.props.contentId,
|
||||
};
|
||||
|
||||
if (this.props["aria-label"]) {
|
||||
lockProps["aria-label"] = this.props["aria-label"];
|
||||
} else {
|
||||
lockProps["aria-labelledby"] = "mx_BaseDialog_title";
|
||||
}
|
||||
|
||||
return (
|
||||
<MatrixClientContext.Provider value={this.matrixClient}>
|
||||
<PosthogScreenTracker screenName={this.props.screenName} />
|
||||
<FocusLock
|
||||
returnFocus={true}
|
||||
lockProps={{
|
||||
onKeyDown: this.onKeyDown,
|
||||
role: "dialog",
|
||||
["aria-labelledby"]: "mx_BaseDialog_title",
|
||||
// This should point to a node describing the dialog.
|
||||
// If we were about to completely follow this recommendation we'd need to
|
||||
// make all the components relying on BaseDialog to be aware of it.
|
||||
// So instead we will use the whole content as the description.
|
||||
// Description comes first and if the content contains more text,
|
||||
// AT users can skip its presentation.
|
||||
["aria-describedby"]: this.props.contentId,
|
||||
}}
|
||||
lockProps={lockProps}
|
||||
className={classNames({
|
||||
[this.props.className]: true,
|
||||
'mx_Dialog_fixedWidth': this.props.fixedWidth,
|
||||
|
|
|
@ -79,7 +79,7 @@ import { getCachedRoomIDForAlias } from "../../../RoomAliasCache";
|
|||
const MAX_RECENT_SEARCHES = 10;
|
||||
const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons
|
||||
|
||||
const Option: React.FC<ComponentProps<typeof RovingAccessibleButton>> = ({ inputRef, ...props }) => {
|
||||
const Option: React.FC<ComponentProps<typeof RovingAccessibleButton>> = ({ inputRef, children, ...props }) => {
|
||||
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
|
||||
return <AccessibleButton
|
||||
{...props}
|
||||
|
@ -88,7 +88,10 @@ const Option: React.FC<ComponentProps<typeof RovingAccessibleButton>> = ({ input
|
|||
tabIndex={-1}
|
||||
aria-selected={isActive}
|
||||
role="option"
|
||||
/>;
|
||||
>
|
||||
{ children }
|
||||
<div className="mx_SpotlightDialog_enterPrompt" aria-hidden>↵</div>
|
||||
</AccessibleButton>;
|
||||
};
|
||||
|
||||
const TooltipOption: React.FC<ComponentProps<typeof RovingAccessibleTooltipButton>> = ({ inputRef, ...props }) => {
|
||||
|
@ -357,7 +360,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
{ result.room.name }
|
||||
<NotificationBadge notification={RoomNotificationStateStore.instance.getRoomState(result.room)} />
|
||||
<ResultDetails room={result.room} />
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
);
|
||||
}
|
||||
|
@ -372,7 +374,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
{ otherResult.avatar }
|
||||
{ otherResult.name }
|
||||
{ otherResult.description }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
);
|
||||
};
|
||||
|
@ -431,7 +432,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
{ room.name && room.canonical_alias && <div className="mx_SpotlightDialog_result_details">
|
||||
{ room.canonical_alias }
|
||||
</div> }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
)) }
|
||||
{ spaceResultsLoading && <Spinner /> }
|
||||
|
@ -463,7 +463,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
{ _t("Join %(roomAddress)s", {
|
||||
roomAddress: trimmedQuery,
|
||||
}) }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
</div>
|
||||
</div>;
|
||||
|
@ -490,7 +489,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
}}
|
||||
>
|
||||
{ _t("Public rooms") }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
<Option
|
||||
id="mx_SpotlightDialog_button_startChat"
|
||||
|
@ -501,7 +499,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
}}
|
||||
>
|
||||
{ _t("People") }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -544,7 +541,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
{ room.name }
|
||||
<NotificationBadge notification={RoomNotificationStateStore.instance.getRoomState(room)} />
|
||||
<ResultDetails room={room} />
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
)) }
|
||||
</div>
|
||||
|
@ -590,7 +586,6 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
}}
|
||||
>
|
||||
{ _t("Explore public rooms") }
|
||||
<div className="mx_SpotlightDialog_enterPrompt">↵</div>
|
||||
</Option>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -679,7 +674,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
const activeDescendant = rovingContext.state.activeRef?.current?.id;
|
||||
|
||||
return <>
|
||||
<div className="mx_SpotlightDialog_keyboardPrompt">
|
||||
<div id="mx_SpotlightDialog_keyboardPrompt">
|
||||
{ _t("Use <arrows/> to scroll", {}, {
|
||||
arrows: () => <>
|
||||
<div>↓</div>
|
||||
|
@ -696,6 +691,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
hasCancel={false}
|
||||
onKeyDown={onDialogKeyDown}
|
||||
screenName="UnifiedSearch"
|
||||
aria-label={_t("Search Dialog")}
|
||||
>
|
||||
<div className="mx_SpotlightDialog_searchBox mx_textinput">
|
||||
<input
|
||||
|
@ -708,10 +704,17 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", onFinished }) =>
|
|||
onKeyDown={onKeyDown}
|
||||
aria-owns="mx_SpotlightDialog_content"
|
||||
aria-activedescendant={activeDescendant}
|
||||
aria-label={_t("Search")}
|
||||
aria-describedby="mx_SpotlightDialog_keyboardPrompt"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="mx_SpotlightDialog_content" role="listbox" aria-activedescendant={activeDescendant}>
|
||||
<div
|
||||
id="mx_SpotlightDialog_content"
|
||||
role="listbox"
|
||||
aria-activedescendant={activeDescendant}
|
||||
aria-describedby="mx_SpotlightDialog_keyboardPrompt"
|
||||
>
|
||||
{ content }
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue