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

Allow filtering room list during treeview navigation #7219

Merged
merged 3 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/accessibility/RovingTabIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,14 @@ export const reducer = (state: IState, action: IAction) => {

if (state.refs.splice(oldIndex, 1)[0] === state.activeRef) {
// we just removed the active ref, need to replace it
// pick the ref which is now in the index the old ref was in
const len = state.refs.length;
state.activeRef = oldIndex >= len ? state.refs[len - 1] : state.refs[oldIndex];
// pick the ref closest to the index the old ref was in
if (oldIndex >= state.refs.length) {
state.activeRef = findSiblingElement(state.refs, state.refs.length - 1, true);
} else {
state.activeRef = findSiblingElement(state.refs, oldIndex)
|| findSiblingElement(state.refs, oldIndex, true);
}
state.activeRef?.current?.focus();
}

// update the refs list
Expand Down
15 changes: 15 additions & 0 deletions src/components/structures/LeftPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"
import UIStore from "../../stores/UIStore";
import { findSiblingElement, IState as IRovingTabIndexState } from "../../accessibility/RovingTabIndex";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { Key } from "../../Keyboard";

interface IProps {
isMinimized: boolean;
Expand Down Expand Up @@ -304,6 +305,19 @@ export default class LeftPanel extends React.Component<IProps, IState> {
}
};

private onRoomListKeydown = (ev: React.KeyboardEvent) => {
// we cannot handle Space as that is an activation key for all focusable elements in this widget
if (ev.key.length === 1) {
ev.preventDefault();
ev.stopPropagation();
this.roomSearchRef.current?.appendChar(ev.key);
} else if (ev.key === Key.BACKSPACE) {
ev.preventDefault();
ev.stopPropagation();
this.roomSearchRef.current?.backspace();
}
};

private selectRoom = () => {
const firstRoom = this.listContainerRef.current.querySelector<HTMLDivElement>(".mx_RoomTile");
if (firstRoom) {
Expand Down Expand Up @@ -411,6 +425,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
// Firefox sometimes makes this element focusable due to
// overflow:scroll;, so force it out of tab order.
tabIndex={-1}
onKeyDown={this.onRoomListKeydown}
>
{ roomList }
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/components/structures/RoomSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,16 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
</div>
);
}

public appendChar(char: string): void {
this.setState({
query: this.state.query + char,
});
}

public backspace(): void {
this.setState({
query: this.state.query.substring(0, this.state.query.length - 1),
});
}
}
5 changes: 5 additions & 0 deletions test/accessibility/RovingTabIndex-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ const button2 = <Button key={2}>b</Button>;
const button3 = <Button key={3}>c</Button>;
const button4 = <Button key={4}>d</Button>;

// mock offsetParent
Object.defineProperty(HTMLElement.prototype, "offsetParent", {
get() { return this.parentNode; },
});

describe("RovingTabIndex", () => {
it("RovingTabIndexProvider renders children as expected", () => {
const wrapper = mount(<RovingTabIndexProvider>
Expand Down