ARIA Accessibility improvements (#10674)

* Add missing aria-expanded attributes

* Improve autoComplete for phone numbers & email addresses

* Fix room summary card heading order

* Fix missing label on timeline search field

* Use appropriate semantic elements for dropdown listbox

* Use semantic list elements in keyboard settings tab

* Use semantic list elements in spotlight

* Fix types and i18n

* Improve types

* Update tests

* Add snapshot test
This commit is contained in:
Michael Telatynski 2023-04-20 18:13:30 +01:00 committed by GitHub
parent 2da52372d4
commit 782060a26e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 611 additions and 157 deletions

View file

@ -155,6 +155,11 @@ limitations under the License.
overflow-y: auto;
padding: $spacing-16;
ul {
padding: 0;
margin: 0;
}
.mx_SpotlightDialog_section {
> h4,
> .mx_SpotlightDialog_sectionHeader > h4 {

View file

@ -151,10 +151,11 @@ limitations under the License.
margin-right: $spacing-12;
}
> h1 {
> h2 {
color: $tertiary-content;
font-size: $font-12px;
font-weight: 500;
margin: $spacing-12;
}
.mx_BaseCard_Button {

View file

@ -19,8 +19,9 @@ limitations under the License.
text-align: center;
margin-top: $spacing-20;
h2 {
h1 {
margin: $spacing-12 0 $spacing-4;
font-weight: $font-semi-bold;
}
.mx_RoomSummaryCard_alias {
@ -30,7 +31,7 @@ limitations under the License.
text-overflow: ellipsis;
}
h2,
h1,
.mx_RoomSummaryCard_alias {
display: -webkit-box;
-webkit-line-clamp: 2;

View file

@ -16,6 +16,11 @@ limitations under the License.
*/
.mx_KeyboardUserSettingsTab .mx_SettingsTab_section {
ul {
margin: 0;
padding: 0;
}
.mx_KeyboardShortcut_shortcutRow,
.mx_KeyboardShortcut {
display: flex;

View file

@ -164,6 +164,7 @@ export default class CountryDropdown extends React.Component<IProps, IState> {
searchEnabled={true}
disabled={this.props.disabled}
label={_t("Country Dropdown")}
autoComplete="tel-country-code"
>
{options}
</Dropdown>

View file

@ -15,18 +15,21 @@ limitations under the License.
*/
import classNames from "classnames";
import React, { ComponentProps, ReactNode } from "react";
import React, { ReactNode, RefObject } from "react";
import { RovingAccessibleButton } from "../../../../accessibility/roving/RovingAccessibleButton";
import { useRovingTabIndex } from "../../../../accessibility/RovingTabIndex";
import AccessibleButton from "../../elements/AccessibleButton";
import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton";
interface OptionProps extends ComponentProps<typeof RovingAccessibleButton> {
interface OptionProps {
inputRef?: RefObject<HTMLLIElement>;
endAdornment?: ReactNode;
id?: string;
className?: string;
onClick: ((ev: ButtonEvent) => void) | null;
}
export const Option: React.FC<OptionProps> = ({ inputRef, children, endAdornment, className, ...props }) => {
const [onFocus, isActive, ref] = useRovingTabIndex(inputRef);
const [onFocus, isActive, ref] = useRovingTabIndex<HTMLLIElement>(inputRef);
return (
<AccessibleButton
{...props}
@ -36,6 +39,7 @@ export const Option: React.FC<OptionProps> = ({ inputRef, children, endAdornment
tabIndex={-1}
aria-selected={isActive}
role="option"
element="li"
>
{children}
<div className="mx_SpotlightDialog_option--endAdornment">

View file

@ -30,7 +30,7 @@ interface IMenuOptionProps {
highlighted?: boolean;
dropdownKey: string;
id?: string;
inputRef?: Ref<HTMLDivElement>;
inputRef?: Ref<HTMLLIElement>;
onClick(dropdownKey: string): void;
onMouseEnter(dropdownKey: string): void;
}
@ -57,7 +57,7 @@ class MenuOption extends React.Component<IMenuOptionProps> {
});
return (
<div
<li
id={this.props.id}
className={optClasses}
onClick={this.onClick}
@ -67,7 +67,7 @@ class MenuOption extends React.Component<IMenuOptionProps> {
ref={this.props.inputRef}
>
{this.props.children}
</div>
</li>
);
}
}
@ -78,6 +78,7 @@ export interface DropdownProps {
label: string;
value?: string;
className?: string;
autoComplete?: string;
children: NonEmptyArray<ReactElement & { key: string }>;
// negative for consistency with HTML
disabled?: boolean;
@ -318,21 +319,21 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
});
if (!options?.length) {
return [
<div key="0" className="mx_Dropdown_option" role="option" aria-selected={false}>
<li key="0" className="mx_Dropdown_option" role="option" aria-selected={false}>
{_t("No results")}
</div>,
</li>,
];
}
return options;
}
public render(): React.ReactNode {
let currentValue;
let currentValue: JSX.Element | undefined;
const menuStyle: CSSProperties = {};
if (this.props.menuWidth) menuStyle.width = this.props.menuWidth;
let menu;
let menu: JSX.Element | undefined;
if (this.state.expanded) {
if (this.props.searchEnabled) {
currentValue = (
@ -340,6 +341,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
id={`${this.props.id}_input`}
type="text"
autoFocus={true}
autoComplete={this.props.autoComplete}
className="mx_Dropdown_option"
onChange={this.onInputChange}
value={this.state.searchQuery}
@ -355,9 +357,9 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
);
}
menu = (
<div className="mx_Dropdown_menu" style={menuStyle} role="listbox" id={`${this.props.id}_listbox`}>
<ul className="mx_Dropdown_menu" style={menuStyle} role="listbox" id={`${this.props.id}_listbox`}>
{this.getMenuOptions()}
</div>
</ul>
);
}

View file

@ -47,7 +47,7 @@ interface IGroupProps {
export const Group: React.FC<IGroupProps> = ({ className, title, children }) => {
return (
<div className={classNames("mx_BaseCard_Group", className)}>
<h1>{title}</h1>
<h2>{title}</h2>
{children}
</div>
);

View file

@ -318,7 +318,7 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, permalinkCreator, onClose })
/>
</div>
<RoomName room={room}>{(name) => <h2 title={name}>{name}</h2>}</RoomName>
<RoomName room={room}>{(name) => <h1 title={name}>{name}</h1>}</RoomName>
<div className="mx_RoomSummaryCard_alias" title={alias}>
{alias}
</div>

View file

@ -121,6 +121,9 @@ export default class SearchBar extends React.Component<IProps, IState> {
type="text"
autoFocus={true}
placeholder={_t("Search…")}
aria-label={
this.state.scope === SearchScope.Room ? _t("Search this room") : _t("Search all rooms")
}
onKeyDown={this.onSearchChange}
/>
<AccessibleButton

View file

@ -280,7 +280,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
<Field
type="text"
label={_t("Email Address")}
autoComplete="off"
autoComplete="email"
disabled={this.state.verifying}
value={this.state.newEmailAddress}
onChange={this.onChangeNewEmailAddress}

View file

@ -310,7 +310,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
<Field
type="text"
label={_t("Phone Number")}
autoComplete="off"
autoComplete="tel-national"
disabled={this.state.verifying}
prefixComponent={phoneCountry}
value={this.state.newPhoneNumber}

View file

@ -443,6 +443,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
onClick={this.toggleAdvancedSection}
kind="link"
className="mx_SettingsTab_showAdvanced"
aria-expanded={this.state.showAdvancedSection}
>
{this.state.showAdvancedSection ? _t("Hide advanced") : _t("Show advanced")}
</AccessibleButton>

View file

@ -88,7 +88,11 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
const brand = SdkConfig.get().brand;
const toggle = (
<AccessibleButton kind="link" onClick={() => this.setState({ showAdvanced: !this.state.showAdvanced })}>
<AccessibleButton
kind="link"
onClick={() => this.setState({ showAdvanced: !this.state.showAdvanced })}
aria-expanded={this.state.showAdvanced}
>
{this.state.showAdvanced ? _t("Hide advanced") : _t("Show advanced")}
</AccessibleButton>
);

View file

@ -41,10 +41,10 @@ const KeyboardShortcutRow: React.FC<IKeyboardShortcutRowProps> = ({ name }) => {
if (!displayName || !value) return null;
return (
<div className="mx_KeyboardShortcut_shortcutRow">
<li className="mx_KeyboardShortcut_shortcutRow">
{displayName}
<KeyboardShortcut value={value} />
</div>
</li>
);
};
@ -59,12 +59,12 @@ const KeyboardShortcutSection: React.FC<IKeyboardShortcutSectionProps> = ({ cate
return (
<div className="mx_SettingsTab_section" key={categoryName}>
<div className="mx_SettingsTab_subheading">{_t(category.categoryLabel)}</div>
<div>
<ul>
{" "}
{category.settingNames.map((shortcutName) => {
return <KeyboardShortcutRow key={shortcutName} name={shortcutName} />;
})}{" "}
</div>
</ul>
</div>
);
};

View file

@ -134,6 +134,7 @@ const QuickSettingsButton: React.FC<{
title={_t("Quick settings")}
inputRef={handle}
forceHide={!isPanelCollapsed}
aria-expanded={!isPanelCollapsed}
>
{!isPanelCollapsed ? _t("Settings") : null}
</AccessibleTooltipButton>

View file

@ -97,6 +97,7 @@ const SpaceSettingsVisibilityTab: React.FC<IProps> = ({ matrixClient: cli, space
onClick={toggleAdvancedSection}
kind="link"
className="mx_SettingsTab_showAdvanced"
aria-expanded={showAdvancedSection}
>
{showAdvancedSection ? _t("Hide advanced") : _t("Show advanced")}
</AccessibleButton>

View file

@ -2141,6 +2141,8 @@
"This Room": "This Room",
"All Rooms": "All Rooms",
"Search…": "Search…",
"Search this room": "Search this room",
"Search all rooms": "Search all rooms",
"Failed to connect to integration manager": "Failed to connect to integration manager",
"You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled",
"Add some now": "Add some now",

View file

@ -174,7 +174,7 @@ describe("Spotlight Dialog", () => {
expect(filterChip.innerHTML).toContain("Public rooms");
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("div.mx_SpotlightDialog_option");
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
expect(options[0].innerHTML).toContain(testPublicRoom.name);
});
@ -196,7 +196,7 @@ describe("Spotlight Dialog", () => {
expect(filterChip.innerHTML).toContain("People");
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("div.mx_SpotlightDialog_option");
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
});
@ -242,7 +242,7 @@ describe("Spotlight Dialog", () => {
expect(filterChip.innerHTML).toContain("Public rooms");
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("div.mx_SpotlightDialog_option");
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
expect(options[0]!.innerHTML).toContain(testPublicRoom.name);
@ -265,7 +265,7 @@ describe("Spotlight Dialog", () => {
expect(filterChip.innerHTML).toContain("People");
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("div.mx_SpotlightDialog_option");
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
});
@ -324,7 +324,7 @@ describe("Spotlight Dialog", () => {
await flushPromisesWithFakeTimers();
const content = document.querySelector("#mx_SpotlightDialog_content")!;
options = content.querySelectorAll("div.mx_SpotlightDialog_option");
options = content.querySelectorAll("li.mx_SpotlightDialog_option");
});
it("should find Rooms", () => {
@ -350,7 +350,7 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
const options = document.querySelectorAll("div.mx_SpotlightDialog_option");
const options = document.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
@ -372,7 +372,7 @@ describe("Spotlight Dialog", () => {
await flushPromisesWithFakeTimers();
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("div.mx_SpotlightDialog_option");
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
expect(options[0].innerHTML).toContain(testPublicRoom.name);

View file

@ -1,12 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<FilterDropdown /> renders dropdown options in menu 1`] = `
<div
<ul
class="mx_Dropdown_menu"
id="test_listbox"
role="listbox"
>
<div
<li
aria-selected="true"
class="mx_Dropdown_option mx_Dropdown_option_highlight"
id="test__one"
@ -25,8 +25,8 @@ exports[`<FilterDropdown /> renders dropdown options in menu 1`] = `
Option one
</span>
</div>
</div>
<div
</li>
<li
aria-selected="false"
class="mx_Dropdown_option"
id="test__two"
@ -47,8 +47,8 @@ exports[`<FilterDropdown /> renders dropdown options in menu 1`] = `
with description
</span>
</div>
</div>
</div>
</li>
</ul>
`;
exports[`<FilterDropdown /> renders selected option 1`] = `

View file

@ -44,11 +44,11 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
tabindex="0"
/>
</div>
<h2
<h1
title="!room:domain.org"
>
!room:domain.org
</h2>
</h1>
<div
class="mx_RoomSummaryCard_alias"
title=""
@ -61,9 +61,9 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
<div
class="mx_BaseCard_Group mx_RoomSummaryCard_aboutGroup"
>
<h1>
<h2>
About
</h1>
</h2>
<div
class="mx_AccessibleButton mx_BaseCard_Button mx_RoomSummaryCard_Button mx_RoomSummaryCard_icon_people"
role="button"
@ -116,9 +116,9 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
<div
class="mx_BaseCard_Group mx_RoomSummaryCard_appsGroup"
>
<h1>
<h2>
Widgets
</h1>
</h2>
<div
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link"
role="button"

View file

@ -0,0 +1,37 @@
/*
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { render } from "@testing-library/react";
import React from "react";
import AppearanceUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/AppearanceUserSettingsTab";
import { stubClient } from "../../../../../test-utils";
// Fake random strings to give a predictable snapshot
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: () => "abdefghi",
}));
describe("AppearanceUserSettingsTab", () => {
beforeEach(() => {
stubClient();
});
it("should render", () => {
const { asFragment } = render(<AppearanceUserSettingsTab />);
expect(asFragment()).toMatchSnapshot();
});
});

View file

@ -0,0 +1,386 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AppearanceUserSettingsTab should render 1`] = `
<DocumentFragment>
<div
class="mx_SettingsTab mx_AppearanceUserSettingsTab"
>
<div
class="mx_SettingsTab_heading"
>
Customise your appearance
</div>
<div
class="mx_SettingsTab_subsectionText"
>
Appearance Settings only affect this Element session.
</div>
<div
class="mx_SettingsTab_section mx_ThemeChoicePanel"
>
<span
class="mx_SettingsTab_subheading"
>
Theme
</span>
<div
class="mx_ThemeSelectors"
data-testid="theme-choice-panel-selectors"
>
<label
class="mx_StyledRadioButton mx_ThemeSelector_light mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined"
>
<input
disabled=""
id="theme-light"
name="theme"
type="radio"
value="light"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Light
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
<label
class="mx_StyledRadioButton mx_ThemeSelector_dark mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined"
>
<input
disabled=""
id="theme-dark"
name="theme"
type="radio"
value="dark"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Dark
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</div>
</div>
<div
class="mx_SettingsTab_section mx_LayoutSwitcher"
>
<span
class="mx_SettingsTab_subheading"
>
Message layout
</span>
<div
class="mx_LayoutSwitcher_RadioButtons"
>
<label
class="mx_LayoutSwitcher_RadioButton"
>
<div
class="mx_LayoutSwitcher_RadioButton_preview mx_IRCLayout mx_EventTilePreview_loader"
>
<div
class="mx_Spinner"
>
<div
aria-label="Loading…"
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
</div>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
name="layout"
type="radio"
value="irc"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
IRC (Experimental)
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</label>
<label
class="mx_LayoutSwitcher_RadioButton mx_LayoutSwitcher_RadioButton_selected"
>
<div
class="mx_LayoutSwitcher_RadioButton_preview mx_EventTilePreview_loader"
>
<div
class="mx_Spinner"
>
<div
aria-label="Loading…"
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
</div>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled mx_StyledRadioButton_checked"
>
<input
checked=""
name="layout"
type="radio"
value="group"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Modern
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</label>
<label
class="mx_LayoutSwitcher_RadioButton"
>
<div
class="mx_LayoutSwitcher_RadioButton_preview mx_EventTilePreview_loader"
>
<div
class="mx_Spinner"
>
<div
aria-label="Loading…"
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
</div>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
name="layout"
type="radio"
value="bubble"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Message bubbles
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</label>
</div>
</div>
<div
class="mx_SettingsTab_section mx_FontScalingPanel"
>
<span
class="mx_SettingsTab_subheading"
>
Font size
</span>
<div
class="mx_FontScalingPanel_preview mx_EventTilePreview_loader"
>
<div
class="mx_Spinner"
>
<div
aria-label="Loading…"
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
</div>
<div
class="mx_FontScalingPanel_fontSlider"
>
<div
class="mx_FontScalingPanel_fontSlider_smallText"
>
Aa
</div>
<div
class="mx_Slider"
>
<input
aria-label="Font size"
autocomplete="off"
max="18"
min="13"
step="1"
type="range"
value="15"
/>
<output
class="mx_Slider_selection"
style="left: calc(2px + 40% + 1.2em - 0.96em);"
>
<span
class="mx_Slider_selection_label"
>
15
</span>
</output>
</div>
<div
class="mx_FontScalingPanel_fontSlider_largeText"
>
Aa
</div>
</div>
<span
class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
id="checkbox_abdefghi"
type="checkbox"
/>
<label
for="checkbox_abdefghi"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
Use custom size
</div>
</label>
</span>
<div
class="mx_Field mx_Field_input mx_FontScalingPanel_customFontSizeField"
>
<input
autocomplete="off"
disabled=""
id="font_size_field"
label="Font size"
placeholder="15"
type="number"
value="15"
/>
<label
for="font_size_field"
>
Font size
</label>
</div>
</div>
<div
class="mx_SettingsTab_section mx_AppearanceUserSettingsTab_Advanced"
>
<div
aria-expanded="false"
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link"
role="button"
tabindex="0"
>
Show advanced
</div>
</div>
<div
class="mx_SettingsTab_section mx_ImageSizePanel"
>
<span
class="mx_SettingsTab_subheading"
>
Image size in the timeline
</span>
<div
class="mx_ImageSizePanel_radios"
>
<label>
<div
class="mx_ImageSizePanel_size mx_ImageSizePanel_sizeDefault"
/>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled mx_StyledRadioButton_checked"
>
<input
checked=""
name="image_size"
type="radio"
value="normal"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Default
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</label>
<label>
<div
class="mx_ImageSizePanel_size mx_ImageSizePanel_sizeLarge"
/>
<label
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
>
<input
name="image_size"
type="radio"
value="large"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
>
Large
</div>
<div
class="mx_StyledRadioButton_spacer"
/>
</label>
</label>
</div>
</div>
</div>
</DocumentFragment>
`;

View file

@ -18,9 +18,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Composer
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Send message
@ -33,8 +33,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
New line
@ -53,8 +53,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle Bold
@ -73,8 +73,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle Italics
@ -93,8 +93,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle Quote
@ -119,8 +119,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle Link
@ -145,8 +145,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle Code Block
@ -165,8 +165,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Undo edit
@ -185,8 +185,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Redo edit
@ -205,8 +205,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to start of the composer
@ -225,8 +225,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to end of the composer
@ -245,8 +245,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Cancel replying to a message
@ -259,8 +259,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate to next message to edit
@ -273,8 +273,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate to previous message to edit
@ -287,8 +287,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate to next message in composer history
@ -313,8 +313,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate to previous message in composer history
@ -339,8 +339,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Send a sticker
@ -359,9 +359,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -371,9 +371,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Calls
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle microphone mute
@ -392,8 +392,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle webcam on/off
@ -412,9 +412,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -424,9 +424,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Room
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Search (must be enabled)
@ -445,8 +445,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Upload a file
@ -471,8 +471,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Dismiss read marker and jump to bottom
@ -485,8 +485,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to oldest unread message
@ -505,8 +505,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Scroll up in the timeline
@ -519,8 +519,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Scroll down in the timeline
@ -533,8 +533,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to first message
@ -553,8 +553,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to last message
@ -573,9 +573,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -585,9 +585,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Room List
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Select room from the room list
@ -600,8 +600,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Collapse room list section
@ -614,8 +614,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Expand room list section
@ -628,8 +628,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate down in the room list
@ -642,8 +642,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Navigate up in the room list
@ -656,9 +656,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -668,9 +668,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Accessibility
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Close dialog or context menu
@ -683,8 +683,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Activate selected button
@ -697,9 +697,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -709,9 +709,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Navigation
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle the top left menu
@ -730,8 +730,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle right panel
@ -750,8 +750,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Toggle space panel
@ -776,8 +776,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Open this settings tab
@ -796,8 +796,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Go to Home View
@ -822,8 +822,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Jump to room search
@ -842,8 +842,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Next unread room or DM
@ -868,8 +868,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Previous unread room or DM
@ -894,8 +894,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Next room or DM
@ -914,8 +914,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Previous room or DM
@ -934,9 +934,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
<div
class="mx_SettingsTab_section"
@ -946,9 +946,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
>
Autocomplete
</div>
<div>
<ul>
<div
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Cancel autocomplete
@ -961,8 +961,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Next autocomplete suggestion
@ -975,8 +975,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Previous autocomplete suggestion
@ -989,8 +989,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Complete
@ -1003,8 +1003,8 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
<div
</li>
<li
class="mx_KeyboardShortcut_shortcutRow"
>
Force complete
@ -1017,9 +1017,9 @@ exports[`KeyboardUserSettingsTab renders list of keyboard shortcuts 1`] = `
</kbd>
</div>
</div>
</li>
</div>
</ul>
</div>
</div>
</div>