Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Update toast styles to match Figma #12833

Merged
merged 10 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"@sentry/browser": "^8.0.0",
"@testing-library/react-hooks": "^8.0.1",
"@vector-im/compound-design-tokens": "^1.6.1",
"@vector-im/compound-web": "^5.4.0",
"@vector-im/compound-web": "^5.5.0",
"@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4",
"@zxcvbn-ts/language-en": "^3.0.2",
Expand Down
4 changes: 2 additions & 2 deletions playwright/pages/toasts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class Toasts {
*/
public async acceptToast(expectedTitle: string): Promise<void> {
const toast = await this.getToast(expectedTitle);
await toast.locator(".mx_Toast_buttons .mx_AccessibleButton_kind_primary").click();
await toast.locator('.mx_Toast_buttons button[data-kind="primary"]').click();
}

/**
Expand All @@ -55,6 +55,6 @@ export class Toasts {
*/
public async rejectToast(expectedTitle: string): Promise<void> {
const toast = await this.getToast(expectedTitle);
await toast.locator(".mx_Toast_buttons .mx_AccessibleButton_kind_danger_outline").click();
await toast.locator('.mx_Toast_buttons button[data-kind="secondary"]').click();
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 1 addition & 4 deletions res/css/structures/_ToastContainer.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,14 @@ limitations under the License.
overflow: hidden;
text-overflow: ellipsis;
margin: 4px 0 11px 0;
color: $secondary-content;
font: var(--cpd-font-body-sm-regular);

a {
text-decoration: none;
}
}

.mx_Toast_detail {
color: $secondary-content;
}

.mx_Toast_deviceID {
font-size: $font-10px;
}
Expand Down
10 changes: 6 additions & 4 deletions src/SupportedBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
import { logger } from "matrix-js-sdk/src/logger";
import browserlist from "browserslist";
import electronToChromium from "electron-to-chromium/versions";
import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out";

import { DeviceType, parseUserAgent } from "./utils/device/parseUserAgent";
import ToastStore from "./stores/ToastStore";
Expand Down Expand Up @@ -112,10 +113,11 @@ export function checkBrowserSupport(): void {
title: _t("unsupported_browser|title", { brand }),
props: {
description: _t("unsupported_browser|description", { brand }),
acceptLabel: _t("action|learn_more"),
onAccept: onLearnMoreClick,
rejectLabel: _t("action|dismiss"),
onReject: onDismissClick,
secondaryLabel: _t("action|learn_more"),
SecondaryIcon: PopOutIcon,
onSecondaryClick: onLearnMoreClick,
primaryLabel: _t("action|dismiss"),
onPrimaryClick: onDismissClick,
},
component: GenericToast,
priority: 40,
Expand Down
4 changes: 2 additions & 2 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1390,8 +1390,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
title: userNotice.title,
props: {
description: <Linkify>{userNotice.description}</Linkify>,
acceptLabel: _t("action|ok"),
onAccept: () => {
primaryLabel: _t("action|ok"),
onPrimaryClick: () => {
ToastStore.sharedInstance().dismissToast(key);
localStorage.setItem(key, "1");
},
Expand Down
5 changes: 4 additions & 1 deletion src/components/structures/ToastContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ limitations under the License.

import * as React from "react";
import classNames from "classnames";
import { Text } from "@vector-im/compound-web";

import ToastStore, { IToast } from "../../stores/ToastStore";

Expand Down Expand Up @@ -78,7 +79,9 @@ export default class ToastContainer extends React.Component<{}, IState> {
if (title) {
titleElement = (
<div className="mx_Toast_title">
<h2>{title}</h2>
<Text size="lg" weight="semibold" as="h2">
{title}
</Text>
<span className="mx_Toast_title_countIndicator">{countIndicator}</span>
</div>
);
Expand Down
12 changes: 6 additions & 6 deletions src/components/views/toasts/GenericExpiringToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const SECOND = 1000;

const GenericExpiringToast: React.FC<IProps> = ({
description,
acceptLabel,
primaryLabel,
dismissLabel,
onAccept,
onPrimaryClick,
onDismiss,
toastKey,
numSeconds,
Expand All @@ -52,10 +52,10 @@ const GenericExpiringToast: React.FC<IProps> = ({
return (
<GenericToast
description={description}
acceptLabel={acceptLabel}
onAccept={onAccept}
rejectLabel={rejectLabel}
onReject={onReject}
primaryLabel={primaryLabel}
onPrimaryClick={onPrimaryClick}
secondaryLabel={rejectLabel}
onSecondaryClick={onReject}
/>
);
};
Expand Down
50 changes: 33 additions & 17 deletions src/components/views/toasts/GenericToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,37 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { ReactNode } from "react";
import React, { ComponentType, ReactNode } from "react";
import { Button } from "@vector-im/compound-web";

import AccessibleButton from "../elements/AccessibleButton";
import { XOR } from "../../../@types/common";

export interface IProps {
description: ReactNode;
detail?: ReactNode;
acceptLabel: string;
primaryLabel: string;
PrimaryIcon?: ComponentType<React.SVGAttributes<SVGElement>>;

onAccept(): void;
onPrimaryClick(): void;
}

interface IPropsExtended extends IProps {
rejectLabel: string;
onReject(): void;
secondaryLabel: string;
SecondaryIcon?: ComponentType<React.SVGAttributes<SVGElement>>;
destructive?: "primary" | "secondary";
onSecondaryClick(): void;
}

const GenericToast: React.FC<XOR<IPropsExtended, IProps>> = ({
description,
detail,
acceptLabel,
rejectLabel,
onAccept,
onReject,
primaryLabel,
PrimaryIcon,
secondaryLabel,
SecondaryIcon,
destructive,
onPrimaryClick,
onSecondaryClick,
}) => {
const detailContent = detail ? <div className="mx_Toast_detail">{detail}</div> : null;

Expand All @@ -49,14 +55,24 @@ const GenericToast: React.FC<XOR<IPropsExtended, IProps>> = ({
{detailContent}
</div>
<div className="mx_Toast_buttons" aria-live="off">
{onReject && rejectLabel && (
<AccessibleButton kind="danger_outline" onClick={onReject}>
{rejectLabel}
</AccessibleButton>
{onSecondaryClick && secondaryLabel && (
<Button
onClick={onSecondaryClick}
kind={destructive === "secondary" ? "destructive" : "secondary"}
Icon={SecondaryIcon}
size="sm"
>
{secondaryLabel}
</Button>
)}
<AccessibleButton onClick={onAccept} kind="primary">
{acceptLabel}
</AccessibleButton>
<Button
onClick={onPrimaryClick}
kind={destructive === "primary" ? "destructive" : "primary"}
Icon={PrimaryIcon}
size="sm"
>
{primaryLabel}
</Button>
</div>
</div>
);
Expand Down
8 changes: 4 additions & 4 deletions src/components/views/toasts/VerificationRequestToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
<GenericToast
description={description}
detail={detail}
acceptLabel={
primaryLabel={
request.isSelfVerification || !request.roomId
? _t("encryption|verification|request_toast_accept")
: _t("encryption|verification|request_toast_accept_user")
}
onAccept={this.accept}
rejectLabel={declineLabel}
onReject={this.cancel}
onPrimaryClick={this.accept}
secondaryLabel={declineLabel}
onSecondaryClick={this.cancel}
/>
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/stores/LifecycleStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ async function checkServerVersions(): Promise<void> {
version: MINIMUM_MATRIX_VERSION,
brand: SdkConfig.get().brand,
}),
acceptLabel: _t("action|ok"),
onAccept: () => {
primaryLabel: _t("action|ok"),
onPrimaryClick: () => {
ToastStore.sharedInstance().dismissToast(toastKey);
},
},
Expand Down
16 changes: 8 additions & 8 deletions src/toasts/AnalyticsToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ export const showToast = (): void => {
// them to opt in again.
props = {
description: _t("analytics|consent_migration"),
acceptLabel: _t("analytics|accept_button"),
onAccept,
rejectLabel: _t("action|learn_more"),
onReject: onLearnMorePreviouslyOptedIn,
primaryLabel: _t("analytics|accept_button"),
onPrimaryClick: onAccept,
secondaryLabel: _t("action|learn_more"),
onSecondaryClick: onLearnMorePreviouslyOptedIn,
};
} else if (legacyAnalyticsOptIn === null || legacyAnalyticsOptIn === undefined) {
// The user had no analytics setting previously set, so we just need to prompt to opt-in, rather than
Expand All @@ -102,10 +102,10 @@ export const showToast = (): void => {
);
props = {
description: _t("analytics|learn_more", {}, { LearnMoreLink: learnMoreLink }),
acceptLabel: _t("action|yes"),
onAccept,
rejectLabel: _t("action|no"),
onReject,
primaryLabel: _t("action|yes"),
onPrimaryClick: onAccept,
secondaryLabel: _t("action|no"),
onSecondaryClick: onReject,
};
} else {
// false
Expand Down
8 changes: 4 additions & 4 deletions src/toasts/BulkUnverifiedSessionsToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ export const showToast = (deviceIds: Set<string>): void => {
icon: "verification_warning",
props: {
description: _t("encryption|verification|unverified_sessions_toast_description"),
acceptLabel: _t("action|review"),
onAccept,
rejectLabel: _t("encryption|verification|unverified_sessions_toast_reject"),
onReject,
primaryLabel: _t("action|review"),
onPrimaryClick: onAccept,
secondaryLabel: _t("encryption|verification|unverified_sessions_toast_reject"),
onSecondaryClick: onReject,
},
component: GenericToast,
priority: 50,
Expand Down
8 changes: 4 additions & 4 deletions src/toasts/DesktopNotificationsToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ export const showToast = (fromMessageSend: boolean): void => {
: _t("notifications|enable_prompt_toast_title"),
props: {
description: _t("notifications|enable_prompt_toast_description"),
acceptLabel: _t("action|enable"),
onAccept,
rejectLabel: _t("action|dismiss"),
onReject,
primaryLabel: _t("action|enable"),
onPrimaryClick: onAccept,
secondaryLabel: _t("action|dismiss"),
onSecondaryClick: onReject,
},
component: GenericToast,
priority: 30,
Expand Down
8 changes: 4 additions & 4 deletions src/toasts/MobileGuideToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ export const showToast = (): void => {
title: _t("mobile_guide|toast_title"),
props: {
description: _t("mobile_guide|toast_description", { brand }),
acceptLabel: _t("mobile_guide|toast_accept"),
onAccept,
rejectLabel: _t("action|dismiss"),
onReject,
primaryLabel: _t("mobile_guide|toast_accept"),
onPrimaryClick: onAccept,
secondaryLabel: _t("action|dismiss"),
onSecondaryClick: onReject,
},
component: GenericToast,
priority: 99,
Expand Down
4 changes: 2 additions & 2 deletions src/toasts/ServerLimitToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ export const showToast = (
{errorText} {contactText}
</React.Fragment>
),
acceptLabel: _t("action|ok"),
onAccept: () => {
primaryLabel: _t("action|ok"),
onPrimaryClick: () => {
hideToast();
if (onHideToast) onHideToast();
},
Expand Down
9 changes: 5 additions & 4 deletions src/toasts/SetupEncryptionToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,11 @@ export const showToast = (kind: Kind): void => {
icon: getIcon(kind),
props: {
description: getDescription(kind),
acceptLabel: getSetupCaption(kind),
onAccept,
rejectLabel: _t("encryption|verification|unverified_sessions_toast_reject"),
onReject,
primaryLabel: getSetupCaption(kind),
onPrimaryClick: onAccept,
secondaryLabel: _t("encryption|verification|unverified_sessions_toast_reject"),
onSecondaryClick: onReject,
destructive: "secondary",
},
component: GenericToast,
priority: kind === Kind.VERIFY_THIS_SESSION ? 95 : 40,
Expand Down
9 changes: 5 additions & 4 deletions src/toasts/UnverifiedSessionToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ export const showToast = async (deviceId: string): Promise<void> => {
props: {
description: device.display_name,
detail: <DeviceMetaData device={extendedDevice} />,
acceptLabel: _t("encryption|verification|unverified_session_toast_accept"),
onAccept,
rejectLabel: _t("action|no"),
onReject,
primaryLabel: _t("encryption|verification|unverified_session_toast_accept"),
onPrimaryClick: onAccept,
secondaryLabel: _t("action|no"),
onSecondaryClick: onReject,
destructive: "secondary",
},
component: GenericToast,
priority: 80,
Expand Down
8 changes: 4 additions & 4 deletions src/toasts/UpdateToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ export const showToast = (version: string, newVersion: string, releaseNotes?: st
title: _t("update|toast_title", { brand }),
props: {
description: _t("update|toast_description", { brand }),
acceptLabel,
onAccept,
rejectLabel: _t("action|dismiss"),
onReject,
primaryLabel: acceptLabel,
onPrimaryClick: onAccept,
secondaryLabel: _t("action|dismiss"),
onSecondaryClick: onReject,
},
component: GenericToast,
priority: 20,
Expand Down
8 changes: 4 additions & 4 deletions test/components/views/toasts/GenericToast-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import GenericToast from "../../../../src/components/views/toasts/GenericToast";

const renderGenericToast = (props: Partial<ComponentProps<typeof GenericToast>> = {}): RenderResult => {
const propsWithDefaults = {
acceptLabel: "Accept",
primaryLabel: "Accept",
description: <div>Description</div>,
onAccept: () => {},
onReject: () => {},
rejectLabel: "Reject",
onPrimaryClick: () => {},
onSecondaryClick: () => {},
secondaryLabel: "Reject",
...props,
};

Expand Down
Loading
Loading