Improve icon rendering in iconized context menu (#31458)

* Fix composer button visibility in contrast colour mode

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update test

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Simplify

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update screenshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Improve icon rendering in iconized context menu

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add test

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Delint

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-12-09 15:10:42 +00:00
committed by GitHub
parent 4fda167c11
commit efe59ff35f
37 changed files with 440 additions and 564 deletions

View File

@@ -10,6 +10,7 @@ import { EventType, RoomType, JoinRule, Preset, type Room, RoomEvent } from "mat
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import React, { type JSX, useCallback, useContext, useRef, useState } from "react";
import { PlusIcon, RoomIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import createRoom, { type IOpts } from "../../createRoom";
@@ -66,6 +67,7 @@ import MainSplit from "./MainSplit";
import RightPanel from "./RightPanel";
import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
import { type RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
import { Icon as HashVideoIcon } from "../../../res/img/element-icons/roomlist/hash-video.svg";
interface IProps {
space: Room;
@@ -117,7 +119,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
<>
<IconizedContextMenuOption
label={_t("action|new_room")}
iconClassName="mx_LegacyRoomList_iconNewRoom"
icon={<PlusIcon />}
onClick={async (e): Promise<void> => {
e.preventDefault();
e.stopPropagation();
@@ -132,7 +134,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
{videoRoomsEnabled && (
<IconizedContextMenuOption
label={_t("action|new_video_room")}
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
icon={<HashVideoIcon />}
onClick={async (e): Promise<void> => {
e.preventDefault();
e.stopPropagation();
@@ -157,7 +159,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
)}
<IconizedContextMenuOption
label={_t("action|add_existing_room")}
iconClassName="mx_LegacyRoomList_iconAddExistingRoom"
icon={<RoomIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -168,7 +170,7 @@ const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
{canCreateSpace && (
<IconizedContextMenuOption
label={_t("room_list|add_space_label")}
iconClassName="mx_LegacyRoomList_iconPlus"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();

View File

@@ -8,6 +8,13 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, createRef, type ReactNode } from "react";
import { type Room } from "matrix-js-sdk/src/matrix";
import {
HomeSolidIcon,
LockSolidIcon,
QrCodeIcon,
SettingsSolidIcon,
LeaveIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import defaultDispatcher from "../../dispatcher/dispatcher";
@@ -42,7 +49,9 @@ import PosthogTrackers from "../../PosthogTrackers";
import { type ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
import { SDKContext } from "../../contexts/SDKContext";
import { shouldShowFeedback } from "../../utils/Feedback";
import DarkLightModeSvg from "../../../res/img/element-icons/roomlist/dark-light-mode.svg";
import { Icon as DarkLightModeSvg } from "../../../res/img/element-icons/roomlist/dark-light-mode.svg";
import { Icon as NotificationsIcon } from "../../../res/img/element-icons/notifications.svg";
import { Icon as FeedbackIcon } from "../../../res/img/element-icons/feedback.svg";
interface IProps {
isPanelCollapsed: boolean;
@@ -297,7 +306,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
if (this.hasHomePage) {
homeButton = (
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconHome"
icon={<HomeSolidIcon />}
label={_t("common|home")}
onClick={this.onHomeClick}
/>
@@ -308,7 +317,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
if (shouldShowFeedback()) {
feedbackButton = (
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconMessage"
icon={<FeedbackIcon />}
label={_t("common|feedback")}
onClick={this.onProvideFeedback}
/>
@@ -317,7 +326,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
const linkNewDeviceButton = (
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconQr"
icon={<QrCodeIcon />}
label={_t("user_menu|link_new_device")}
onClick={(e) => this.onSettingsOpen(e, UserTab.SessionManager, { showMsc4108QrCode: true })}
/>
@@ -328,24 +337,24 @@ export default class UserMenu extends React.Component<IProps, IState> {
{homeButton}
{linkNewDeviceButton}
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconBell"
icon={<NotificationsIcon />}
label={_t("notifications|enable_prompt_toast_title")}
onClick={(e) => this.onSettingsOpen(e, UserTab.Notifications)}
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconLock"
icon={<LockSolidIcon />}
label={_t("room_settings|security|title")}
onClick={(e) => this.onSettingsOpen(e, UserTab.Security)}
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconSettings"
icon={<SettingsSolidIcon />}
label={_t("user_menu|settings")}
onClick={(e) => this.onSettingsOpen(e)}
/>
{feedbackButton}
<IconizedContextMenuOption
className="mx_IconizedContextMenu_option_red"
iconClassName="mx_UserMenu_iconSignOut"
icon={<LeaveIcon />}
label={_t("action|sign_out")}
onClick={this.onSignOutClick}
/>
@@ -357,7 +366,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
<IconizedContextMenuOptionList>
{homeButton}
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconSettings"
icon={<SettingsSolidIcon />}
label={_t("common|settings")}
onClick={(e) => this.onSettingsOpen(e)}
/>
@@ -398,7 +407,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
: _t("user_menu|switch_theme_dark")
}
>
<img src={DarkLightModeSvg} role="presentation" alt="" width={16} />
<DarkLightModeSvg width="16px" height="16px" />
</RovingAccessibleButton>
</div>
{topSection}

View File

@@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { LabsIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import Modal from "../../../Modal";
import DevtoolsDialog from "../dialogs/DevtoolsDialog";
@@ -32,7 +33,7 @@ export const DeveloperToolsOption: React.FC<Props> = ({ onFinished, roomId }) =>
onFinished();
}}
label={_t("devtools|title")}
iconClassName="mx_IconizedContextMenu_developerTools"
icon={<LabsIcon />}
/>
);
};

View File

@@ -26,14 +26,7 @@ interface IDeviceContextMenuDeviceProps {
}
const DeviceContextMenuDevice: React.FC<IDeviceContextMenuDeviceProps> = ({ label, selected, onClick }) => {
return (
<IconizedContextMenuRadio
iconClassName="mx_DeviceContextMenu_device_icon"
label={label}
active={selected}
onClick={onClick}
/>
);
return <IconizedContextMenuRadio label={label} active={selected} onClick={onClick} />;
};
interface IDeviceContextMenuSectionProps {

View File

@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, type ReactNode } from "react";
import classNames from "classnames";
import { CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import ContextMenu, {
ChevronFace,
@@ -33,26 +34,19 @@ interface IOptionListProps {
interface IOptionProps extends React.ComponentProps<typeof MenuItem> {
icon?: ReactNode;
iconClassName?: string;
isDestructive?: boolean;
}
interface ICheckboxProps extends React.ComponentProps<typeof MenuItemCheckbox> {
iconClassName: string;
icon?: ReactNode;
words?: boolean;
}
interface IRadioProps extends React.ComponentProps<typeof MenuItemRadio> {
iconClassName?: string;
icon?: ReactNode;
}
export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({
label,
iconClassName,
active,
className,
...props
}) => {
export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({ label, icon, active, className, ...props }) => {
return (
<MenuItemRadio
{...props}
@@ -63,35 +57,28 @@ export const IconizedContextMenuRadio: React.FC<IRadioProps> = ({
active={active}
label={label}
>
{iconClassName && <span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />}
{icon}
<span className="mx_IconizedContextMenu_label">{label}</span>
{active && <span className="mx_IconizedContextMenu_icon mx_IconizedContextMenu_checked" />}
{active && <CheckIcon className="mx_IconizedContextMenu_checked" />}
</MenuItemRadio>
);
};
export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
label,
iconClassName,
icon,
active,
className,
words,
...props
}) => {
let marker: JSX.Element;
let marker: JSX.Element | undefined;
if (words) {
marker = (
<span className="mx_IconizedContextMenu_activeText">{active ? _t("common|on") : _t("common|off")}</span>
);
} else {
marker = (
<span
className={classNames("mx_IconizedContextMenu_icon", {
mx_IconizedContextMenu_checked: active,
mx_IconizedContextMenu_unchecked: !active,
})}
/>
);
} else if (active) {
marker = <CheckIcon className="mx_IconizedContextMenu_checked" />;
}
return (
@@ -104,7 +91,7 @@ export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
active={active}
label={label}
>
<span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />
{icon}
<span className="mx_IconizedContextMenu_label">{label}</span>
{marker}
</MenuItemCheckbox>
@@ -114,7 +101,6 @@ export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
label,
className,
iconClassName,
icon,
children,
isDestructive,
@@ -130,7 +116,6 @@ export const IconizedContextMenuOption: React.FC<IOptionProps> = ({
})}
label={label}
>
{iconClassName && <span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />}
{icon}
<span className="mx_IconizedContextMenu_label">{label}</span>
{children}

View File

@@ -20,6 +20,27 @@ import {
Thread,
M_POLL_START,
} from "matrix-js-sdk/src/matrix";
import {
CheckIcon,
ChevronUpIcon,
EditIcon,
ErrorSolidIcon,
InlineCodeIcon,
LinkIcon,
PinIcon,
QuoteIcon,
ReactionAddIcon,
ReplyIcon,
RestartIcon,
ThreadsIcon,
UnpinIcon,
DeleteIcon,
ForwardIcon,
PopOutIcon,
VisibilityOnIcon,
ShareIcon,
CopyIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import dis from "../../../dispatcher/dispatcher";
@@ -53,6 +74,8 @@ import { type ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadP
import { CardContext } from "../right_panel/context";
import PinningUtils from "../../../utils/PinningUtils";
import PosthogTrackers from "../../../PosthogTrackers.ts";
import { Icon as ViewInRoomIcon } from "../../../../res/img/element-icons/view-in-room.svg";
import { Icon as ChildRelationshipIcon } from "../../../../res/img/element-icons/child-relationship.svg";
interface IReplyInThreadButton {
mxEvent: MatrixEvent;
@@ -86,13 +109,7 @@ const ReplyInThreadButton: React.FC<IReplyInThreadButton> = ({ mxEvent, closeMen
closeMenu();
};
return (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconReplyInThread"
label={_t("action|reply_in_thread")}
onClick={onClick}
/>
);
return <IconizedContextMenuOption icon={<ThreadsIcon />} label={_t("action|reply_in_thread")} onClick={onClick} />;
};
interface IProps extends MenuProps {
@@ -413,7 +430,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (!mxEvent.isRedacted() && unsentReactionsCount !== 0) {
resendReactionsButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconResend"
icon={<RestartIcon />}
label={_t("timeline|context_menu|resent_unsent_reactions", { unsentCount: unsentReactionsCount })}
onClick={this.onResendReactionsClick}
/>
@@ -424,7 +441,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (isSent && this.state.canRedact) {
redactButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconRedact"
icon={<DeleteIcon />}
label={_t("action|remove")}
onClick={this.onRedactClick}
/>
@@ -437,7 +454,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
const mapSiteLink = createMapSiteLinkFromEvent(shareableLocationEvent);
openInMapSiteButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconOpenInMapSite"
icon={<PopOutIcon />}
onClick={null}
label={_t("timeline|context_menu|open_in_osm")}
element="a"
@@ -455,7 +472,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (contentActionable && forwardableEvent) {
forwardButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconForward"
icon={<ForwardIcon />}
label={_t("action|forward")}
onClick={this.onForwardClick(forwardableEvent)}
/>
@@ -465,7 +482,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
// This is specifically not behind the developerMode flag to give people insight into the Matrix
const viewSourceButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconSource"
icon={<InlineCodeIcon />}
label={_t("timeline|context_menu|view_source")}
onClick={this.onViewSourceClick}
/>
@@ -475,7 +492,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (eventTileOps?.isWidgetHidden()) {
unhidePreviewButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconUnhidePreview"
icon={<VisibilityOnIcon />}
label={_t("timeline|context_menu|show_url_preview")}
onClick={this.onUnhidePreviewClick}
/>
@@ -486,7 +503,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (permalink) {
permalinkButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconPermalink"
icon={<ShareIcon />}
onClick={this.onShareClick}
label={_t("action|share")}
element="a"
@@ -506,7 +523,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (this.canEndPoll(mxEvent)) {
endPollButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconEndPoll"
icon={<CheckIcon />}
label={_t("poll|end_title")}
onClick={this.onEndPollClick}
/>
@@ -521,7 +538,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
) {
externalURLButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconLink"
icon={<LinkIcon />}
onClick={this.closeMenu}
label={_t("timeline|context_menu|external_url")}
element="a"
@@ -541,7 +558,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (collapseReplyChain) {
collapseReplyChainButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconCollapse"
icon={<ChevronUpIcon />}
label={_t("timeline|context_menu|collapse_reply_thread")}
onClick={this.onCollapseReplyChainClick}
/>
@@ -553,7 +570,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (relatedEventId && SettingsStore.getValue("developerMode")) {
jumpToRelatedEventButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_jumpToEvent"
icon={<ChildRelationshipIcon />}
label={_t("timeline|context_menu|view_related_event")}
onClick={() => this.onJumpToRelatedEventClick(relatedEventId)}
/>
@@ -564,7 +581,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (mxEvent.getSender() !== me) {
reportEventButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconReport"
icon={<ErrorSolidIcon />}
label={_t("timeline|context_menu|report")}
onClick={this.onReportEventClick}
/>
@@ -575,7 +592,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (link) {
copyLinkButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconCopy"
icon={<CopyIcon />}
onClick={this.onCopyLinkClick}
label={_t("action|copy_link")}
element="a"
@@ -597,7 +614,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (rightClick && selectedText) {
copyButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconCopy"
icon={<CopyIcon />}
label={_t("action|copy")}
triggerOnMouseDown={true} // We use onMouseDown so that the selection isn't cleared when we click
onClick={this.onCopyClick}
@@ -609,7 +626,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (rightClick && selectedText && selectedText.trim().length > 0 && this.isSelectionWithinSingleTextBody()) {
quoteButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconQuote"
icon={<QuoteIcon />}
label={_t("action|quote")}
triggerOnMouseDown={true}
onClick={this.onQuoteClick}
@@ -620,11 +637,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
let editButton: JSX.Element | undefined;
if (rightClick && canEditContent(cli, mxEvent)) {
editButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconEdit"
label={_t("action|edit")}
onClick={this.onEditClick}
/>
<IconizedContextMenuOption icon={<EditIcon />} label={_t("action|edit")} onClick={this.onEditClick} />
);
}
@@ -632,7 +645,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (rightClick && contentActionable && canSendMessages) {
replyButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconReply"
icon={<ReplyIcon />}
label={_t("action|reply")}
onClick={this.onReplyClick}
/>
@@ -654,7 +667,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (rightClick && contentActionable && canReact) {
reactButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconReact"
icon={<ReactionAddIcon />}
label={_t("action|react")}
onClick={this.onReactClick}
inputRef={this.reactButtonRef}
@@ -667,7 +680,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
const isPinned = PinningUtils.isPinned(MatrixClientPeg.safeGet(), this.props.mxEvent);
pinButton = (
<IconizedContextMenuOption
iconClassName={isPinned ? "mx_MessageContextMenu_iconUnpin" : "mx_MessageContextMenu_iconPin"}
icon={isPinned ? <UnpinIcon /> : <PinIcon />}
label={isPinned ? _t("action|unpin") : _t("action|pin")}
onClick={() => this.onPinClick(isPinned)}
/>
@@ -678,7 +691,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
if (isThreadRootEvent) {
viewInRoomButton = (
<IconizedContextMenuOption
iconClassName="mx_MessageContextMenu_iconViewInRoom"
icon={<ViewInRoomIcon />}
label={_t("timeline|mab|view_in_room")}
onClick={this.viewInRoom}
/>

View File

@@ -9,6 +9,15 @@ Please see LICENSE files in the repository root for full details.
import { logger } from "matrix-js-sdk/src/logger";
import { type Room } from "matrix-js-sdk/src/matrix";
import React, { type JSX, useContext } from "react";
import {
FavouriteSolidIcon,
LinkIcon,
SettingsSolidIcon,
ArrowDownIcon,
MarkAsReadIcon,
MarkAsUnreadIcon,
LeaveIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import RoomListActions from "../../../actions/RoomListActions";
@@ -34,6 +43,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
import { UIComponent } from "../../../settings/UIFeature";
import { DeveloperToolsOption } from "./DeveloperToolsOption";
import { useSettingValue } from "../../../hooks/useSettings";
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
export interface RoomGeneralContextMenuProps extends IContextMenuProps {
room: Room;
@@ -153,7 +163,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onClick={wrapHandler((ev) => onTagRoom(ev, DefaultTagID.Favourite), onPostFavoriteClick, true)}
active={isFavorite}
label={isFavorite ? _t("room|context_menu|unfavourite") : _t("room|context_menu|favourite")}
iconClassName="mx_RoomGeneralContextMenu_iconStar"
icon={<FavouriteSolidIcon />}
/>
);
@@ -163,7 +173,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onClick={wrapHandler((ev) => onTagRoom(ev, DefaultTagID.LowPriority), onPostLowPriorityClick, true)}
active={isLowPriority}
label={_t("room|context_menu|low_priority")}
iconClassName="mx_RoomGeneralContextMenu_iconArrowDown"
icon={<ArrowDownIcon />}
/>
);
@@ -180,7 +190,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onPostInviteClick,
)}
label={_t("action|invite")}
iconClassName="mx_RoomGeneralContextMenu_iconInvite"
icon={<InviteIcon />}
/>
);
}
@@ -198,7 +208,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onPostCopyLinkClick,
)}
label={_t("room|context_menu|copy_link")}
iconClassName="mx_RoomGeneralContextMenu_iconCopyLink"
icon={<LinkIcon />}
/>
);
}
@@ -214,7 +224,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onPostSettingsClick,
)}
label={_t("common|settings")}
iconClassName="mx_RoomGeneralContextMenu_iconSettings"
icon={<SettingsSolidIcon />}
/>
);
@@ -222,7 +232,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
if (roomTags.includes(DefaultTagID.Archived)) {
leaveOption = (
<IconizedContextMenuOption
iconClassName="mx_RoomGeneralContextMenu_iconSignOut"
icon={<LeaveIcon />}
label={_t("room|context_menu|forget")}
className="mx_IconizedContextMenu_option_red"
onClick={wrapHandler(
@@ -248,7 +258,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
)}
label={_t("action|leave")}
className="mx_IconizedContextMenu_option_red"
iconClassName="mx_RoomGeneralContextMenu_iconSignOut"
icon={<LeaveIcon />}
/>
);
}
@@ -263,7 +273,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onFinished?.();
}, onPostMarkAsReadClick)}
label={_t("room|context_menu|mark_read")}
iconClassName="mx_RoomGeneralContextMenu_iconMarkAsRead"
icon={<MarkAsReadIcon />}
/>
);
} else if (!roomTags.includes(DefaultTagID.Archived)) {
@@ -274,7 +284,7 @@ export const RoomGeneralContextMenu: React.FC<RoomGeneralContextMenuProps> = ({
onFinished?.();
}, onPostMarkAsUnreadClick)}
label={_t("room|context_menu|mark_unread")}
iconClassName="mx_RoomGeneralContextMenu_iconMarkAsUnread"
icon={<MarkAsUnreadIcon />}
/>
);
} else {

View File

@@ -20,6 +20,10 @@ import IconizedContextMenu, {
IconizedContextMenuRadio,
} from "../context_menus/IconizedContextMenu";
import { type ButtonEvent } from "../elements/AccessibleButton";
import { Icon as NotificationsIcon } from "../../../../res/img/element-icons/notifications.svg";
import { Icon as NotificationsDefaultIcon } from "../../../../res/img/element-icons/roomlist/notifications-default.svg";
import { Icon as NotificationsDmIcon } from "../../../../res/img/element-icons/roomlist/notifications-dm.svg";
import { Icon as NotificationsOffIcon } from "../../../../res/img/element-icons/roomlist/notifications-off.svg";
interface IProps extends IContextMenuProps {
room: Room;
@@ -46,7 +50,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
<IconizedContextMenuRadio
label={_t("room|context_menu|notifications_default")}
active={notificationState === RoomNotifState.AllMessages}
iconClassName="mx_RoomNotificationContextMenu_iconBell"
icon={<NotificationsIcon />}
onClick={wrapHandler(() => setNotificationState(RoomNotifState.AllMessages))}
/>
);
@@ -55,7 +59,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
<IconizedContextMenuRadio
label={_t("notifications|all_messages")}
active={notificationState === RoomNotifState.AllMessagesLoud}
iconClassName="mx_RoomNotificationContextMenu_iconBellDot"
icon={<NotificationsDefaultIcon />}
onClick={wrapHandler(() => setNotificationState(RoomNotifState.AllMessagesLoud))}
/>
);
@@ -64,7 +68,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
<IconizedContextMenuRadio
label={_t("notifications|mentions_keywords")}
active={notificationState === RoomNotifState.MentionsOnly}
iconClassName="mx_RoomNotificationContextMenu_iconBellMentions"
icon={<NotificationsDmIcon />}
onClick={wrapHandler(() => setNotificationState(RoomNotifState.MentionsOnly))}
/>
);
@@ -73,7 +77,7 @@ export const RoomNotificationContextMenu: React.FC<IProps> = ({ room, onFinished
<IconizedContextMenuRadio
label={_t("room|context_menu|notifications_mute")}
active={notificationState === RoomNotifState.Mute}
iconClassName="mx_RoomNotificationContextMenu_iconBellCrossed"
icon={<NotificationsOffIcon />}
onClick={wrapHandler(() => setNotificationState(RoomNotifState.Mute))}
/>
);

View File

@@ -8,6 +8,14 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, useContext } from "react";
import { type Room, EventType, RoomType } from "matrix-js-sdk/src/matrix";
import {
HomeSolidIcon,
PlusIcon,
SettingsSolidIcon,
LeaveIcon,
SearchIcon,
PreferencesIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { type IProps as IContextMenuProps } from "../../structures/ContextMenu";
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
@@ -32,6 +40,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
import { UIComponent } from "../../../settings/UIFeature";
import PosthogTrackers from "../../../PosthogTrackers";
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
interface IProps extends IContextMenuProps {
space?: Room;
@@ -60,7 +69,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
<IconizedContextMenuOption
data-testid="invite-option"
className="mx_SpacePanel_contextMenu_inviteButton"
iconClassName="mx_SpacePanel_iconInvite"
icon={<InviteIcon />}
label={_t("action|invite")}
onClick={onInviteClick}
/>
@@ -81,7 +90,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
settingsOption = (
<IconizedContextMenuOption
data-testid="settings-option"
iconClassName="mx_SpacePanel_iconSettings"
icon={<SettingsSolidIcon />}
label={_t("common|settings")}
onClick={onSettingsClick}
/>
@@ -98,7 +107,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
leaveOption = (
<IconizedContextMenuOption
data-testid="leave-option"
iconClassName="mx_SpacePanel_iconLeave"
icon={<LeaveIcon />}
className="mx_IconizedContextMenu_option_red"
label={_t("space|leave_dialog_action")}
onClick={onLeaveClick}
@@ -123,7 +132,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
devtoolsOption = (
<IconizedContextMenuOption
iconClassName="mx_SpacePanel_iconSettings"
icon={<SettingsSolidIcon />}
label={_t("space|context_menu|devtools_open_timeline")}
onClick={onViewTimelineClick}
/>
@@ -170,7 +179,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
{canAddRooms && (
<IconizedContextMenuOption
data-testid="new-room-option"
iconClassName="mx_SpacePanel_iconPlus"
icon={<PlusIcon />}
label={_t("common|room")}
onClick={onNewRoomClick}
/>
@@ -178,7 +187,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
{canAddVideoRooms && (
<IconizedContextMenuOption
data-testid="new-video-room-option"
iconClassName="mx_SpacePanel_iconPlus"
icon={<PlusIcon />}
label={_t("common|video_room")}
onClick={onNewVideoRoomClick}
>
@@ -188,7 +197,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
{canAddSubSpaces && (
<IconizedContextMenuOption
data-testid="new-subspace-option"
iconClassName="mx_SpacePanel_iconPlus"
icon={<PlusIcon />}
label={_t("common|space")}
onClick={onNewSubspaceClick}
>
@@ -234,18 +243,18 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
{!hideHeader && <div className="mx_SpacePanel_contextMenu_header">{space.name}</div>}
<IconizedContextMenuOptionList first>
<IconizedContextMenuOption
iconClassName="mx_SpacePanel_iconHome"
icon={<HomeSolidIcon />}
label={_t("space|context_menu|home")}
onClick={onHomeClick}
/>
{inviteOption}
<IconizedContextMenuOption
iconClassName="mx_SpacePanel_iconExplore"
icon={<SearchIcon />}
label={canAddRooms ? _t("space|context_menu|manage_and_explore") : _t("space|context_menu|explore")}
onClick={onExploreRoomsClick}
/>
<IconizedContextMenuOption
iconClassName="mx_SpacePanel_iconPreferences"
icon={<PreferencesIcon />}
label={_t("common|preferences")}
onClick={onPreferencesClick}
/>

View File

@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { useCallback, useEffect } from "react";
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { LinkIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { type ButtonEvent } from "../elements/AccessibleButton";
import dis from "../../../dispatcher/dispatcher";
@@ -20,6 +21,7 @@ import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOpti
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Icon as ViewInRoomIcon } from "../../../../res/img/element-icons/view-in-room.svg";
export interface ThreadListContextMenuProps {
mxEvent: MatrixEvent;
@@ -102,7 +104,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
<IconizedContextMenuOption
onClick={(e) => viewInRoom(e)}
label={_t("timeline|mab|view_in_room")}
iconClassName="mx_ThreadPanel_viewInRoom"
icon={<ViewInRoomIcon />}
/>
)}
{permalinkCreator && (
@@ -110,7 +112,7 @@ const ThreadListContextMenu: React.FC<ThreadListContextMenuProps> = ({
data-testid="copy-thread-link"
onClick={(e) => copyLinkToThread(e)}
label={_t("timeline|mab|copy_link_thread")}
iconClassName="mx_ThreadPanel_copyLinkToThread"
icon={<LinkIcon />}
/>
)}
</IconizedContextMenuOptionList>

View File

@@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import classNames from "classnames";
import { type Room } from "matrix-js-sdk/src/matrix";
import React, { type JSX, Fragment, useState } from "react";
import React, { type JSX, Fragment, useState, type ReactNode } from "react";
import { OverflowHorizontalIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { ContextMenuTooltipButton } from "../../../../accessibility/context_menu/ContextMenuTooltipButton";
import { useNotificationState } from "../../../../hooks/useRoomNotificationState";
@@ -21,11 +21,25 @@ import { type ButtonEvent } from "../../elements/AccessibleButton";
import { contextMenuBelow } from "../../rooms/RoomTile";
import { shouldShowComponent } from "../../../../customisations/helpers/UIComponents";
import { UIComponent } from "../../../../settings/UIFeature";
import { Icon as NotificationsIcon } from "../../../../../res/img/element-icons/notifications.svg";
import { Icon as NotificationsDefaultIcon } from "../../../../../res/img/element-icons/roomlist/notifications-default.svg";
import { Icon as NotificationsDmIcon } from "../../../../../res/img/element-icons/roomlist/notifications-dm.svg";
import { Icon as NotificationsOffIcon } from "../../../../../res/img/element-icons/roomlist/notifications-off.svg";
interface Props {
room: Room;
}
export function getNotificationIcon(state: RoomNotifState): ReactNode {
const icons: Record<RoomNotifState, JSX.Element> = {
[RoomNotifState.AllMessages]: <NotificationsIcon />,
[RoomNotifState.AllMessagesLoud]: <NotificationsDefaultIcon />,
[RoomNotifState.MentionsOnly]: <NotificationsDmIcon />,
[RoomNotifState.Mute]: <NotificationsOffIcon />,
};
return icons[state];
}
export function RoomResultContextMenus({ room }: Props): JSX.Element {
const [notificationState] = useNotificationState(room);
@@ -64,14 +78,6 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
);
}
const notificationMenuClasses = classNames("mx_SpotlightDialog_option--notifications", {
// Show bell icon for the default case too.
mx_RoomNotificationContextMenu_iconBell: notificationState === RoomNotifState.AllMessages,
mx_RoomNotificationContextMenu_iconBellDot: notificationState === RoomNotifState.AllMessagesLoud,
mx_RoomNotificationContextMenu_iconBellMentions: notificationState === RoomNotifState.MentionsOnly,
mx_RoomNotificationContextMenu_iconBellCrossed: notificationState === RoomNotifState.Mute,
});
return (
<Fragment>
{shouldShowComponent(UIComponent.RoomOptionsMenu) && (
@@ -86,11 +92,13 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
}}
title={room.isSpaceRoom() ? _t("space|context_menu|options") : _t("room|context_menu|title")}
isExpanded={generalMenuPosition !== null}
/>
>
<OverflowHorizontalIcon />
</ContextMenuTooltipButton>
)}
{!room.isSpaceRoom() && (
<ContextMenuTooltipButton
className={notificationMenuClasses}
className="mx_SpotlightDialog_option--notifications"
onClick={(ev: ButtonEvent) => {
ev.preventDefault();
ev.stopPropagation();
@@ -100,7 +108,9 @@ export function RoomResultContextMenus({ room }: Props): JSX.Element {
}}
title={_t("room_list|notification_options")}
isExpanded={notificationMenuPosition !== null}
/>
>
{getNotificationIcon(notificationState!)}
</ContextMenuTooltipButton>
)}
{generalMenu}
{notificationMenu}

View File

@@ -8,6 +8,13 @@ Please see LICENSE files in the repository root for full details.
import { EventType, type Room, RoomType } from "matrix-js-sdk/src/matrix";
import React, { type JSX, type ComponentType, createRef, type ReactComponentElement, type SyntheticEvent } from "react";
import {
PlusIcon,
UserAddSolidIcon,
RoomIcon,
SearchIcon,
ShareIcon,
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { type IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex.tsx";
import MatrixClientContext from "../../../contexts/MatrixClientContext.tsx";
@@ -67,6 +74,7 @@ import { getKeyBindingsManager } from "../../../KeyBindingsManager.ts";
import AccessibleButton from "../elements/AccessibleButton.tsx";
import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation.ts";
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../LegacyCallHandler.tsx";
import { Icon as HashVideoIcon } from "../../../../res/img/element-icons/roomlist/hash-video.svg";
interface IProps {
onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void;
@@ -142,7 +150,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
{showCreateRooms && (
<IconizedContextMenuOption
label={_t("action|start_new_chat")}
iconClassName="mx_LegacyRoomList_iconStartChat"
icon={<UserAddSolidIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -158,7 +166,7 @@ const DmAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex, dispatcher = default
{showInviteUsers && (
<IconizedContextMenuOption
label={_t("action|invite_to_space")}
iconClassName="mx_LegacyRoomList_iconInvite"
icon={<ShareIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -230,7 +238,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
<IconizedContextMenuOptionList first>
<IconizedContextMenuOption
label={_t("action|explore_rooms")}
iconClassName="mx_LegacyRoomList_iconExplore"
icon={<SearchIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -247,7 +255,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
<>
<IconizedContextMenuOption
label={_t("action|new_room")}
iconClassName="mx_LegacyRoomList_iconNewRoom"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -261,7 +269,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
{videoRoomsEnabled && (
<IconizedContextMenuOption
label={_t("action|new_video_room")}
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
icon={<HashVideoIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -279,7 +287,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
)}
<IconizedContextMenuOption
label={_t("action|add_existing_room")}
iconClassName="mx_LegacyRoomList_iconAddExistingRoom"
icon={<RoomIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -300,7 +308,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
<>
<IconizedContextMenuOption
label={_t("action|new_room")}
iconClassName="mx_LegacyRoomList_iconNewRoom"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -312,7 +320,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
{videoRoomsEnabled && (
<IconizedContextMenuOption
label={_t("action|new_video_room")}
iconClassName="mx_LegacyRoomList_iconNewVideoRoom"
icon={<HashVideoIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -333,7 +341,7 @@ const UntaggedAuxButton: React.FC<IAuxButtonProps> = ({ tabIndex }) => {
{showExploreRooms ? (
<IconizedContextMenuOption
label={_t("action|explore_public_rooms")}
iconClassName="mx_LegacyRoomList_iconExplore"
icon={<SearchIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();

View File

@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import { ClientEvent, EventType, type Room, RoomEvent, RoomType } from "matrix-js-sdk/src/matrix";
import React, { type JSX, useContext, useEffect, useState } from "react";
import { Tooltip } from "@vector-im/compound-web";
import { PlusIcon, UserAddSolidIcon, SearchIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
@@ -51,6 +52,8 @@ import IconizedContextMenu, {
import SpaceContextMenu from "../context_menus/SpaceContextMenu";
import InlineSpinner from "../elements/InlineSpinner";
import { HomeButtonContextMenu } from "../spaces/SpacePanel";
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
import { Icon as HashVideoIcon } from "../../../../res/img/element-icons/roomlist/hash-video.svg";
const contextMenuBelow = (elementRect: DOMRect): MenuProps => {
// align the context menu's icons with the icon which opened the context menu
@@ -178,7 +181,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
inviteOption = (
<IconizedContextMenuOption
label={_t("action|invite")}
iconClassName="mx_LegacyRoomListHeader_iconInvite"
icon={<InviteIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -194,7 +197,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
newRoomOptions = (
<>
<IconizedContextMenuOption
iconClassName="mx_LegacyRoomListHeader_iconNewRoom"
icon={<PlusIcon />}
label={_t("action|new_room")}
onClick={(e) => {
e.preventDefault();
@@ -206,7 +209,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
/>
{videoRoomsEnabled && (
<IconizedContextMenuOption
iconClassName="mx_LegacyRoomListHeader_iconNewVideoRoom"
icon={<HashVideoIcon />}
label={_t("action|new_video_room")}
onClick={(e) => {
e.preventDefault();
@@ -236,7 +239,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
{newRoomOptions}
<IconizedContextMenuOption
label={_t("action|explore_rooms")}
iconClassName="mx_LegacyRoomListHeader_iconExplore"
icon={<SearchIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -251,7 +254,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
/>
<IconizedContextMenuOption
label={_t("action|add_existing_room")}
iconClassName="mx_LegacyRoomListHeader_iconPlus"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -264,7 +267,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
{canCreateSpaces && (
<IconizedContextMenuOption
label={_t("room_list|add_space_label")}
iconClassName="mx_LegacyRoomListHeader_iconPlus"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -289,7 +292,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
<>
<IconizedContextMenuOption
label={_t("action|start_new_chat")}
iconClassName="mx_LegacyRoomListHeader_iconStartChat"
icon={<UserAddSolidIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -300,7 +303,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
/>
<IconizedContextMenuOption
label={_t("action|new_room")}
iconClassName="mx_LegacyRoomListHeader_iconNewRoom"
icon={<PlusIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -312,7 +315,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
{videoRoomsEnabled && (
<IconizedContextMenuOption
label={_t("action|new_video_room")}
iconClassName="mx_LegacyRoomListHeader_iconNewVideoRoom"
icon={<HashVideoIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -333,7 +336,7 @@ const LegacyRoomListHeader: React.FC<IProps> = ({ onVisibilityChange }) => {
joinRoomOpt = (
<IconizedContextMenuOption
label={_t("room_list|join_public_room_label")}
iconClassName="mx_LegacyRoomListHeader_iconExplore"
icon={<SearchIcon />}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();

View File

@@ -45,6 +45,7 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
import { UIComponent } from "../../../settings/UIFeature";
import { isKnockDenied } from "../../../utils/membership";
import SettingsStore from "../../../settings/SettingsStore";
import { getNotificationIcon } from "../dialogs/spotlight/RoomResultContextMenus.tsx";
interface Props {
room: Room;
@@ -293,12 +294,6 @@ class RoomTile extends React.PureComponent<Props, State> {
const state = this.roomProps.notificationVolume;
const classes = classNames("mx_RoomTile_notificationsButton", {
// Show bell icon for the default case too.
mx_RoomNotificationContextMenu_iconBell: state === RoomNotifState.AllMessages,
mx_RoomNotificationContextMenu_iconBellDot: state === RoomNotifState.AllMessagesLoud,
mx_RoomNotificationContextMenu_iconBellMentions: state === RoomNotifState.MentionsOnly,
mx_RoomNotificationContextMenu_iconBellCrossed: state === RoomNotifState.Mute,
// Only show the icon by default if the room is overridden to muted.
// TODO: [FTUE Notifications] Probably need to detect global mute state
mx_RoomTile_notificationsButton_show: state === RoomNotifState.Mute,
@@ -312,7 +307,9 @@ class RoomTile extends React.PureComponent<Props, State> {
title={_t("room_list|notification_options")}
isExpanded={!!this.state.notificationsMenuPosition}
tabIndex={isActive ? 0 : -1}
/>
>
{getNotificationIcon(state!)}
</ContextMenuTooltipButton>
{this.state.notificationsMenuPosition && (
<RoomNotificationContextMenu
{...contextMenuBelow(this.state.notificationsMenuPosition)}

View File

@@ -99,7 +99,6 @@ export const HomeButtonContextMenu: React.FC<ComponentProps<typeof SpaceContextM
{!hideHeader && <div className="mx_SpacePanel_contextMenu_header">{_t("common|home")}</div>}
<IconizedContextMenuOptionList first>
<IconizedContextMenuCheckbox
iconClassName="mx_SpacePanel_noIcon"
label={_t("settings|sidebar|metaspaces_home_all_rooms")}
active={allRoomsInHome}
onClick={() => {