diff --git a/cypress/e2e/integration-manager/get-openid-token.spec.ts b/cypress/e2e/integration-manager/get-openid-token.spec.ts index c1026a5787..b2dcb9146a 100644 --- a/cypress/e2e/integration-manager/get-openid-token.spec.ts +++ b/cypress/e2e/integration-manager/get-openid-token.spec.ts @@ -59,7 +59,7 @@ const INTEGRATION_MANAGER_HTML = ` `; function openIntegrationManager() { - cy.findByRole("tab", { name: "Room info" }).click(); + cy.findByRole("button", { name: "Room info" }).click(); cy.findByRole("button", { name: "Add widgets, bridges & bots" }).click(); } diff --git a/cypress/e2e/integration-manager/kick.spec.ts b/cypress/e2e/integration-manager/kick.spec.ts index 4b29be4b23..7075c1c199 100644 --- a/cypress/e2e/integration-manager/kick.spec.ts +++ b/cypress/e2e/integration-manager/kick.spec.ts @@ -62,7 +62,7 @@ const INTEGRATION_MANAGER_HTML = ` `; function openIntegrationManager() { - cy.findByRole("tab", { name: "Room info" }).click(); + cy.findByRole("button", { name: "Room info" }).click(); cy.findByRole("button", { name: "Add widgets, bridges & bots" }).click(); } diff --git a/src/accessibility/RovingTabIndex.tsx b/src/accessibility/RovingTabIndex.tsx index 7b8cb7ede5..1963459835 100644 --- a/src/accessibility/RovingTabIndex.tsx +++ b/src/accessibility/RovingTabIndex.tsx @@ -156,6 +156,7 @@ export const reducer: Reducer = (state: IState, action: IAction }; interface IProps { + handleLoop?: boolean; handleHomeEnd?: boolean; handleUpDown?: boolean; handleLeftRight?: boolean; @@ -167,6 +168,7 @@ export const findSiblingElement = ( refs: RefObject[], startIndex: number, backwards = false, + loop = false, ): RefObject | undefined => { if (backwards) { for (let i = startIndex; i < refs.length && i >= 0; i--) { @@ -174,12 +176,18 @@ export const findSiblingElement = ( return refs[i]; } } + if (loop) { + return findSiblingElement(refs.slice(startIndex + 1), refs.length - 1, true, false); + } } else { for (let i = startIndex; i < refs.length && i >= 0; i++) { if (refs[i].current?.offsetParent !== null) { return refs[i]; } } + if (loop) { + return findSiblingElement(refs.slice(0, startIndex), 0, false, false); + } } }; @@ -188,6 +196,7 @@ export const RovingTabIndexProvider: React.FC = ({ handleHomeEnd, handleUpDown, handleLeftRight, + handleLoop, onKeyDown, }) => { const [state, dispatch] = useReducer>(reducer, { @@ -252,7 +261,7 @@ export const RovingTabIndexProvider: React.FC = ({ handled = true; if (context.state.refs.length > 0) { const idx = context.state.refs.indexOf(context.state.activeRef!); - focusRef = findSiblingElement(context.state.refs, idx + 1); + focusRef = findSiblingElement(context.state.refs, idx + 1, false, handleLoop); } } break; @@ -266,7 +275,7 @@ export const RovingTabIndexProvider: React.FC = ({ handled = true; if (context.state.refs.length > 0) { const idx = context.state.refs.indexOf(context.state.activeRef!); - focusRef = findSiblingElement(context.state.refs, idx - 1, true); + focusRef = findSiblingElement(context.state.refs, idx - 1, true, handleLoop); } } break; @@ -289,7 +298,7 @@ export const RovingTabIndexProvider: React.FC = ({ }); } }, - [context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight], + [context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight, handleLoop], ); return ( diff --git a/src/components/structures/TabbedView.tsx b/src/components/structures/TabbedView.tsx index 0d3d01041b..1efada7143 100644 --- a/src/components/structures/TabbedView.tsx +++ b/src/components/structures/TabbedView.tsx @@ -22,9 +22,9 @@ import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../languageHandler"; import AutoHideScrollbar from "./AutoHideScrollbar"; -import AccessibleButton from "../views/elements/AccessibleButton"; import { PosthogScreenTracker, ScreenName } from "../../PosthogTrackers"; import { NonEmptyArray } from "../../@types/common"; +import { RovingAccessibleButton, RovingTabIndexProvider } from "../../accessibility/RovingTabIndex"; /** * Represents a tab for the TabbedView. @@ -98,9 +98,10 @@ export default class TabbedView extends React.Component { } private renderTabLabel(tab: Tab): JSX.Element { - let classes = "mx_TabbedView_tabLabel "; - - if (this.state.activeTabId === tab.id) classes += "mx_TabbedView_tabLabel_active"; + const isActive = this.state.activeTabId === tab.id; + const classes = classNames("mx_TabbedView_tabLabel", { + mx_TabbedView_tabLabel_active: isActive, + }); let tabIcon: JSX.Element | undefined; if (tab.icon) { @@ -108,24 +109,35 @@ export default class TabbedView extends React.Component { } const onClickHandler = (): void => this.setActiveTab(tab); + const id = this.getTabId(tab); const label = _t(tab.label); return ( - {tabIcon} - {label} - + + {label} + + ); } + private getTabId(tab: Tab): string { + return `mx_tabpanel_${tab.id}`; + } + private renderTabPanel(tab: Tab): React.ReactNode { + const id = this.getTabId(tab); return ( -
+
{tab.body}
); @@ -147,7 +159,23 @@ export default class TabbedView extends React.Component { return (
{screenName && } -
{labels}
+ + {({ onKeyDownHandler }) => ( +
+ {labels} +
+ )} +
{panel}
); diff --git a/src/components/views/right_panel/HeaderButton.tsx b/src/components/views/right_panel/HeaderButton.tsx index 6d6872bc1e..03106face2 100644 --- a/src/components/views/right_panel/HeaderButton.tsx +++ b/src/components/views/right_panel/HeaderButton.tsx @@ -54,8 +54,7 @@ export default class HeaderButton extends React.Component { return ( extends React.Component - {this.renderButtons()} -
- ); + return
{this.renderButtons()}
; } } diff --git a/test/components/structures/__snapshots__/TabbedView-test.tsx.snap b/test/components/structures/__snapshots__/TabbedView-test.tsx.snap index 77ead236a3..acd6a4bae6 100644 --- a/test/components/structures/__snapshots__/TabbedView-test.tsx.snap +++ b/test/components/structures/__snapshots__/TabbedView-test.tsx.snap @@ -6,12 +6,16 @@ exports[` renders tabs 1`] = ` class="mx_TabbedView mx_TabbedView_tabsOnLeft" >
renders tabs 1`] = ` /> General
Labs
Security
Settings tabs renders default tabs correctly 1`] = ` NodeList [
General
,
Security & Privacy
,
Roles & Permissions
,
Notifications
,
Poll history diff --git a/test/components/views/dialogs/__snapshots__/UserSettingsDialog-test.tsx.snap b/test/components/views/dialogs/__snapshots__/UserSettingsDialog-test.tsx.snap index fb887a304d..4c1e9b20f9 100644 --- a/test/components/views/dialogs/__snapshots__/UserSettingsDialog-test.tsx.snap +++ b/test/components/views/dialogs/__snapshots__/UserSettingsDialog-test.tsx.snap @@ -3,9 +3,11 @@ exports[` renders tabs correctly 1`] = ` NodeList [
General
,
Appearance
,
Notifications
,
Preferences
,
Keyboard
,
Sidebar
,
Security & Privacy
,
Labs
,
Help & About