mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-16 21:24:59 +08:00
Fix room list v2 context menus to be aria menus
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
83cfdd9c07
commit
069cdf3ce0
@ -23,6 +23,8 @@ import classNames from 'classnames';
|
|||||||
import {Key} from "../../Keyboard";
|
import {Key} from "../../Keyboard";
|
||||||
import * as sdk from "../../index";
|
import * as sdk from "../../index";
|
||||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
|
import StyledCheckbox from "../views/elements/StyledCheckbox";
|
||||||
|
import StyledRadioButton from "../views/elements/StyledRadioButton";
|
||||||
|
|
||||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||||
// of doing reusable widgets like dialog boxes & menus where we go and
|
// of doing reusable widgets like dialog boxes & menus where we go and
|
||||||
@ -421,6 +423,23 @@ MenuItemCheckbox.propTypes = {
|
|||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Semantic component for representing a styled role=menuitemcheckbox
|
||||||
|
export const StyledMenuItemCheckbox = ({children, label, active=false, disabled=false, ...props}) => {
|
||||||
|
return (
|
||||||
|
<StyledCheckbox {...props} role="menuitemcheckbox" aria-checked={active} aria-disabled={disabled} tabIndex={-1} aria-label={label}>
|
||||||
|
{ children }
|
||||||
|
</StyledCheckbox>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
StyledMenuItemCheckbox.propTypes = {
|
||||||
|
...AccessibleButton.propTypes,
|
||||||
|
label: PropTypes.string, // optional
|
||||||
|
active: PropTypes.bool.isRequired,
|
||||||
|
disabled: PropTypes.bool, // optional
|
||||||
|
className: PropTypes.string, // optional
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
// Semantic component for representing a role=menuitemradio
|
// Semantic component for representing a role=menuitemradio
|
||||||
export const MenuItemRadio = ({children, label, active=false, disabled=false, ...props}) => {
|
export const MenuItemRadio = ({children, label, active=false, disabled=false, ...props}) => {
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
@ -439,6 +458,23 @@ MenuItemRadio.propTypes = {
|
|||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Semantic component for representing a styled role=menuitemradio
|
||||||
|
export const StyledMenuItemRadio = ({children, label, active=false, disabled=false, ...props}) => {
|
||||||
|
return (
|
||||||
|
<StyledRadioButton {...props} role="menuitemradio" aria-checked={active} aria-disabled={disabled} tabIndex={-1} aria-label={label}>
|
||||||
|
{ children }
|
||||||
|
</StyledRadioButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
StyledMenuItemRadio.propTypes = {
|
||||||
|
...StyledMenuItemRadio.propTypes,
|
||||||
|
label: PropTypes.string, // optional
|
||||||
|
active: PropTypes.bool.isRequired,
|
||||||
|
disabled: PropTypes.bool, // optional
|
||||||
|
className: PropTypes.string, // optional
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
// Placement method for <ContextMenu /> to position context menu to right of elementRect with chevronOffset
|
// Placement method for <ContextMenu /> to position context menu to right of elementRect with chevronOffset
|
||||||
export const toRightOf = (elementRect, chevronOffset=12) => {
|
export const toRightOf = (elementRect, chevronOffset=12) => {
|
||||||
const left = elementRect.right + window.pageXOffset + 3;
|
const left = elementRect.right + window.pageXOffset + 3;
|
||||||
|
@ -26,16 +26,18 @@ import AccessibleButton from "../../views/elements/AccessibleButton";
|
|||||||
import RoomTile2 from "./RoomTile2";
|
import RoomTile2 from "./RoomTile2";
|
||||||
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
||||||
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
||||||
import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu";
|
import {
|
||||||
import StyledCheckbox from "../elements/StyledCheckbox";
|
ContextMenu,
|
||||||
import StyledRadioButton from "../elements/StyledRadioButton";
|
ContextMenuButton,
|
||||||
|
StyledMenuItemCheckbox,
|
||||||
|
StyledMenuItemRadio,
|
||||||
|
} from "../../structures/ContextMenu";
|
||||||
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||||
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import NotificationBadge from "./NotificationBadge";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
||||||
import Tooltip from "../elements/Tooltip";
|
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
|
|
||||||
@ -329,40 +331,40 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
|||||||
<div className="mx_RoomSublist2_contextMenu">
|
<div className="mx_RoomSublist2_contextMenu">
|
||||||
<div>
|
<div>
|
||||||
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Sort by")}</div>
|
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Sort by")}</div>
|
||||||
<StyledRadioButton
|
<StyledMenuItemRadio
|
||||||
onChange={() => this.onTagSortChanged(SortAlgorithm.Recent)}
|
onChange={() => this.onTagSortChanged(SortAlgorithm.Recent)}
|
||||||
checked={!isAlphabetical}
|
checked={!isAlphabetical}
|
||||||
name={`mx_${this.props.tagId}_sortBy`}
|
name={`mx_${this.props.tagId}_sortBy`}
|
||||||
>
|
>
|
||||||
{_t("Activity")}
|
{_t("Activity")}
|
||||||
</StyledRadioButton>
|
</StyledMenuItemRadio>
|
||||||
<StyledRadioButton
|
<StyledMenuItemRadio
|
||||||
onChange={() => this.onTagSortChanged(SortAlgorithm.Alphabetic)}
|
onChange={() => this.onTagSortChanged(SortAlgorithm.Alphabetic)}
|
||||||
checked={isAlphabetical}
|
checked={isAlphabetical}
|
||||||
name={`mx_${this.props.tagId}_sortBy`}
|
name={`mx_${this.props.tagId}_sortBy`}
|
||||||
>
|
>
|
||||||
{_t("A-Z")}
|
{_t("A-Z")}
|
||||||
</StyledRadioButton>
|
</StyledMenuItemRadio>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<div>
|
||||||
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Unread rooms")}</div>
|
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Unread rooms")}</div>
|
||||||
<StyledCheckbox
|
<StyledMenuItemCheckbox
|
||||||
onChange={this.onUnreadFirstChanged}
|
onChange={this.onUnreadFirstChanged}
|
||||||
checked={isUnreadFirst}
|
checked={isUnreadFirst}
|
||||||
>
|
>
|
||||||
{_t("Always show first")}
|
{_t("Always show first")}
|
||||||
</StyledCheckbox>
|
</StyledMenuItemCheckbox>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<div>
|
||||||
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Show")}</div>
|
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Show")}</div>
|
||||||
<StyledCheckbox
|
<StyledMenuItemCheckbox
|
||||||
onChange={this.onMessagePreviewChanged}
|
onChange={this.onMessagePreviewChanged}
|
||||||
checked={this.props.layout.showPreviews}
|
checked={this.props.layout.showPreviews}
|
||||||
>
|
>
|
||||||
{_t("Message preview")}
|
{_t("Message preview")}
|
||||||
</StyledCheckbox>
|
</StyledMenuItemCheckbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
|
@ -26,7 +26,13 @@ import dis from '../../../dispatcher/dispatcher';
|
|||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/ContextMenu";
|
import {
|
||||||
|
ContextMenu,
|
||||||
|
ContextMenuButton,
|
||||||
|
MenuItemRadio,
|
||||||
|
MenuItemCheckbox,
|
||||||
|
MenuItem,
|
||||||
|
} from "../../structures/ContextMenu";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
||||||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||||
@ -328,20 +334,24 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||||||
<ContextMenu {...contextMenuBelow(this.state.generalMenuPosition)} onFinished={this.onCloseGeneralMenu}>
|
<ContextMenu {...contextMenuBelow(this.state.generalMenuPosition)} onFinished={this.onCloseGeneralMenu}>
|
||||||
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
<div className="mx_IconizedContextMenu mx_IconizedContextMenu_compact mx_RoomTile2_contextMenu">
|
||||||
<div className="mx_IconizedContextMenu_optionList">
|
<div className="mx_IconizedContextMenu_optionList">
|
||||||
<AccessibleButton onClick={(e) => this.onTagRoom(e, DefaultTagID.Favourite)}>
|
<MenuItemCheckbox
|
||||||
|
onClick={(e) => this.onTagRoom(e, DefaultTagID.Favourite)}
|
||||||
|
active={false} // TODO: https://github.com/vector-im/riot-web/issues/14283
|
||||||
|
label={_t("Favourite")}
|
||||||
|
>
|
||||||
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconStar" />
|
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconStar" />
|
||||||
<span className="mx_IconizedContextMenu_label">{_t("Favourite")}</span>
|
<span className="mx_IconizedContextMenu_label">{_t("Favourite")}</span>
|
||||||
</AccessibleButton>
|
</MenuItemCheckbox>
|
||||||
<AccessibleButton onClick={this.onOpenRoomSettings}>
|
<MenuItem onClick={this.onOpenRoomSettings} label={_t("Settings")}>
|
||||||
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconSettings" />
|
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconSettings" />
|
||||||
<span className="mx_IconizedContextMenu_label">{_t("Settings")}</span>
|
<span className="mx_IconizedContextMenu_label">{_t("Settings")}</span>
|
||||||
</AccessibleButton>
|
</MenuItem>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_IconizedContextMenu_optionList mx_RoomTile2_contextMenu_redRow">
|
<div className="mx_IconizedContextMenu_optionList mx_RoomTile2_contextMenu_redRow">
|
||||||
<AccessibleButton onClick={this.onLeaveRoomClick}>
|
<MenuItem onClick={this.onLeaveRoomClick} label={_t("Leave Room")}>
|
||||||
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconSignOut" />
|
<span className="mx_IconizedContextMenu_icon mx_RoomTile2_iconSignOut" />
|
||||||
<span className="mx_IconizedContextMenu_label">{_t("Leave Room")}</span>
|
<span className="mx_IconizedContextMenu_label">{_t("Leave Room")}</span>
|
||||||
</AccessibleButton>
|
</MenuItem>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
|
Loading…
Reference in New Issue
Block a user