Room List Section Management#
Overview#
Room List Section Management in Element Web lets users organize rooms into custom sections (user-defined groups) alongside the built-in default sections (Favourites, Chats, Low Priority). The feature is exposed through a "Move to section" submenu in the per-room "More Options" context menu, built with the SubMenu component from @vector-im/compound-web.
Data Model & Persistence#
Custom section data is stored as two account-level settings (synced per user via SettingLevel.ACCOUNT):
RoomList.CustomSectionData— aRecord<CustomTag, CustomSection>mapping section tags to their metadata (tag,name, optionalspaceId). Default:{}.RoomList.OrderedCustomSections— aCustomTag[]array controlling display order. Default:[].
Both settings are defined in Settings.tsx and managed by the helper functions in apps/web/src/stores/room-list-v3/section.ts:
| Function | Purpose |
|---|---|
getCustomSectionData() | Reads and validates section metadata from settings |
getOrderedCustomSections() | Returns ordered section tag list, filtering unknown tags |
createSection() | Creates a new section with a unique element.io.section.<uuid> tag |
editSection() | Renames a section |
deleteSection() | Removes a section from both settings |
reorderSection() | Updates section order |
Section ordering follows a pinned pattern: Favourites always appears at the top, Low Priority at the bottom, and custom sections + Chats are reorderable in between .
"Move to Section" UI#
The "Move to Section" submenu lives inside RoomListItemMoreOptionsMenu.tsx. It renders only when snapshot.areSectionsEnabled is true , using compound-web's SubMenu component with a MenuItem trigger .
Key behaviors:
- Section items show a
CheckIconwhen the room is already in that section , toggled viavm.onToggleSection(section.tag). - A "New section" item always appears at the bottom of the submenu, calling
vm.onCreateSection. - A separator before "New section" is only rendered when custom sections exist (
hasSections) . - A "Remove from section" action appears below the submenu when the room is already in a section (
isInSection), callingvm.onRemoveFromSection. Added in PR #33733. - Default sections (Favourites, Low Priority, Chats) are excluded from the submenu to prevent duplication with their existing toggle items in the main menu. This filtering was introduced in PR #33278.
- Long section names are truncated via a
.sectionLabelCSS class (max-width: 200px,text-overflow: ellipsis) inRoomListItemMoreOptionsMenu.module.css.
View Model: RoomListItemViewModel#
RoomListItemViewModel.ts is the central orchestrator for section state in per-room context menus:
- Snapshot field
sections: an array of{ tag, name, isSelected }objects derived bybuildSections(), which checksroom.tagsto computeisSelectedper section. - Caching (
availableSections): The expensivegetCustomSectionData()settings read is cached in a privateavailableSectionsfield (computed once in the constructor).buildSections()only derivesisSelectedfromroom.tagson each snapshot rebuild. The cache is invalidated on settings change. Introduced in PR #34102. - Settings watchers: The VM subscribes to both
RoomList.OrderedCustomSections(order changes) andRoomList.CustomSectionData(creation/rename/deletion), triggering a recompute ofavailableSections.
The RoomListSectionHeaderViewModel also subscribes to RoomList.CustomSectionData to update section header titles reactively .
Key Source Files#
| File | Role |
|---|---|
RoomListItemMoreOptionsMenu.tsx | UI: SubMenu rendering and "Move to section" interactions |
RoomListItemViewModel.ts | VM: section state, caching, toggle/remove actions |
section.ts | Persistence: CRUD helpers for custom section settings |
RoomListStoreV3.ts | Store: section ordering and loading |
Settings.tsx | Settings definitions for CustomSectionData and OrderedCustomSections |
RoomListSectionHeaderViewModel.ts | VM: reactive section header title updates |