diff --git a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss index ee228ec262e..bbe2bb575ee 100644 --- a/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss +++ b/res/css/views/rooms/RoomListPanel/_RoomListItemView.pcss @@ -18,10 +18,6 @@ all: unset; cursor: pointer; - &:hover { - background-color: var(--cpd-color-bg-action-secondary-hovered); - } - .mx_RoomListItemView_container { padding-left: var(--cpd-space-2x); font: var(--cpd-font-body-md-regular); @@ -44,12 +40,12 @@ } } -.mx_RoomListItemView_menu_open { +.mx_RoomListItemView_hover { background-color: var(--cpd-color-bg-action-secondary-hovered); +} - .mx_RoomListItemView_content { - padding-right: var(--cpd-space-1-5x); - } +.mx_RoomListItemView_menu_open .mx_RoomListItemView_content { + padding-right: var(--cpd-space-1-5x); } .mx_RoomListItemView_selected { diff --git a/src/components/views/rooms/RoomListPanel/RoomList.tsx b/src/components/views/rooms/RoomListPanel/RoomList.tsx index 628723246fc..80fb82220c7 100644 --- a/src/components/views/rooms/RoomListPanel/RoomList.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomList.tsx @@ -5,8 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ -import React, { useCallback, type JSX } from "react"; -import { AutoSizer, List, type ListRowProps } from "react-virtualized"; +import React, { useCallback, type JSX, useState, useEffect } from "react"; +import { ArrowKeyStepper, AutoSizer, List, type ListRowProps } from "react-virtualized"; import { type RoomListViewState } from "../../../viewmodels/roomlist/RoomListViewModel"; import { _t } from "../../../../languageHandler"; @@ -23,11 +23,22 @@ interface RoomListProps { * A virtualized list of rooms. */ export function RoomList({ vm: { rooms, activeIndex } }: RoomListProps): JSX.Element { + const [focusedIndex, setFocusedIndex] = useState(activeIndex); + useEffect(() => { + setFocusedIndex(activeIndex); + }, [activeIndex]); + const roomRendererMemoized = useCallback( ({ key, index, style }: ListRowProps) => ( - + ), - [rooms, activeIndex], + [rooms, activeIndex, focusedIndex], ); // The first div is needed to make the virtualized list take all the remaining space and scroll correctly @@ -35,16 +46,30 @@ export function RoomList({ vm: { rooms, activeIndex } }: RoomListProps): JSX.Ele
{({ height, width }) => ( - + isControlled={true} + scrollToRow={focusedIndex ?? 0} + onScrollToChange={({ scrollToRow }) => setFocusedIndex(scrollToRow)} + > + {({ onSectionRendered, scrollToRow }) => ( + + )} + )}
diff --git a/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx index 36839d75b08..ab91bd2d7d1 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListItemView.tsx @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -import React, { type JSX, memo, useState } from "react"; +import React, { type JSX, memo, useEffect, useRef, useState } from "react"; import { type Room } from "matrix-js-sdk/src/matrix"; import classNames from "classnames"; @@ -24,6 +24,10 @@ interface RoomListItemViewPropsProps extends React.HTMLAttributes(null); const vm = useRoomListItemViewModel(room); const [isHover, setIsHover] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); + + // Focus the button when the room is selected via keyboard navigation + useEffect(() => { + if (isKeyboardSelected) { + ref.current?.focus(); + } else { + ref.current?.blur(); + } + }, [isKeyboardSelected]); + // The compound menu in RoomListItemMenuView needs to be rendered when the hover menu is shown // Using display: none; and then display:flex when hovered in CSS causes the menu to be misaligned - const showHoverDecoration = (isMenuOpen || isHover) && vm.showHoverMenu; + const showHoverDecoration = isMenuOpen || isHover; + const showHoverMenu = showHoverDecoration && vm.showHoverMenu; - const isNotificationDecorationVisible = !showHoverDecoration && vm.showNotificationDecoration; + const isInvitation = vm.notificationState.invited; + const isNotificationDecorationVisible = isInvitation || (!showHoverDecoration && vm.showNotificationDecoration); return (