Deduplicate icons using Compound Design Tokens (#150)

* Deduplicate icons using Compound Design Tokens

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>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
pull/28192/head
Michael Telatynski 2024-10-14 17:54:15 +01:00 committed by GitHub
parent 63986f8c42
commit d770e2afcc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 82 additions and 93 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -69,8 +69,8 @@ Please see LICENSE files in the repository root for full details.
font-size: $font-12px;
}
.mx_AutocompleteInput_editor_selection_remove_button {
padding: 0 $spacing-4;
.mx_AutocompleteInput_editor_selection_remove_button svg {
vertical-align: middle;
}
.mx_AutocompleteInput_matches {

View File

@ -24,13 +24,13 @@ Please see LICENSE files in the repository root for full details.
cursor: pointer;
.mx_RoomSearch_icon {
width: 16px;
height: 16px;
mask: url("$(res)/img/element-icons/roomlist/search.svg");
width: 20px;
height: 20px;
mask-image: url("@vector-im/compound-design-tokens/icons/search.svg");
mask-repeat: no-repeat;
mask-size: contain;
background-color: $secondary-content;
margin-left: 7px;
margin-bottom: 2px;
margin-left: var(--cpd-space-2x);
flex-shrink: 0;
}

View File

@ -53,13 +53,14 @@ Please see LICENSE files in the repository root for full details.
}
.mx_AuthBody_icon {
width: 40px;
width: 44px;
height: 44px;
}
.mx_AuthBody_lockIcon {
color: $secondary-content;
height: 32px;
margin-bottom: -3px; /* tweak to align all icons on different forgot password steps */
width: 32px;
}
.mx_AuthBody_text {

View File

@ -174,8 +174,11 @@ Please see LICENSE files in the repository root for full details.
.mx_InviteDialog_userTile_remove {
display: inline-block;
margin-inline-start: $spacing-4;
vertical-align: middle;
svg {
vertical-align: middle;
}
}
}

View File

@ -1,3 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.0918 17.0489L11.6069 23.7576L26.91 8" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 243 B

View File

@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM6.77698 4.13517C6.71698 3.45117 7.22098 2.85117 7.90498 2.80317C8.57698 2.75517 9.17698 3.25917 9.24898 3.94317V4.13517L8.86498 8.93517C8.82898 9.37917 8.45698 9.71517 8.01298 9.71517H7.94098C7.52098 9.67917 7.19698 9.35517 7.16098 8.93517L6.77698 4.13517ZM9.0564 12.0673C9.0564 12.6505 8.58361 13.1233 8.0004 13.1233C7.41719 13.1233 6.9444 12.6505 6.9444 12.0673C6.9444 11.4841 7.41719 11.0113 8.0004 11.0113C8.58361 11.0113 9.0564 11.4841 9.0564 12.0673Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 741 B

View File

@ -1,3 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3333 1.85156C10.2958 1.85156 7.83333 4.314 7.83333 7.35156V13.1742H7C5.34315 13.1742 4 14.5174 4 16.1742V27.6666C4 29.3234 5.34315 30.6666 7 30.6666H25C26.6569 30.6666 28 29.3234 28 27.6666V16.1742C28 14.5174 26.6569 13.1742 25 13.1742H24.1667V7.35156C24.1667 4.314 21.7042 1.85156 18.6667 1.85156H13.3333ZM21.1667 13.1742V7.35156C21.1667 5.97085 20.0474 4.85156 18.6667 4.85156H13.3333C11.9526 4.85156 10.8333 5.97085 10.8333 7.35156V13.1742H21.1667Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 631 B

View File

@ -1,3 +0,0 @@
<svg width="40" height="29" viewBox="0 0 40 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.260962 2.57584L18.9049 21.1615C19.5449 21.7995 20.5805 21.7995 21.2205 21.1615L39.7726 2.66735C39.9199 3.08419 40 3.53274 40 4V25C40 27.2091 38.2091 29 36 29H4C1.79086 29 0 27.2091 0 25V4C0 3.49835 0.0923447 3.01827 0.260962 2.57584ZM2.58227 0.258515C3.02293 0.0914515 3.50079 0 4 0H36C36.5334 0 37.0424 0.104395 37.5077 0.293868L20.0627 17.6843L2.58227 0.258515Z" fill="#737D8C"/>
</svg>

Before

Width:  |  Height:  |  Size: 537 B

View File

@ -1,3 +0,0 @@
<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1333 8.06667C12.1333 10.3126 10.3126 12.1333 8.06667 12.1333C5.82071 12.1333 4 10.3126 4 8.06667C4 5.82071 5.82071 4 8.06667 4C10.3126 4 12.1333 5.82071 12.1333 8.06667ZM12.9992 11.5994C13.7131 10.6044 14.1333 9.38463 14.1333 8.06667C14.1333 4.71614 11.4172 2 8.06667 2C4.71614 2 2 4.71614 2 8.06667C2 11.4172 4.71614 14.1333 8.06667 14.1333C9.38457 14.1333 10.6043 13.7131 11.5992 12.9993C11.6274 13.0369 11.6586 13.0729 11.6928 13.1071L14.2928 15.7071C14.6833 16.0977 15.3165 16.0977 15.707 15.7071C16.0975 15.3166 16.0975 14.6834 15.707 14.2929L13.107 11.6929C13.0728 11.6587 13.0368 11.6276 12.9992 11.5994Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 772 B

View File

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" transform="translate(1 1)">
<circle cx="6" cy="6" r="6"/>
<path d="M4.254 4.2a1.8 1.8 0 0 1 3.498.6c0 1.2-1.8 1.8-1.8 1.8M6 8.991"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 357 B

View File

@ -1 +0,0 @@
<svg width="58" height="60" viewBox="26 25 6 6" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-5.9%" y="-7.9%" width="111.8%" height="115.8%" filterUnits="objectBoundingBox" id="a"><feOffset dy="2" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="16" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0.473684211 0 0 0 0 1 0 0 0 0.241258741 0" in="shadowBlurOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><g filter="url(#a)" transform="translate(-406 -215)" stroke="#61708B"><path d="M438 240l-6 6M432 240l6 6"/></g></svg>

Before

Width:  |  Height:  |  Size: 693 B

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="14px" height="14px" viewBox="-1 -1 13 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.4.4 (17249) - http://www.bohemiancoding.com/sketch -->
<title>Line + Line</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Line-+-Line" sketch:type="MSLayerGroup" transform="translate(2.000000, 2.000000)" stroke="#4A4A4A" stroke-width="2.82" stroke-linecap="square">
<path d="M4,0.228763834 L4,7.77123617" id="Line" sketch:type="MSShapeGroup"></path>
<path d="M0.228763834,4 L7.77123617,4" id="Line" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 912 B

View File

@ -8,13 +8,12 @@ Please see LICENSE files in the repository root for full details.
import React, { useState, ReactNode, ChangeEvent, KeyboardEvent, useRef, ReactElement } from "react";
import classNames from "classnames";
import { SearchIcon, CloseIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import Autocompleter from "../../autocomplete/AutocompleteProvider";
import { Key } from "../../Keyboard";
import { ICompletion } from "../../autocomplete/Autocompleter";
import AccessibleButton from "../../components/views/elements/AccessibleButton";
import { Icon as PillRemoveIcon } from "../../../res/img/icon-pill-remove.svg";
import { Icon as SearchIcon } from "../../../res/img/element-icons/roomlist/search.svg";
import useFocus from "../../hooks/useFocus";
interface AutocompleteInputProps {
@ -119,7 +118,7 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
onClick={onClickInputArea}
data-testid="autocomplete-editor"
>
<SearchIcon className="mx_AutocompleteInput_search_icon" width={16} height={16} />
<SearchIcon className="mx_AutocompleteInput_search_icon" width="18px" height="18px" />
{selection.map((item) => (
<SelectionItem
key={item.completionId}
@ -179,7 +178,7 @@ const SelectionItem: React.FC<SelectionItemProps> = ({ item, onClick, render })
onClick={() => onClick(item)}
data-testid={`autocomplete-selection-remove-button-${item.completionId}`}
>
<PillRemoveIcon width={8} height={8} />
<CloseIcon width="16px" height="16px" />
</AccessibleButton>
</span>
);

View File

@ -7,8 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { ReactNode } from "react";
import { Icon as WarningBadgeIcon } from "../../../res/img/compound/error-16px.svg";
import { WarningIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
interface ErrorMessageProps {
message: string | ReactNode | null;
@ -19,7 +18,7 @@ interface ErrorMessageProps {
* Reserves two lines to display errors to prevent layout shifts when the error pops up.
*/
export const ErrorMessage: React.FC<ErrorMessageProps> = ({ message }) => {
const icon = message ? <WarningBadgeIcon className="mx_Icon mx_Icon_16" /> : null;
const icon = message ? <WarningIcon className="mx_Icon mx_Icon_16" /> : null;
return (
<div className="mx_ErrorMessage">

View File

@ -11,6 +11,7 @@ Please see LICENSE files in the repository root for full details.
import React, { ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { sleep } from "matrix-js-sdk/src/utils";
import { LockSolidIcon, CheckIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { _t, _td } from "../../../languageHandler";
import Modal from "../../../Modal";
@ -23,8 +24,6 @@ import AuthBody from "../../views/auth/AuthBody";
import PassphraseConfirmField from "../../views/auth/PassphraseConfirmField";
import StyledCheckbox from "../../views/elements/StyledCheckbox";
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
import { Icon as CheckboxIcon } from "../../../../res/img/compound/checkbox-32px.svg";
import { Icon as LockIcon } from "../../../../res/img/compound/padlock-32px.svg";
import QuestionDialog from "../../views/dialogs/QuestionDialog";
import { EnterEmail } from "./forgot-password/EnterEmail";
import { CheckEmail } from "./forgot-password/CheckEmail";
@ -369,7 +368,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
return (
<>
<LockIcon className="mx_AuthBody_lockIcon" />
<LockSolidIcon className="mx_AuthBody_lockIcon" />
<h1>{_t("auth|reset_password_title")}</h1>
<form onSubmit={this.onSubmitForm}>
<fieldset disabled={this.state.phase === Phase.ResettingPassword}>
@ -417,7 +416,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
public renderDone(): JSX.Element {
return (
<>
<CheckboxIcon className="mx_Icon mx_Icon_32 mx_Icon_accent" />
<CheckIcon className="mx_Icon mx_Icon_32 mx_Icon_accent" />
<h1>{_t("auth|reset_password|reset_successful")}</h1>
{this.state.logoutDevices ? <p>{_t("auth|reset_password|devices_logout_success")}</p> : null}
<input

View File

@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { ReactNode, useRef } from "react";
import { EmailSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as EmailIcon } from "../../../../../res/img/element-icons/Email-icon.svg";
import { _t, _td } from "../../../../languageHandler";
import EmailField from "../../../views/auth/EmailField";
import { ErrorMessage } from "../../ErrorMessage";
@ -54,7 +54,7 @@ export const EnterEmail: React.FC<EnterEmailProps> = ({
return (
<>
<EmailIcon className="mx_AuthBody_icon" />
<EmailSolidIcon className="mx_AuthBody_icon" />
<h1>{_t("auth|enter_email_heading")}</h1>
<p className="mx_AuthBody_text">
{_t("auth|enter_email_explainer", { homeserver }, { b: (t) => <strong>{t}</strong> })}

View File

@ -13,6 +13,7 @@ import { KnownMembership } from "matrix-js-sdk/src/types";
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { logger } from "matrix-js-sdk/src/logger";
import { uniqBy } from "lodash";
import { CloseIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as EmailPillAvatarIcon } from "../../../../res/img/icon-email-pill-avatar.svg";
import { _t, _td } from "../../../languageHandler";
@ -123,13 +124,12 @@ class DMUserTile extends React.PureComponent<IDMUserTileProps> {
let closeButton;
if (this.props.onRemove) {
closeButton = (
<AccessibleButton className="mx_InviteDialog_userTile_remove" onClick={this.onRemove}>
<img
src={require("../../../../res/img/icon-pill-remove.svg").default}
alt={_t("action|remove")}
width={8}
height={8}
/>
<AccessibleButton
className="mx_InviteDialog_userTile_remove"
onClick={this.onRemove}
aria-label={_t("action|remove")}
>
<CloseIcon width="16px" height="16px" />
</AccessibleButton>
);
}

View File

@ -11,6 +11,7 @@ Please see LICENSE files in the repository root for full details.
import React from "react";
import { RoomMember } from "matrix-js-sdk/src/matrix";
import { Tooltip } from "@vector-im/compound-web";
import { HelpIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
@ -21,7 +22,6 @@ import BaseAvatar from "../avatars/BaseAvatar";
import Heading from "../typography/Heading";
import AccessibleButton from "./AccessibleButton";
import { parseUrl } from "../../../utils/UrlUtils";
import { Icon as HelpIcon } from "../../../../res/img/feather-customised/help-circle.svg";
interface IProps {
url: string;

View File

@ -10,11 +10,11 @@ import classNames from "classnames";
import React, { forwardRef, ForwardRefExoticComponent, useContext } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api";
import { WarningIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { _t } from "../../../languageHandler";
import { IBodyProps } from "./IBodyProps";
import { LocalDeviceVerificationStateContext } from "../../../contexts/LocalDeviceVerificationStateContext";
import { Icon as WarningBadgeIcon } from "../../../../res/img/compound/error-16px.svg";
function getErrorMessage(mxEvent: MatrixEvent, isVerified: boolean | undefined): string | React.JSX.Element {
switch (mxEvent.decryptionFailureReason) {
@ -41,7 +41,7 @@ function getErrorMessage(mxEvent: MatrixEvent, isVerified: boolean | undefined):
case DecryptionFailureCode.SENDER_IDENTITY_PREVIOUSLY_VERIFIED:
return (
<span>
<WarningBadgeIcon className="mx_Icon mx_Icon_16" />
<WarningIcon className="mx_Icon mx_Icon_16" />
{_t("timeline|decryption_failure|sender_identity_previously_verified")}
</span>
);

View File

@ -66,7 +66,6 @@ interface IProps {
presenceLastActiveAgo: number;
presenceLastTs: number;
presenceCurrentlyActive?: boolean;
showInviteButton: boolean;
onClick(): void;
showPresence: boolean;
subtextLabel?: string;
@ -135,20 +134,6 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
</div>
);
let inviteButton;
if (this.props.showInviteButton) {
inviteButton = (
<div className="mx_EntityTile_invite">
<img
alt={_t("action|invite")}
src={require("../../../../res/img/plus.svg").default}
width="16"
height="16"
/>
</div>
);
}
let powerLabel;
const powerStatus = this.props.powerStatus;
if (powerStatus) {
@ -178,7 +163,6 @@ export default class EntityTile extends React.PureComponent<IProps, IState> {
</div>
{nameAndPresence}
{powerLabel}
{inviteButton}
</AccessibleButton>
</div>
);

View File

@ -7,8 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { Icon as WarningIcon } from "../../../../res/img/compound/error-16px.svg";
import { WarningIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
interface Props {
message: string;

View File

@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { WarningIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Icon as WarningIcon } from "../../../../res/img/compound/error-16px.svg";
import { _t } from "../../../languageHandler";
export const VoiceBroadcastRecordingConnectionError: React.FC = () => {

View File

@ -306,9 +306,21 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
aria-labelledby="floating-ui-86"
class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
>
<div
<svg
class="mx_Icon mx_Icon_12"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 8a1.5 1.5 0 0 0-1.5 1.5 1 1 0 1 1-2 0 3.5 3.5 0 1 1 6.01 2.439c-.122.126-.24.243-.352.355-.287.288-.54.54-.76.824-.293.375-.398.651-.398.882a1 1 0 1 1-2 0c0-.874.407-1.58.819-2.11.305-.392.688-.775 1-1.085l.257-.26A1.5 1.5 0 0 0 12 8Zm1 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
/>
<path
d="M8.1 21.212A9.738 9.738 0 0 0 12 22a9.738 9.738 0 0 0 3.9-.788 10.098 10.098 0 0 0 3.175-2.137c.9-.9 1.613-1.958 2.137-3.175A9.738 9.738 0 0 0 22 12a9.738 9.738 0 0 0-.788-3.9 10.099 10.099 0 0 0-2.137-3.175c-.9-.9-1.958-1.612-3.175-2.137A9.738 9.738 0 0 0 12 2a9.738 9.738 0 0 0-3.9.788 10.099 10.099 0 0 0-3.175 2.137c-.9.9-1.612 1.958-2.137 3.175A9.738 9.738 0 0 0 2 12a9.74 9.74 0 0 0 .788 3.9 10.098 10.098 0 0 0 2.137 3.175c.9.9 1.958 1.613 3.175 2.137Zm9.575-3.537C16.125 19.225 14.233 20 12 20c-2.233 0-4.125-.775-5.675-2.325C4.775 16.125 4 14.233 4 12c0-2.233.775-4.125 2.325-5.675C7.875 4.775 9.767 4 12 4c2.233 0 4.125.775 5.675 2.325C19.225 7.875 20 9.767 20 12c0 2.233-.775 4.125-2.325 5.675Z"
/>
</svg>
</div>
with example.com.
</span>

View File

@ -26,9 +26,23 @@ exports[`DecryptionFailureBody should handle messages from users who change iden
class="mx_DecryptionFailureBody mx_EventTile_content mx_DecryptionFailureVerifiedIdentityChanged"
>
<span>
<div
<svg
class="mx_Icon mx_Icon_16"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.713 17.713A.968.968 0 0 1 12 18a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 17a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 16a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 17a.97.97 0 0 1-.287.713Zm0-4A.968.968 0 0 1 12 14a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 13V9a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 8a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 9v4a.97.97 0 0 1-.287.713Z"
/>
<path
clip-rule="evenodd"
d="M10.264 3.039c.767-1.344 2.705-1.344 3.472 0l8.554 14.969c.762 1.333-.2 2.992-1.736 2.992H3.446c-1.535 0-2.498-1.659-1.736-2.992l8.553-14.969ZM3.446 19 12 4.031l8.554 14.97H3.446Z"
fill-rule="evenodd"
/>
</svg>
Verified identity has changed
</span>
</div>

View File

@ -890,9 +890,23 @@ exports[`VoiceBroadcastPlaybackBody when rendering an error broadcast should ren
<div
class="mx_VoiceBroadcastRecordingConnectionError"
>
<div
<svg
class="mx_Icon mx_Icon_16"
/>
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.713 17.713A.968.968 0 0 1 12 18a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 17a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 16a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 17a.97.97 0 0 1-.287.713Zm0-4A.968.968 0 0 1 12 14a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 13V9a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 8a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 9v4a.97.97 0 0 1-.287.713Z"
/>
<path
clip-rule="evenodd"
d="M10.264 3.039c.767-1.344 2.705-1.344 3.472 0l8.554 14.969c.762 1.333-.2 2.992-1.736 2.992H3.446c-1.535 0-2.498-1.659-1.736-2.992l8.553-14.969ZM3.446 19 12 4.031l8.554 14.97H3.446Z"
fill-rule="evenodd"
/>
</svg>
Unable to play this voice broadcast
</div>
</div>