New room list: fix multiple visual issues (#29673)

* fix(room list item): add bold when there is a notification

* fix(room list item menu): fix color of check icon

* fix(menu): remove chevron

* chore: update @vector-im/compound-web

* test(room list): update tests

* test(e2e): update snapshots
This commit is contained in:
Florian Duros
2025-04-04 09:45:45 +02:00
committed by GitHub
parent 5ce5e9092b
commit d337106eed
18 changed files with 85 additions and 22 deletions

View File

@@ -93,7 +93,7 @@
"@types/png-chunks-extract": "^1.0.2",
"@types/react-virtualized": "^9.21.30",
"@vector-im/compound-design-tokens": "^4.0.0",
"@vector-im/compound-web": "^7.10.0",
"@vector-im/compound-web": "^7.10.1",
"@vector-im/matrix-wysiwyg": "2.38.3",
"@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

@@ -39,7 +39,7 @@
box-sizing: border-box;
min-width: 0;
span {
.mx_RoomListItemView_roomName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -71,3 +71,7 @@
padding-right: var(--cpd-space-3x);
}
}
.mx_RoomListItemView_bold .mx_RoomListItemView_roomName {
font: var(--cpd-font-body-md-semibold);
}

View File

@@ -36,6 +36,10 @@ export interface RoomListItemViewState {
* The notification state of the room.
*/
notificationState: RoomNotificationState;
/**
* Whether the room should be bolded.
*/
isBold: boolean;
}
/**
@@ -51,6 +55,7 @@ export function useRoomListItemViewModel(room: Room): RoomListItemViewState {
hasAccessToOptionsMenu(room) || hasAccessToNotificationMenu(room, matrixClient.isGuest(), isArchived);
const notificationState = useMemo(() => RoomNotificationStateStore.instance.getRoomState(room), [room]);
const a11yLabel = getA11yLabel(room, notificationState);
const isBold = notificationState.hasAnyNotificationOrActivity;
// Actions
@@ -67,6 +72,7 @@ export function useRoomListItemViewModel(room: Room): RoomListItemViewState {
showHoverMenu,
openRoom,
a11yLabel,
isBold,
};
}

View File

@@ -80,16 +80,32 @@ function SpaceMenu({ vm }: SpaceMenuProps): JSX.Element {
</IconButton>
}
>
<MenuItem Icon={HomeIcon} label={_t("room_list|space_menu|home")} onSelect={vm.openSpaceHome} />
<MenuItem
Icon={HomeIcon}
label={_t("room_list|space_menu|home")}
onSelect={vm.openSpaceHome}
hideChevron={true}
/>
{vm.canInviteInSpace && (
<MenuItem Icon={UserAddIcon} label={_t("action|invite")} onSelect={vm.inviteInSpace} />
<MenuItem
Icon={UserAddIcon}
label={_t("action|invite")}
onSelect={vm.inviteInSpace}
hideChevron={true}
/>
)}
<MenuItem Icon={PreferencesIcon} label={_t("common|preferences")} onSelect={vm.openSpacePreferences} />
<MenuItem
Icon={PreferencesIcon}
label={_t("common|preferences")}
onSelect={vm.openSpacePreferences}
hideChevron={true}
/>
{vm.canAccessSpaceSettings && (
<MenuItem
Icon={SettingsIcon}
label={_t("room_list|space_menu|space_settings")}
onSelect={vm.openSpaceSettings}
hideChevron={true}
/>
)}
</Menu>
@@ -123,10 +139,22 @@ function ComposeMenu({ vm }: ComposeMenuProps): JSX.Element {
</IconButton>
}
>
<MenuItem Icon={UserAddIcon} label={_t("action|new_message")} onSelect={vm.createChatRoom} />
{vm.canCreateRoom && <MenuItem Icon={RoomIcon} label={_t("action|new_room")} onSelect={vm.createRoom} />}
<MenuItem
Icon={UserAddIcon}
label={_t("action|new_message")}
onSelect={vm.createChatRoom}
hideChevron={true}
/>
{vm.canCreateRoom && (
<MenuItem Icon={RoomIcon} label={_t("action|new_room")} onSelect={vm.createRoom} hideChevron={true} />
)}
{vm.canCreateVideoRoom && (
<MenuItem Icon={VideoCallIcon} label={_t("action|new_video_room")} onSelect={vm.createVideoRoom} />
<MenuItem
Icon={VideoCallIcon}
label={_t("action|new_video_room")}
onSelect={vm.createVideoRoom}
hideChevron={true}
/>
)}
</Menu>
);

View File

@@ -90,6 +90,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("room_list|more_options|mark_read")}
onSelect={vm.markAsRead}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
)}
{vm.canMarkAsUnread && (
@@ -98,6 +99,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("room_list|more_options|mark_unread")}
onSelect={vm.markAsUnread}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
)}
<ToggleMenuItem
@@ -112,6 +114,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("room_list|more_options|low_priority")}
onSelect={vm.toggleLowPriority}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
{vm.canInvite && (
<MenuItem
@@ -119,6 +122,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("action|invite")}
onSelect={vm.invite}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
)}
{vm.canCopyRoomLink && (
@@ -127,6 +131,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("room_list|more_options|copy_link")}
onSelect={vm.copyRoomLink}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
)}
<Separator />
@@ -136,6 +141,7 @@ function MoreOptionsMenu({ vm, setMenuOpen }: MoreOptionsMenuProps): JSX.Element
label={_t("room_list|more_options|leave_room")}
onSelect={vm.leaveRoom}
onClick={(evt) => evt.stopPropagation()}
hideChevron={true}
/>
</Menu>
);
@@ -173,6 +179,8 @@ interface NotificationMenuProps {
function NotificationMenu({ vm, setMenuOpen }: NotificationMenuProps): JSX.Element {
const [open, setOpen] = useState(false);
const checkComponent = <CheckIcon width="24px" height="24px" color="var(--cpd-color-icon-primary)" />;
return (
<Menu
open={open}
@@ -192,7 +200,7 @@ function NotificationMenu({ vm, setMenuOpen }: NotificationMenuProps): JSX.Eleme
onSelect={() => vm.setRoomNotifState(RoomNotifState.AllMessages)}
onClick={(evt) => evt.stopPropagation()}
>
{vm.isNotificationAllMessage && <CheckIcon width="24px" height="24px" />}
{vm.isNotificationAllMessage && checkComponent}
</MenuItem>
<MenuItem
aria-selected={vm.isNotificationAllMessageLoud}
@@ -201,7 +209,7 @@ function NotificationMenu({ vm, setMenuOpen }: NotificationMenuProps): JSX.Eleme
onSelect={() => vm.setRoomNotifState(RoomNotifState.AllMessagesLoud)}
onClick={(evt) => evt.stopPropagation()}
>
{vm.isNotificationAllMessageLoud && <CheckIcon width="24px" height="24px" />}
{vm.isNotificationAllMessageLoud && checkComponent}
</MenuItem>
<MenuItem
aria-selected={vm.isNotificationMentionOnly}
@@ -210,7 +218,7 @@ function NotificationMenu({ vm, setMenuOpen }: NotificationMenuProps): JSX.Eleme
onSelect={() => vm.setRoomNotifState(RoomNotifState.MentionsOnly)}
onClick={(evt) => evt.stopPropagation()}
>
{vm.isNotificationMentionOnly && <CheckIcon width="24px" height="24px" />}
{vm.isNotificationMentionOnly && checkComponent}
</MenuItem>
<MenuItem
aria-selected={vm.isNotificationMute}
@@ -219,7 +227,7 @@ function NotificationMenu({ vm, setMenuOpen }: NotificationMenuProps): JSX.Eleme
onSelect={() => vm.setRoomNotifState(RoomNotifState.Mute)}
onClick={(evt) => evt.stopPropagation()}
>
{vm.isNotificationMute && <CheckIcon width="24px" height="24px" />}
{vm.isNotificationMute && checkComponent}
</MenuItem>
</Menu>
);

View File

@@ -48,6 +48,7 @@ export function RoomListItemView({ room, isSelected, ...props }: RoomListItemVie
mx_RoomListItemView_notification_decoration: isNotificationDecorationVisible,
mx_RoomListItemView_menu_open: showHoverDecoration,
mx_RoomListItemView_selected: isSelected,
mx_RoomListItemView_bold: vm.isBold,
})}
type="button"
aria-selected={isSelected}
@@ -69,7 +70,9 @@ export function RoomListItemView({ room, isSelected, ...props }: RoomListItemVie
justify="space-between"
>
{/* We truncate the room name when too long. Title here is to show the full name on hover */}
<span title={room.name}>{room.name}</span>
<span className="mx_RoomListItemView_roomName" title={room.name}>
{room.name}
</span>
{showHoverDecoration ? (
<RoomListItemMenuView
room={room}

View File

@@ -41,6 +41,7 @@ describe("<RoomListItemView />", () => {
showHoverMenu: false,
notificationState: new RoomNotificationState(room, false),
a11yLabel: "Open room room1",
isBold: false,
};
mocked(useRoomListItemViewModel).mockReturnValue(defaultValue);

View File

@@ -62,6 +62,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room0"
>
room0
@@ -109,6 +110,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room1"
>
room1
@@ -156,6 +158,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room2"
>
room2
@@ -203,6 +206,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room3"
>
room3
@@ -250,6 +254,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room4"
>
room4
@@ -297,6 +302,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room5"
>
room5
@@ -344,6 +350,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room6"
>
room6
@@ -391,6 +398,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room7"
>
room7
@@ -438,6 +446,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room8"
>
room8
@@ -485,6 +494,7 @@ exports[`<RoomList /> should render a room list 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room9"
>
room9

View File

@@ -40,6 +40,7 @@ exports[`<RoomListItemView /> should be selected if isSelected=true 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room1"
>
room1
@@ -90,6 +91,7 @@ exports[`<RoomListItemView /> should render a room item 1`] = `
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
>
<span
class="mx_RoomListItemView_roomName"
title="room1"
>
room1

View File

@@ -24,7 +24,7 @@ exports[`<NotificationDecoration /> should render the invitation decoration 1`]
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;"
>
<span
class="_unread-counter_1ibqq_8"
class="_unread-counter_9mg0k_8"
>
1
</span>
@@ -51,7 +51,7 @@ exports[`<NotificationDecoration /> should render the mention decoration 1`] = `
/>
</svg>
<span
class="_unread-counter_1ibqq_8"
class="_unread-counter_9mg0k_8"
>
1
</span>
@@ -92,7 +92,7 @@ exports[`<NotificationDecoration /> should render the notification decoration 1`
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;"
>
<span
class="_unread-counter_1ibqq_8"
class="_unread-counter_9mg0k_8"
>
1
</span>
@@ -108,7 +108,7 @@ exports[`<NotificationDecoration /> should render the notification decoration wi
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-1-5x); --mx-flex-wrap: nowrap;"
>
<div
class="_unread-counter_1ibqq_8"
class="_unread-counter_9mg0k_8"
/>
</div>
</DocumentFragment>

View File

@@ -3724,10 +3724,10 @@
resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-4.0.1.tgz#5c4ea7ad664d8e6206dc42e41649c80ef060a760"
integrity sha512-V4AsK1FVFxZ6DmmCoeAi8FyvE7ODMlXPWjqRGotcnVaoGNrDQrVz2ZGV85DCz5ISxB3iynYASe6OXsDVXT1zFA==
"@vector-im/compound-web@^7.10.0":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-7.10.0.tgz#d3913ea8737c56271152a1643f12d5c5be370718"
integrity sha512-lqIA/eHum5tekFkNeHmgK9Cm48pl7leWKVvJDy/hJFX2KDHqGvPcIy6E0waqTIsodV8z0GAztj1c/1cYRpdYIA==
"@vector-im/compound-web@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-7.10.1.tgz#9aa7fc93550b4b064484fa30226439b2d07bb35e"
integrity sha512-3tVIPCNxXCrMz6TqJc5GiOndPC7bjCRdYIcSKIb7T3B0gVo81aAD2wWL5xSb33yDbXc/tdlKCiav57eQB8dRsQ==
dependencies:
"@floating-ui/react" "^0.27.0"
"@radix-ui/react-context-menu" "^2.2.1"
@@ -3741,13 +3741,14 @@
"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm":
version "0.0.0"
uid ""
"@vector-im/matrix-wysiwyg@2.38.3":
version "2.38.3"
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.3.tgz#cc54d8b3e9472bcd8e622126ba364ee31952cd8a"
integrity sha512-fqo8P55Vc/t0vxpFar9RDJN5gKEjJmzrLo+O4piDbFda6VrRoqrWAtiu0Au0g6B4hRDPKIuFupk8v9Ja7q8Hvg==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../bindings/wysiwyg-wasm"
"@vector-im/matrix-wysiwyg-wasm" "link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.3-cc54d8b3e9472bcd8e622126ba364ee31952cd8a-integrity/node_modules/bindings/wysiwyg-wasm"
"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1":
version "1.14.1"