feat: migrate the sidebar and side panel to `Item`

Merged
JU
2d ago
+7348-1608

Proposed changes (including videos or screenshots)

ARCH-2496
Migrates the Sidebar and Sidepanel components to the Item components, and applies the result to the sidebar, side panel and navbar search in the same PR.

It also makes the room search behave like the composer popups from #42820 when moving through it with a keyboard or a pointer: focus stays in the search field, one result is active at a time, the pointer and the arrow keys both move it, and the focus ring shows only when the keyboard picked it.

Room search after the arrow keys and then the pointer: develop keeps the ring on one result and the hover on another, this PR highlights one

Captured against open.rocket.chat with yarn dev:next, develop above and this PR below. Private room names are blurred.

Room search with keyboard then pointer, develop vs this PR

Fuselage

Renders the Sidebar and Sidepanel components with the Item family from RocketChat/fuselage#2281. The public rcx-sidebar-* classes stay in place.

  • SidebarItem, its parts and SidebarLink render with Item, ItemMedia, ItemIcon, ItemContent, ItemRow, ItemTitle, ItemDescription, ItemMeta and ItemActions.
  • New optional label prop on SidebarItemIcon names the icon for assistive technology.
  • SidebarGroupTitle, SidebarCollapseGroup and SidebarCollapseGroupMenu render as ItemGroupHeader, ItemGroup and ItemActions. The collapse group's list is named by its title. This keeps the restyled collapse group header from RocketChat/fuselage#2285.
  • Sidebar rows, links and the collapse group header use the md inset from the Item scale, set inside the components. It replaces the fixed 12px inset, and headers and rows line up.
  • SidebarItem can render as a container row: pass is='div' and put the new SidebarItemLink inside SidebarItemTitle. Only the title is the link, and it covers the whole row, so menus and buttons sit beside it instead of inside it. The new SidebarItemActions holds always-visible buttons, such as accepting or rejecting a call. SidebarItem also gets a highlighted prop. A div row drops href, target, rel and download. The default anchor row is unchanged.
  • SidebarItem forwards focused and focusVisible to Item, so a sidebar row can be a listbox's active option.
  • SidebarDivider renders as ItemDivider.
  • SidepanelList renders as an ItemGroup and SidepanelDivider as an ItemDivider, keeping the full-width line under SidepanelHeader.
  • Fix: SidebarCollapseGroup no longer passes its actions prop to the DOM.

Rocket.Chat

  • New navigation room rows are container rows (SidebarItem is='div' + SidebarItemLink): only the title is the link, and the menu and call buttons sit beside it in SidebarItemActions. Group headers use the bridged SidebarCollapseGroup, and the filters use Item parts.
  • Old sidebar rows render with the same RoomListItem; the Condensed, Medium and Extended templates are removed.
  • Navbar search rows use the bridged SidebarItem parts.
  • The room search keeps focus in the search field while the arrow keys move through the results, pointing at the active one with aria-activedescendant, as the combobox pattern expects. The result under the pointer becomes the one Enter opens.
  • Room icons are named for assistive technology (useRoomIconLabel), and UnreadBadge renders with Badge.

Issue(s)

Replaces RocketChat/fuselage#2295, and takes over the sidebar, side panel and navbar search parts of #42520.

Steps to test or reproduce

  • yarn workspace @rocket.chat/fuselage storybook: the Sidebar, SidebarItem and Sidepanel stories.
  • In the app, with both the old and the new navigation: room rows in every view mode, unread and selected rooms, group collapse, row menus, incoming call buttons, keyboard navigation between rows, and navbar search. Check with a keyboard and a screen reader.
  • In the room search, move through the results with the arrow keys and with the pointer: one result is highlighted at a time, Enter opens it, and typing keeps working while a result is active.

Further comments

Based on develop. The room search reuses useActiveDescendant, which landed with #42820.

The search commits sit on top, since they need the Item-based SidebarItem from this PR:

  1. feat(fuselage): SidebarItem forwards focused and focusVisible
  2. fix: the room search keeps focus on its combobox

Part of the Item migration, split by area:

  • #42818: options, selects, menus and member lists (merged)
  • #42820: composer popups and ItemMeta truncate (merged)
  • this PR: sidebar, side panel, and keyboard and pointer behaviour of the room search
  • #42832: lists that only use Item (independent)

Not changed here: the fuselage SidebarLink still renders its menu inside its anchor. Container rows are the way to keep menus and buttons out of the link.

Jest snapshots and the visual-regression baselines (arm64 image) were regenerated here. fuselage.api.md isn't part of this repository, so those changes were dropped.

Summary by CodeRabbit

  • New Features
    • Sidebar room rows now support condensed, medium, and extended layouts, with room titles linked separately from adjacent menus and call actions.
    • Room icons have accessible names, and incoming calls are identified for assistive technology.
    • Search keeps keyboard focus in the input while arrow keys navigate results. Enter opens the active result, including the row under the pointer.
  • Bug Fixes
    • Sidebar group controls support keyboard activation, and menus no longer trigger group collapsing.
    • Updated sidebar and side-panel layouts improve screen-reader labeling and accessibility.