Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit fe24c8a

Browse files
authored
Improve ThreadPanel ctx menu accessibility (#7217)
1 parent 9727a82 commit fe24c8a

20 files changed

+35
-48
lines changed

Diff for: res/css/structures/_ContextualMenu.scss

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ limitations under the License.
2727
width: 100%;
2828
height: 100%;
2929
opacity: 1.0;
30-
z-index: 5000;
3130
}
3231

3332
.mx_ContextualMenu {

Diff for: res/css/views/right_panel/_ThreadPanel.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ limitations under the License.
120120
&:hover {
121121
background-color: $event-selected-color;
122122
}
123-
&[aria-selected="true"] {
123+
&[aria-checked="true"] {
124124
:first-child {
125125
margin-left: -20px;
126126
}

Diff for: src/components/structures/ContextMenu.tsx

+7-15
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ interface IState {
103103
// all options inside the menu should be of role=menuitem/menuitemcheckbox/menuitemradiobutton and have tabIndex={-1}
104104
// this will allow the ContextMenu to manage its own focus using arrow keys as per the ARIA guidelines.
105105
@replaceableComponent("structures.ContextMenu")
106-
export class ContextMenu extends React.PureComponent<IProps, IState> {
106+
export default class ContextMenu extends React.PureComponent<IProps, IState> {
107107
private readonly initialFocus: HTMLElement;
108108

109109
static defaultProps = {
@@ -411,6 +411,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
411411
onClick={this.onClick}
412412
onContextMenu={this.onContextMenuPreventBubbling}
413413
>
414+
{ background }
414415
<div
415416
className={menuClasses}
416417
style={menuStyle}
@@ -419,7 +420,6 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
419420
>
420421
{ body }
421422
</div>
422-
{ background }
423423
</div>
424424
);
425425
}
@@ -530,30 +530,22 @@ export const useContextMenu = <T extends any = HTMLElement>(): ContextMenuTuple<
530530
return [isOpen, button, open, close, setIsOpen];
531531
};
532532

533-
@replaceableComponent("structures.LegacyContextMenu")
534-
export default class LegacyContextMenu extends ContextMenu {
535-
render() {
536-
return this.renderMenu(false);
537-
}
538-
}
539-
540533
// XXX: Deprecated, used only for dynamic Tooltips. Avoid using at all costs.
541534
export function createMenu(ElementClass, props) {
542535
const onFinished = function(...args) {
543536
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
544-
545-
if (props && props.onFinished) {
546-
props.onFinished.apply(null, args);
547-
}
537+
props?.onFinished?.apply(null, args);
548538
};
549539

550-
const menu = <LegacyContextMenu
540+
const menu = <ContextMenu
551541
{...props}
542+
mountAsChild={true}
543+
hasBackground={false}
552544
onFinished={onFinished} // eslint-disable-line react/jsx-no-bind
553545
windowResize={onFinished} // eslint-disable-line react/jsx-no-bind
554546
>
555547
<ElementClass {...props} onFinished={onFinished} />
556-
</LegacyContextMenu>;
548+
</ContextMenu>;
557549

558550
ReactDOM.render(menu, getOrCreateContainer());
559551

Diff for: src/components/structures/ThreadPanel.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
2424
import MatrixClientContext from '../../contexts/MatrixClientContext';
2525
import { _t } from '../../languageHandler';
2626
import { ContextMenuButton } from '../../accessibility/context_menu/ContextMenuButton';
27-
import ContextMenu, { ChevronFace, useContextMenu } from './ContextMenu';
27+
import ContextMenu, { ChevronFace, MenuItemRadio, useContextMenu } from './ContextMenu';
2828
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
2929
import TimelinePanel from './TimelinePanel';
3030
import { Layout } from '../../settings/enums/Layout';
3131
import { useEventEmitter } from '../../hooks/useEventEmitter';
32-
import AccessibleButton from '../views/elements/AccessibleButton';
3332
import { TileShape } from '../views/rooms/EventTile';
3433
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
3534

@@ -98,14 +97,14 @@ export const ThreadPanelHeaderFilterOptionItem = ({
9897
onClick: () => void;
9998
isSelected: boolean;
10099
}) => {
101-
return <AccessibleButton
102-
aria-selected={isSelected}
100+
return <MenuItemRadio
101+
active={isSelected}
103102
className="mx_ThreadPanel_Header_FilterOptionItem"
104103
onClick={onClick}
105104
>
106105
<span>{ label }</span>
107106
<span>{ description }</span>
108-
</AccessibleButton>;
107+
</MenuItemRadio>;
109108
};
110109

111110
export const ThreadPanelHeader = ({ filterOption, setFilterOption }: {
@@ -141,8 +140,8 @@ export const ThreadPanelHeader = ({ filterOption, setFilterOption }: {
141140
top={0}
142141
right={25}
143142
onFinished={closeMenu}
144-
managed={false}
145143
chevronFace={ChevronFace.Top}
144+
mountAsChild={true}
146145
>
147146
{ contextMenuOptions }
148147
</ContextMenu> : null;

Diff for: src/components/views/avatars/MemberStatusMessageAvatar.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import MemberAvatar from '../avatars/MemberAvatar';
2121
import classNames from 'classnames';
2222
import StatusMessageContextMenu from "../context_menus/StatusMessageContextMenu";
2323
import SettingsStore from "../../../settings/SettingsStore";
24-
import { ChevronFace, ContextMenu, ContextMenuButton } from "../../structures/ContextMenu";
24+
import ContextMenu, { ChevronFace, ContextMenuButton } from "../../structures/ContextMenu";
2525
import { replaceableComponent } from "../../../utils/replaceableComponent";
2626
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
2727
import { ResizeMethod } from "matrix-js-sdk/src/@types/partials";

Diff for: src/components/views/context_menus/CallContextMenu.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
import React from 'react';
1818
import PropTypes from 'prop-types';
1919
import { _t } from '../../../languageHandler';
20-
import { ContextMenu, IProps as IContextMenuProps, MenuItem } from '../../structures/ContextMenu';
20+
import ContextMenu, { IProps as IContextMenuProps, MenuItem } from '../../structures/ContextMenu';
2121
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
2222
import CallHandler from '../../../CallHandler';
2323
import InviteDialog, { KIND_CALL_TRANSFER } from '../dialogs/InviteDialog';

Diff for: src/components/views/context_menus/DialpadContextMenu.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
import * as React from "react";
1818
import { createRef } from "react";
1919
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
20-
import { ContextMenu, IProps as IContextMenuProps } from '../../structures/ContextMenu';
20+
import ContextMenu, { IProps as IContextMenuProps } from '../../structures/ContextMenu';
2121
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
2222
import Field from "../elements/Field";
2323
import DialPad from '../voip/DialPad';

Diff for: src/components/views/context_menus/IconizedContextMenu.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ limitations under the License.
1717
import React from "react";
1818
import classNames from "classnames";
1919

20-
import {
20+
import ContextMenu, {
2121
ChevronFace,
22-
ContextMenu,
2322
IProps as IContextMenuProps,
2423
MenuItem,
2524
MenuItemCheckbox, MenuItemRadio,

Diff for: src/components/views/directory/NetworkDropdown.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ import { IProtocol } from "matrix-js-sdk/src/client";
2121

2222
import { MatrixClientPeg } from '../../../MatrixClientPeg';
2323
import { instanceForInstanceId } from '../../../utils/DirectoryUtils';
24-
import {
24+
import ContextMenu, {
2525
ChevronFace,
26-
ContextMenu,
2726
ContextMenuButton,
2827
MenuGroup,
2928
MenuItem,

Diff for: src/components/views/elements/DNDTagTile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ limitations under the License.
1818
import TagTile from './TagTile';
1919

2020
import React from 'react';
21-
import { ContextMenu, toRightOf, useContextMenu } from "../../structures/ContextMenu";
21+
import ContextMenu, { toRightOf, useContextMenu } from "../../structures/ContextMenu";
2222
import * as sdk from '../../../index';
2323

2424
export default function DNDTagTile(props) {

Diff for: src/components/views/groups/GroupInviteTile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import dis from '../../../dispatcher/dispatcher';
2323
import { _t } from '../../../languageHandler';
2424
import classNames from 'classnames';
2525
import { MatrixClientPeg } from "../../../MatrixClientPeg";
26-
import { ContextMenu, ContextMenuButton, toRightOf } from "../../structures/ContextMenu";
26+
import ContextMenu, { ContextMenuButton, toRightOf } from "../../structures/ContextMenu";
2727
import MatrixClientContext from "../../../contexts/MatrixClientContext";
2828
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
2929
import { replaceableComponent } from "../../../utils/replaceableComponent";

Diff for: src/components/views/messages/MessageActionBar.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type { Relations } from 'matrix-js-sdk/src/models/relations';
2323
import { _t } from '../../../languageHandler';
2424
import dis from '../../../dispatcher/dispatcher';
2525
import { Action } from '../../../dispatcher/actions';
26-
import { aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
26+
import ContextMenu, { aboveLeftOf, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
2727
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
2828
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
2929
import Toolbar from "../../../accessibility/Toolbar";

Diff for: src/components/views/messages/ReactionsRow.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { _t } from '../../../languageHandler';
2424
import { isContentActionable } from '../../../utils/EventUtils';
2525
import { replaceableComponent } from "../../../utils/replaceableComponent";
2626
import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton";
27-
import { aboveLeftOf, ContextMenu, useContextMenu } from "../../structures/ContextMenu";
27+
import ContextMenu, { aboveLeftOf, useContextMenu } from "../../structures/ContextMenu";
2828
import ReactionPicker from "../emojipicker/ReactionPicker";
2929
import ReactionsRowButton from "./ReactionsRowButton";
3030
import MatrixClientContext from "../../../contexts/MatrixClientContext";

Diff for: src/components/views/rooms/MessageComposer.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ import { makeRoomPermalink, RoomPermalinkCreator } from '../../../utils/permalin
2727
import ContentMessages from '../../../ContentMessages';
2828
import E2EIcon from './E2EIcon';
2929
import SettingsStore from "../../../settings/SettingsStore";
30-
import {
30+
import ContextMenu, {
3131
aboveLeftOf,
32-
ContextMenu,
3332
useContextMenu,
3433
MenuItem,
3534
AboveLeftOf,

Diff for: src/components/views/rooms/RoomSublist.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ import { _t } from "../../../languageHandler";
2626
import AccessibleButton from "../../views/elements/AccessibleButton";
2727
import RoomTile from "./RoomTile";
2828
import { ListLayout } from "../../../stores/room-list/ListLayout";
29-
import {
29+
import ContextMenu, {
3030
ChevronFace,
31-
ContextMenu,
3231
ContextMenuTooltipButton,
3332
StyledMenuItemCheckbox,
3433
StyledMenuItemRadio,

Diff for: src/components/views/rooms/Stickerpicker.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16+
1617
import React from 'react';
1718
import { Room } from 'matrix-js-sdk/src/models/room';
1819
import { _t, _td } from '../../../languageHandler';
@@ -24,7 +25,7 @@ import WidgetUtils, { IWidgetEvent } from '../../../utils/WidgetUtils';
2425
import PersistedElement from "../elements/PersistedElement";
2526
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
2627
import SettingsStore from "../../../settings/SettingsStore";
27-
import { ChevronFace, ContextMenu } from "../../structures/ContextMenu";
28+
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
2829
import { WidgetType } from "../../../widgets/WidgetType";
2930
import { Action } from "../../../dispatcher/actions";
3031
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";

Diff for: src/components/views/spaces/QuickSettingsButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import React, { useMemo } from "react";
1818

1919
import { _t } from "../../../languageHandler";
2020
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
21-
import { alwaysAboveRightOf, ChevronFace, ContextMenu, useContextMenu } from "../../structures/ContextMenu";
21+
import ContextMenu, { alwaysAboveRightOf, ChevronFace, useContextMenu } from "../../structures/ContextMenu";
2222
import AccessibleButton from "../elements/AccessibleButton";
2323
import StyledCheckbox from "../elements/StyledCheckbox";
2424
import { MetaSpace } from "../../../stores/spaces";

Diff for: src/components/views/spaces/SpaceCreateMenu.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { HistoryVisibility, Preset } from "matrix-js-sdk/src/@types/partials";
2222

2323
import { _t } from "../../../languageHandler";
2424
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
25-
import { ChevronFace, ContextMenu } from "../../structures/ContextMenu";
25+
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
2626
import createRoom, { IOpts as ICreateOpts } from "../../../createRoom";
2727
import MatrixClientContext from "../../../contexts/MatrixClientContext";
2828
import SpaceBasicSettings, { SpaceAvatar } from "./SpaceBasicSettings";

Diff for: test/components/structures/ThreadPanel-test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('ThreadPanel', () => {
7070
wrapper.find(ContextMenuButton).simulate('click');
7171
const found = wrapper.find(ThreadPanelHeaderFilterOptionItem);
7272
expect(found.length).toEqual(2);
73-
const foundButton = found.find('[aria-selected=true]').first();
73+
const foundButton = found.find('[aria-checked=true]').first();
7474
expect(foundButton.text()).toEqual(`${_t("All threads")}${_t('Shows all threads from current room')}`);
7575
expect(foundButton).toMatchSnapshot();
7676
});

Diff for: test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap

+6-6
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,21 @@ exports[`ThreadPanel Header expect that My filter for ThreadPanelHeader properly
4646

4747
exports[`ThreadPanel Header expect that ThreadPanelHeader has the correct option selected in the context menu 1`] = `
4848
<AccessibleButton
49-
aria-selected={true}
49+
aria-checked={true}
5050
className="mx_ThreadPanel_Header_FilterOptionItem"
5151
element="div"
5252
onClick={[Function]}
53-
role="button"
54-
tabIndex={0}
53+
role="menuitemradio"
54+
tabIndex={-1}
5555
>
5656
<div
57-
aria-selected={true}
57+
aria-checked={true}
5858
className="mx_AccessibleButton mx_ThreadPanel_Header_FilterOptionItem"
5959
onClick={[Function]}
6060
onKeyDown={[Function]}
6161
onKeyUp={[Function]}
62-
role="button"
63-
tabIndex={0}
62+
role="menuitemradio"
63+
tabIndex={-1}
6464
>
6565
<span>
6666
All threads

0 commit comments

Comments
 (0)