= ({
{errorText && }
-
+
{_t("auth|check_email_resend_prompt")}
diff --git a/src/components/structures/auth/forgot-password/EnterEmail.tsx b/src/components/structures/auth/forgot-password/EnterEmail.tsx
index 643cb6c9636..75907b2a5e6 100644
--- a/src/components/structures/auth/forgot-password/EnterEmail.tsx
+++ b/src/components/structures/auth/forgot-password/EnterEmail.tsx
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode, useRef } from "react";
import { EmailSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
+import { Button } from "@vector-im/compound-web";
import { _t, _td } from "../../../../languageHandler";
import EmailField from "../../../views/auth/EmailField";
@@ -74,9 +75,9 @@ export const EnterEmail: React.FC = ({
/>
{errorText && }
-
diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx
index 88e9aa06157..113ea833eae 100644
--- a/src/components/views/auth/RegistrationForm.tsx
+++ b/src/components/views/auth/RegistrationForm.tsx
@@ -10,6 +10,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, type BaseSyntheticEvent, type ComponentProps, type ReactNode } from "react";
import { type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
+import { Button } from "@vector-im/compound-web";
import * as Email from "../../../email";
import { looksValid as phoneNumberLooksValid, type PhoneNumberCountryDefinition } from "../../../phonenumber";
@@ -548,12 +549,9 @@ export default class RegistrationForm extends React.PureComponent
+
+ {_t("action|register")}
+
);
let emailHelperText: JSX.Element | undefined;
diff --git a/src/components/views/elements/SSOButtons.tsx b/src/components/views/elements/SSOButtons.tsx
index 52fdef752ca..9f321c42e20 100644
--- a/src/components/views/elements/SSOButtons.tsx
+++ b/src/components/views/elements/SSOButtons.tsx
@@ -6,7 +6,7 @@ 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 React, { type JSX } from "react";
+import React, { type ComponentProps, type JSX } from "react";
import { chunk } from "lodash";
import classNames from "classnames";
import {
@@ -18,12 +18,18 @@ import {
DELEGATED_OIDC_COMPATIBILITY,
} from "matrix-js-sdk/src/matrix";
import { type Signup } from "@matrix-org/analytics-events/types/typescript/Signup";
+import { Button, Tooltip } from "@vector-im/compound-web";
+import { MacIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import PlatformPeg from "../../../PlatformPeg";
-import AccessibleButton from "./AccessibleButton";
import { _t } from "../../../languageHandler";
import { mediaFromMxc } from "../../../customisations/Media";
import { PosthogAnalytics } from "../../../PosthogAnalytics";
+import { Icon as FacebookIcon } from "../../../../res/img/element-icons/brands/facebook.svg";
+import { Icon as GithubIcon } from "../../../../res/img/element-icons/brands/github.svg";
+import { Icon as GitlabIcon } from "../../../../res/img/element-icons/brands/gitlab.svg";
+import { Icon as GoogleIcon } from "../../../../res/img/element-icons/brands/google.svg";
+import { Icon as TwitterIcon } from "../../../../res/img/element-icons/brands/twitter.svg";
interface ISSOButtonProps extends IProps {
idp?: IIdentityProvider;
@@ -31,24 +37,22 @@ interface ISSOButtonProps extends IProps {
action?: SSOAction;
}
-const getIcon = (brand: IdentityProviderBrand | string): string | null => {
+const getIcon = (brand: IdentityProviderBrand | string): typeof FacebookIcon | null => {
switch (brand) {
- /* eslint-disable @typescript-eslint/no-require-imports */
case IdentityProviderBrand.Apple:
- return require("@vector-im/compound-design-tokens/icons/mac.svg").default;
+ return MacIcon;
case IdentityProviderBrand.Facebook:
- return require(`../../../../res/img/element-icons/brands/facebook.svg`).default;
+ return FacebookIcon;
case IdentityProviderBrand.Github:
- return require(`../../../../res/img/element-icons/brands/github.svg`).default;
+ return GithubIcon;
case IdentityProviderBrand.Gitlab:
- return require(`../../../../res/img/element-icons/brands/gitlab.svg`).default;
+ return GitlabIcon;
case IdentityProviderBrand.Google:
- return require(`../../../../res/img/element-icons/brands/google.svg`).default;
+ return GoogleIcon;
case IdentityProviderBrand.Twitter:
- return require(`../../../../res/img/element-icons/brands/twitter.svg`).default;
+ return TwitterIcon;
default:
return null;
- /* eslint-enable @typescript-eslint/no-require-imports */
}
};
@@ -78,10 +82,10 @@ const SSOButton: React.FC = ({
fragmentAfterLogin,
idp,
primary,
- mini,
+ mini: iconOnly,
action,
flow,
- ...props
+ disabled,
}) => {
let label: string;
if (idp) {
@@ -98,43 +102,43 @@ const SSOButton: React.FC = ({
PlatformPeg.get()?.startSingleSignOn(matrixClient, loginType, fragmentAfterLogin, idp?.id, action);
};
+ const commonProps: Partial> & Record<`data-${string}`, string> = {
+ iconOnly,
+ className: classNames("mx_SSOButton", {
+ mx_SSOButton_mini: iconOnly,
+ }),
+ onClick,
+ kind: primary ? "primary" : "secondary",
+ disabled,
+ };
+
let icon: JSX.Element | undefined;
- let brandClass: string | undefined;
- const brandIcon = idp?.brand ? getIcon(idp.brand) : null;
- if (idp?.brand && brandIcon) {
+ const BrandIcon = idp?.brand ? getIcon(idp.brand) : null;
+ if (idp?.brand && BrandIcon) {
const brandName = idp.brand.split(".").pop();
- brandClass = `mx_SSOButton_brand_${brandName}`;
- icon =
;
+ icon = ;
+ commonProps["data-testid"] = `idp-${idp.id}`;
} else if (typeof idp?.icon === "string" && idp.icon.startsWith("mxc://")) {
const src = mediaFromMxc(idp.icon, matrixClient).getSquareThumbnailHttp(24) ?? undefined;
- icon =
;
+ icon =
;
}
- const brandPart = brandClass ? { [brandClass]: brandClass } : undefined;
- const classes = classNames(
- "mx_SSOButton",
- {
- mx_SSOButton_mini: mini,
- mx_SSOButton_default: !idp,
- mx_SSOButton_primary: primary,
- },
- brandPart,
- );
-
- if (mini) {
- // TODO fallback icon
+ // TODO fallback icon
+ if (iconOnly) {
return (
-
- {icon}
-
+
+
+ {icon}
+
+
);
}
return (
-
+
{icon}
{label}
-
+
);
};
diff --git a/test/unit-tests/components/structures/MatrixChat-test.tsx b/test/unit-tests/components/structures/MatrixChat-test.tsx
index fe9676d7533..0612ee2bb87 100644
--- a/test/unit-tests/components/structures/MatrixChat-test.tsx
+++ b/test/unit-tests/components/structures/MatrixChat-test.tsx
@@ -1269,7 +1269,7 @@ describe("", () => {
fireEvent.change(screen.getByLabelText("Password"), { target: { value: password } });
// sign in button is an input
- fireEvent.click(screen.getByDisplayValue("Sign in"));
+ fireEvent.click(screen.getByRole("button", { name: "Sign in" }));
};
beforeEach(() => {
diff --git a/test/unit-tests/components/structures/auth/Login-test.tsx b/test/unit-tests/components/structures/auth/Login-test.tsx
index 872ccbd3d01..431b96a7a7a 100644
--- a/test/unit-tests/components/structures/auth/Login-test.tsx
+++ b/test/unit-tests/components/structures/auth/Login-test.tsx
@@ -281,13 +281,13 @@ describe("Login", function () {
],
});
- const { container } = getComponent();
+ const { container, getByTestId } = getComponent();
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading…"));
for (const idp of idpsWithIcons) {
- const ssoButton = container.querySelector(`.mx_SSOButton.mx_SSOButton_brand_${idp.brand}`);
+ const ssoButton = getByTestId(`idp-${idp.id}`);
expect(ssoButton).toBeTruthy();
- expect(ssoButton?.querySelector(`img[alt="${idp.brand}"]`)).toBeTruthy();
+ expect(ssoButton.childNodes[0]).toHaveAccessibleName(idp.brand);
}
const ssoButtons = container.querySelectorAll(".mx_SSOButton");