Switch to rendering svg icons rather than masking them (#31550)
* Switch to rendering svg icons rather than masking them in SpacePanel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in JoinRuleDropdown Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in RoomPreviewCard Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in Space menus Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix badly rendered icon in ThreadPanel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove unused icon underfill Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add missing snapshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type JSX } from "react";
|
||||
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
|
||||
const SpacePillButton: React.FC<{
|
||||
title: string;
|
||||
icon: JSX.Element;
|
||||
description: string;
|
||||
onClick(): void;
|
||||
}> = ({ title, icon, description, onClick }) => {
|
||||
return (
|
||||
<AccessibleButton className="mx_SpacePillButton" onClick={onClick}>
|
||||
{icon}
|
||||
{title}
|
||||
<div>{description}</div>
|
||||
</AccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default SpacePillButton;
|
||||
@@ -10,7 +10,12 @@ 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 {
|
||||
GroupIcon,
|
||||
PlusIcon,
|
||||
RoomIcon,
|
||||
UserProfileSolidIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import createRoom, { type IOpts } from "../../createRoom";
|
||||
@@ -68,6 +73,7 @@ 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";
|
||||
import SpacePillButton from "./SpacePillButton.tsx";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
@@ -455,24 +461,22 @@ const SpaceSetupPrivateScope: React.FC<{
|
||||
})}
|
||||
</div>
|
||||
|
||||
<AccessibleButton
|
||||
className="mx_SpaceRoomView_privateScope_justMeButton"
|
||||
<SpacePillButton
|
||||
icon={<UserProfileSolidIcon />}
|
||||
title={_t("create_space|personal_space")}
|
||||
description={_t("create_space|personal_space_description")}
|
||||
onClick={() => {
|
||||
onFinished(false);
|
||||
}}
|
||||
>
|
||||
{_t("create_space|personal_space")}
|
||||
<div>{_t("create_space|personal_space_description")}</div>
|
||||
</AccessibleButton>
|
||||
<AccessibleButton
|
||||
className="mx_SpaceRoomView_privateScope_meAndMyTeammatesButton"
|
||||
/>
|
||||
<SpacePillButton
|
||||
icon={<GroupIcon />}
|
||||
title={_t("create_space|private_space")}
|
||||
description={_t("create_space|private_space_description")}
|
||||
onClick={() => {
|
||||
onFinished(true);
|
||||
}}
|
||||
>
|
||||
{_t("create_space|private_space")}
|
||||
<div>{_t("create_space|private_space_description")}</div>
|
||||
</AccessibleButton>
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { type EventTimelineSet, type Room, Thread } from "matrix-js-sdk/src/matrix";
|
||||
import { IconButton, Tooltip } from "@vector-im/compound-web";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import ThreadsIcon from "@vector-im/compound-design-tokens/assets/web/icons/threads";
|
||||
import { ThreadsIcon, CheckIcon, ChevronDownIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { Icon as MarkAllThreadsReadIcon } from "../../../res/img/element-icons/check-all.svg";
|
||||
import BaseCard from "../views/right_panel/BaseCard";
|
||||
@@ -57,6 +57,7 @@ export const ThreadPanelHeaderFilterOptionItem: React.FC<
|
||||
> = ({ label, description, onClick, isSelected }) => {
|
||||
return (
|
||||
<MenuItemRadio active={isSelected} className="mx_ThreadPanel_Header_FilterOptionItem" onClick={onClick}>
|
||||
{isSelected ? <CheckIcon /> : null}
|
||||
<span>{label}</span>
|
||||
<span>{description}</span>
|
||||
</MenuItemRadio>
|
||||
@@ -145,6 +146,7 @@ export const ThreadPanelHeader: React.FC<{
|
||||
}}
|
||||
>
|
||||
{`${_t("threads|show_thread_filter")} ${value?.label}`}
|
||||
<ChevronDownIcon />
|
||||
</ContextMenuButton>
|
||||
{contextMenu}
|
||||
</div>
|
||||
|
||||
@@ -57,7 +57,7 @@ const JoinRuleDropdown: React.FC<IProps> = ({
|
||||
options.unshift(
|
||||
(
|
||||
<div key={JoinRule.Knock} className="mx_JoinRuleDropdown_knock">
|
||||
<AskToJoinIcon className="mx_Icon mx_Icon_16 mx_JoinRuleDropdown_icon" />
|
||||
<AskToJoinIcon />
|
||||
{labelKnock}
|
||||
</div>
|
||||
) as ReactElement & { key: string },
|
||||
|
||||
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type JSX, type FC, useContext, useState } from "react";
|
||||
import { type Room, JoinRule } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { InfoSolidIcon, VideoCallSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
@@ -152,7 +153,9 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
|
||||
avatarRow = (
|
||||
<>
|
||||
<RoomAvatar room={room} size="50px" viewAvatarOnClick />
|
||||
<div className="mx_RoomPreviewCard_video" />
|
||||
<div className="mx_RoomPreviewCard_video">
|
||||
<VideoCallSolidIcon />
|
||||
</div>
|
||||
<BetaPill onClick={viewLabs} tooltipTitle={_t("labs|video_rooms_beta")} />
|
||||
</>
|
||||
);
|
||||
@@ -174,6 +177,7 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
|
||||
{room.getJoinRule() === "public" && <RoomFacePile room={room} />}
|
||||
{cannotJoin ? (
|
||||
<div className="mx_RoomPreviewCard_notice">
|
||||
<InfoSolidIcon />
|
||||
{_t("room|join_failed_needs_invite", { roomName: room.name })}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -18,7 +18,6 @@ import React, {
|
||||
type ReactNode,
|
||||
useEffect,
|
||||
} from "react";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
RoomType,
|
||||
HistoryVisibility,
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
type ICreateRoomOpts,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { LockSolidIcon, PublicIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
|
||||
@@ -47,6 +47,7 @@ import { Filter } from "../dialogs/spotlight/Filter";
|
||||
import { type OpenSpotlightPayload } from "../../../dispatcher/payloads/OpenSpotlightPayload.ts";
|
||||
import { useSettingValue } from "../../../hooks/useSettings.ts";
|
||||
import { UIFeature } from "../../../settings/UIFeature.ts";
|
||||
import SpacePillButton from "../../structures/SpacePillButton.tsx";
|
||||
|
||||
export const createSpace = async (
|
||||
client: MatrixClient,
|
||||
@@ -86,20 +87,6 @@ export const createSpace = async (
|
||||
});
|
||||
};
|
||||
|
||||
const SpaceCreateMenuType: React.FC<{
|
||||
title: string;
|
||||
description: string;
|
||||
className: string;
|
||||
onClick(): void;
|
||||
}> = ({ title, description, className, onClick }) => {
|
||||
return (
|
||||
<AccessibleButton className={classNames("mx_SpaceCreateMenuType", className)} onClick={onClick}>
|
||||
{title}
|
||||
<div>{description}</div>
|
||||
</AccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
const spaceNameValidator = withValidation({
|
||||
rules: [
|
||||
{
|
||||
@@ -285,16 +272,16 @@ const SpaceCreateMenu: React.FC<{
|
||||
<h2>{_t("create_space|label")}</h2>
|
||||
<p>{_t("create_space|explainer")}</p>
|
||||
|
||||
<SpaceCreateMenuType
|
||||
<SpacePillButton
|
||||
icon={<PublicIcon />}
|
||||
title={_t("common|public")}
|
||||
description={_t("create_space|public_description")}
|
||||
className="mx_SpaceCreateMenuType_public"
|
||||
onClick={() => setVisibility(Visibility.Public)}
|
||||
/>
|
||||
<SpaceCreateMenuType
|
||||
<SpacePillButton
|
||||
icon={<LockSolidIcon />}
|
||||
title={_t("common|private")}
|
||||
description={_t("create_space|private_description")}
|
||||
className="mx_SpaceCreateMenuType_private"
|
||||
onClick={() => setVisibility(Visibility.Private)}
|
||||
/>
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ import React, {
|
||||
import { DragDropContext, Draggable, Droppable, type DroppableProvidedProps } from "react-beautiful-dnd";
|
||||
import classNames from "classnames";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
FavouriteSolidIcon,
|
||||
HomeSolidIcon,
|
||||
RoomIcon,
|
||||
VideoCallSolidIcon,
|
||||
UserProfileSolidIcon,
|
||||
PlusIcon,
|
||||
ChevronRightIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { useContextMenu } from "../../structures/ContextMenu";
|
||||
@@ -114,6 +123,7 @@ export const HomeButtonContextMenu: React.FC<ComponentProps<typeof SpaceContextM
|
||||
interface IMetaSpaceButtonProps extends ComponentProps<typeof SpaceButton> {
|
||||
selected: boolean;
|
||||
isPanelCollapsed: boolean;
|
||||
icon: JSX.Element;
|
||||
}
|
||||
|
||||
type MetaSpaceButtonProps = Pick<IMetaSpaceButtonProps, "selected" | "isPanelCollapsed">;
|
||||
@@ -152,7 +162,6 @@ const HomeButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCollapsed
|
||||
return (
|
||||
<MetaSpaceButton
|
||||
spaceKey={MetaSpace.Home}
|
||||
className="mx_SpaceButton_home"
|
||||
selected={selected}
|
||||
isPanelCollapsed={isPanelCollapsed}
|
||||
label={getMetaSpaceName(MetaSpace.Home, allRoomsInHome)}
|
||||
@@ -160,6 +169,7 @@ const HomeButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCollapsed
|
||||
ContextMenuComponent={HomeButtonContextMenu}
|
||||
contextMenuTooltip={_t("common|options")}
|
||||
size="32px"
|
||||
icon={<HomeSolidIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -168,12 +178,12 @@ const FavouritesButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCol
|
||||
return (
|
||||
<MetaSpaceButton
|
||||
spaceKey={MetaSpace.Favourites}
|
||||
className="mx_SpaceButton_favourites"
|
||||
selected={selected}
|
||||
isPanelCollapsed={isPanelCollapsed}
|
||||
label={getMetaSpaceName(MetaSpace.Favourites)}
|
||||
notificationState={SpaceStore.instance.getNotificationState(MetaSpace.Favourites)}
|
||||
size="32px"
|
||||
icon={<FavouriteSolidIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -182,12 +192,12 @@ const PeopleButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCollaps
|
||||
return (
|
||||
<MetaSpaceButton
|
||||
spaceKey={MetaSpace.People}
|
||||
className="mx_SpaceButton_people"
|
||||
selected={selected}
|
||||
isPanelCollapsed={isPanelCollapsed}
|
||||
label={getMetaSpaceName(MetaSpace.People)}
|
||||
notificationState={SpaceStore.instance.getNotificationState(MetaSpace.People)}
|
||||
size="32px"
|
||||
icon={<UserProfileSolidIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -196,12 +206,12 @@ const OrphansButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCollap
|
||||
return (
|
||||
<MetaSpaceButton
|
||||
spaceKey={MetaSpace.Orphans}
|
||||
className="mx_SpaceButton_orphans"
|
||||
selected={selected}
|
||||
isPanelCollapsed={isPanelCollapsed}
|
||||
label={getMetaSpaceName(MetaSpace.Orphans)}
|
||||
notificationState={SpaceStore.instance.getNotificationState(MetaSpace.Orphans)}
|
||||
size="32px"
|
||||
icon={<RoomIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -210,12 +220,12 @@ const VideoRoomsButton: React.FC<MetaSpaceButtonProps> = ({ selected, isPanelCol
|
||||
return (
|
||||
<MetaSpaceButton
|
||||
spaceKey={MetaSpace.VideoRooms}
|
||||
className="mx_SpaceButton_videoRooms"
|
||||
selected={selected}
|
||||
isPanelCollapsed={isPanelCollapsed}
|
||||
label={getMetaSpaceName(MetaSpace.VideoRooms)}
|
||||
notificationState={SpaceStore.instance.getNotificationState(MetaSpace.VideoRooms)}
|
||||
size="32px"
|
||||
icon={<VideoCallSolidIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -262,6 +272,7 @@ const CreateSpaceButton: React.FC<Pick<IInnerSpacePanelProps, "isPanelCollapsed"
|
||||
isNarrow={isPanelCollapsed}
|
||||
innerRef={handle}
|
||||
size="32px"
|
||||
icon={<PlusIcon />}
|
||||
/>
|
||||
|
||||
{contextMenu}
|
||||
@@ -449,7 +460,9 @@ const SpacePanel: React.FC = () => {
|
||||
className="mx_SpacePanel_Tooltip_KeyboardShortcut"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
>
|
||||
<ChevronRightIcon />
|
||||
</AccessibleButton>
|
||||
</UserMenu>
|
||||
<Droppable droppableId="top-level-spaces">
|
||||
{(provided, snapshot) => (
|
||||
|
||||
@@ -9,15 +9,17 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { useState } from "react";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { LinkIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { copyPlaintext } from "../../../utils/strings";
|
||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||
import { showRoomInviteDialog } from "../../../RoomInvite";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../settings/UIFeature";
|
||||
import { Icon as InviteIcon } from "../../../../res/img/element-icons/room/invite.svg";
|
||||
import SpacePillButton from "../../structures/SpacePillButton.tsx";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
@@ -29,8 +31,10 @@ const SpacePublicShare: React.FC<IProps> = ({ space, onFinished }) => {
|
||||
|
||||
return (
|
||||
<div className="mx_SpacePublicShare">
|
||||
<AccessibleButton
|
||||
className="mx_SpacePublicShare_shareButton"
|
||||
<SpacePillButton
|
||||
icon={<LinkIcon />}
|
||||
title={_t("space|invite_link")}
|
||||
description={copiedText}
|
||||
onClick={async (): Promise<void> => {
|
||||
const permalinkCreator = new RoomPermalinkCreator(space);
|
||||
permalinkCreator.load();
|
||||
@@ -43,22 +47,18 @@ const SpacePublicShare: React.FC<IProps> = ({ space, onFinished }) => {
|
||||
setCopiedText(_t("action|click_to_copy"));
|
||||
}
|
||||
}}
|
||||
>
|
||||
{_t("space|invite_link")}
|
||||
<div>{copiedText}</div>
|
||||
</AccessibleButton>
|
||||
/>
|
||||
{space.canInvite(MatrixClientPeg.safeGet().getSafeUserId()) &&
|
||||
shouldShowComponent(UIComponent.InviteUsers) ? (
|
||||
<AccessibleButton
|
||||
className="mx_SpacePublicShare_inviteButton"
|
||||
<SpacePillButton
|
||||
icon={<InviteIcon />}
|
||||
title={_t("space|invite")}
|
||||
description={_t("space|invite_description")}
|
||||
onClick={() => {
|
||||
if (onFinished) onFinished();
|
||||
showRoomInviteDialog(space.roomId);
|
||||
}}
|
||||
>
|
||||
{_t("space|invite")}
|
||||
<div>{_t("space|invite_description")}</div>
|
||||
</AccessibleButton>
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -20,6 +20,11 @@ import classNames from "classnames";
|
||||
import { type Room, RoomEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { type DraggableProvidedDragHandleProps } from "react-beautiful-dnd";
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronRightIcon,
|
||||
OverflowHorizontalIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import RoomAvatar from "../avatars/RoomAvatar";
|
||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||
@@ -169,7 +174,9 @@ export const SpaceButton = <T extends keyof HTMLElementTagNameMap>({
|
||||
onClick={openMenu}
|
||||
title={contextMenuTooltip}
|
||||
isExpanded={menuDisplayed}
|
||||
/>
|
||||
>
|
||||
<OverflowHorizontalIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
)}
|
||||
|
||||
{contextMenu}
|
||||
@@ -349,7 +356,9 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
|
||||
onClick={this.toggleCollapse}
|
||||
tabIndex={-1}
|
||||
aria-label={collapsed ? _t("action|expand") : _t("action|collapse")}
|
||||
/>
|
||||
>
|
||||
{collapsed ? <ChevronRightIcon /> : <ChevronDownIcon />}
|
||||
</AccessibleButton>
|
||||
) : null;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
Reference in New Issue
Block a user