Room list: add release announcement for sections (#33800)

* feat: add release announcement for sections

* test: update screenshot

* test: update tests

* test: add release annoucement utils to close it

* test: close release announcement in custom section tests

* test: update release announcement e2e test

* test: add more tests

* feat: update Ra labels

* test: update screenshot

* chore: remove stale screenshot
This commit is contained in:
Florian Duros
2026-06-19 12:06:58 +00:00
committed by GitHub
parent 43b9bc9458
commit 338c18df16
17 changed files with 185 additions and 47 deletions
@@ -67,6 +67,11 @@
"mentions_keywords": "Mentions and keywords",
"mute_room": "Mute room"
},
"release_announcement": {
"room_list_section_close": "Ok",
"room_list_section_description": " Group your chats into sections to keep conversations organised and easy to navigate.",
"room_list_section_title": "Introducing Sections"
},
"room": {
"context_menu": {
"title": "Room options"
@@ -32,6 +32,7 @@ const RoomListHeaderViewWrapperImpl = ({
toggleMessagePreview,
createSection,
collapseOrExpandSections,
closeSectionReleaseAnnouncement,
...rest
}: RoomListHeaderProps): JSX.Element => {
const vm = useMockedViewModel(rest, {
@@ -46,6 +47,7 @@ const RoomListHeaderViewWrapperImpl = ({
toggleMessagePreview,
createSection,
collapseOrExpandSections,
closeSectionReleaseAnnouncement,
});
return <RoomListHeaderView vm={vm} />;
};
@@ -68,6 +70,7 @@ const meta = {
toggleMessagePreview: fn(),
createSection: fn(),
collapseOrExpandSections: fn(),
closeSectionReleaseAnnouncement: fn(),
},
parameters: {
design: {
@@ -124,3 +127,30 @@ export const ExpandSections: Story = {
collapseSections: "expand",
},
};
export const DisplaySectionReleaseAnnouncement: Story = {
decorators: [
(Story) => (
<div style={{ width: "300px" }}>
<Story />
</div>
),
],
args: {
displaySectionReleaseAnnouncement: true,
},
parameters: {
a11y: {
config: {
rules: [
{
// compound-web's ReleaseAnnouncement renders its header as <h3>,
// which jumps from RoomListHeaderView's <h1> ("Rooms").
id: "heading-order",
enabled: false,
},
],
},
},
},
};
@@ -80,6 +80,10 @@ export interface RoomListHeaderViewSnapshot {
* If undefined, no icon are shown.
*/
collapseSections?: CollapseSectionsOption;
/**
* Whether to display the section release announcement
*/
displaySectionReleaseAnnouncement: boolean;
}
export interface RoomListHeaderViewActions {
@@ -127,6 +131,10 @@ export interface RoomListHeaderViewActions {
* Collapse or expand all sections in the room list depending on the current state.
*/
collapseOrExpandSections: () => void;
/**
* Close the section release announcement
*/
closeSectionReleaseAnnouncement: () => void;
}
/**
@@ -19,4 +19,5 @@ export const defaultSnapshot: RoomListHeaderViewSnapshot = {
isMessagePreviewEnabled: true,
useComposeIcon: true,
canCreateSection: true,
displaySectionReleaseAnnouncement: false,
};
@@ -6,7 +6,7 @@
*/
import React, { useState, type JSX } from "react";
import { IconButton, Menu, MenuItem } from "@vector-im/compound-web";
import { IconButton, Menu, MenuItem, ReleaseAnnouncement } from "@vector-im/compound-web";
import ComposeIcon from "@vector-im/compound-design-tokens/assets/web/icons/compose";
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call";
import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat";
@@ -37,7 +37,33 @@ interface ComposeMenuViewProps {
export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
const { translate: _t } = useI18n();
const [open, setOpen] = useState(false);
const { canCreateRoom, canCreateVideoRoom, canCreateSection, useComposeIcon } = useViewModel(vm);
const { canCreateRoom, canCreateVideoRoom, canCreateSection, useComposeIcon, displaySectionReleaseAnnouncement } =
useViewModel(vm);
// 28px button with a 20px icon
const button = (
<IconButton size="28px" style={{ padding: "4px" }} tooltip={_t("action|new_conversation")}>
{useComposeIcon ? (
<ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
) : (
<PlusIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
)}
</IconButton>
);
if (displaySectionReleaseAnnouncement) {
return (
<ReleaseAnnouncement
open={displaySectionReleaseAnnouncement}
onClick={vm.closeSectionReleaseAnnouncement}
header={_t("release_announcement|room_list_section_title")}
description={_t("release_announcement|room_list_section_description")}
closeLabel={_t("release_announcement|room_list_section_close")}
>
{button}
</ReleaseAnnouncement>
);
}
return (
<Menu
@@ -46,16 +72,7 @@ export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
showTitle={false}
title={_t("action|open_menu")}
align="start"
trigger={
// 28px button with a 20px icon
<IconButton size="28px" style={{ padding: "4px" }} tooltip={_t("action|new_conversation")}>
{useComposeIcon ? (
<ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
) : (
<PlusIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
)}
</IconButton>
}
trigger={button}
>
<MenuItem Icon={ChatIcon} label={_t("action|start_chat")} onSelect={vm.createChatRoom} hideChevron />
{canCreateRoom && (
@@ -25,6 +25,7 @@ export class MockedViewModel extends MockViewModel<RoomListHeaderViewSnapshot> i
public toggleMessagePreview = vi.fn<() => void>();
public createSection = vi.fn<() => void>();
public collapseOrExpandSections = vi.fn<() => void>();
public closeSectionReleaseAnnouncement = vi.fn<() => void>();
}
export { defaultSnapshot } from "./default-snapshot";