You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-20 12:02:22 +03:00
frontend: upgrade compound & simplify the confirmation modal implementation
This commit is contained in:
8
frontend/package-lock.json
generated
8
frontend/package-lock.json
generated
@@ -18,7 +18,7 @@
|
|||||||
"@urql/exchange-refocus": "^1.0.2",
|
"@urql/exchange-refocus": "^1.0.2",
|
||||||
"@urql/exchange-request-policy": "^1.0.2",
|
"@urql/exchange-request-policy": "^1.0.2",
|
||||||
"@vector-im/compound-design-tokens": "^0.0.5",
|
"@vector-im/compound-design-tokens": "^0.0.5",
|
||||||
"@vector-im/compound-web": "^0.4.0",
|
"@vector-im/compound-web": "^0.4.1",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"graphql": "^16.8.0",
|
"graphql": "^16.8.0",
|
||||||
@@ -9321,9 +9321,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vector-im/compound-web": {
|
"node_modules/@vector-im/compound-web": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@vector-im/compound-web/-/compound-web-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vector-im/compound-web/-/compound-web-0.4.1.tgz",
|
||||||
"integrity": "sha512-45pshpwpVBwOwIevKZrnWX718Z+qPvxnrSUv3KY4x4ej+PDMt8Qorxv1n98bB7fgF7vwBHK5PQdjq2kTFit+wQ==",
|
"integrity": "sha512-F1KshkUANrapjSzgzmAnHEnNGnyo22ZVHeg0Kjt15Q6I8TuMlnFJ41F0R6GEVOOnsRFi/8DApnh1pB70BJ7OgA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-form": "^0.0.3",
|
"@radix-ui/react-form": "^0.0.3",
|
||||||
"@radix-ui/react-tooltip": "^1.0.6",
|
"@radix-ui/react-tooltip": "^1.0.6",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
"@urql/exchange-refocus": "^1.0.2",
|
"@urql/exchange-refocus": "^1.0.2",
|
||||||
"@urql/exchange-request-policy": "^1.0.2",
|
"@urql/exchange-request-policy": "^1.0.2",
|
||||||
"@vector-im/compound-design-tokens": "^0.0.5",
|
"@vector-im/compound-design-tokens": "^0.0.5",
|
||||||
"@vector-im/compound-web": "^0.4.0",
|
"@vector-im/compound-web": "^0.4.1",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"graphql": "^16.8.0",
|
"graphql": "^16.8.0",
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ describe("<ConfirmationModal />", () => {
|
|||||||
|
|
||||||
// no cancel button without onDeny
|
// no cancel button without onDeny
|
||||||
expect(screen.queryByText("Cancel")).toBeFalsy();
|
expect(screen.queryByText("Cancel")).toBeFalsy();
|
||||||
|
|
||||||
|
// The dialog does not close on escape
|
||||||
|
fireEvent.keyDown(screen.getByRole("alertdialog"), {
|
||||||
|
key: "Escape",
|
||||||
|
code: "Escape",
|
||||||
|
keyCode: 27,
|
||||||
|
});
|
||||||
|
|
||||||
|
// dialog still open
|
||||||
|
expect(screen.queryByRole("alertdialog")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("calls onConfirm on confirmation", () => {
|
it("calls onConfirm on confirmation", () => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import {
|
|||||||
} from "@radix-ui/react-alert-dialog";
|
} from "@radix-ui/react-alert-dialog";
|
||||||
import { Button } from "@vector-im/compound-web";
|
import { Button } from "@vector-im/compound-web";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { ReactNode, useState } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
import styles from "./ConfirmationModal.module.css";
|
import styles from "./ConfirmationModal.module.css";
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ type Props = {
|
|||||||
/**
|
/**
|
||||||
* Generic confirmation modal
|
* Generic confirmation modal
|
||||||
* controls its own open state
|
* controls its own open state
|
||||||
* calls onDeny on cancel, esc, or overlay click
|
* calls onDeny on cancel or esc
|
||||||
* calls onConfirm on confirm click
|
* calls onConfirm on confirm click
|
||||||
*/
|
*/
|
||||||
const ConfirmationModal: React.FC<React.PropsWithChildren<Props>> = ({
|
const ConfirmationModal: React.FC<React.PropsWithChildren<Props>> = ({
|
||||||
@@ -50,57 +50,41 @@ const ConfirmationModal: React.FC<React.PropsWithChildren<Props>> = ({
|
|||||||
children,
|
children,
|
||||||
trigger,
|
trigger,
|
||||||
title,
|
title,
|
||||||
}) => {
|
}) => (
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
<Root>
|
||||||
|
<Trigger asChild>{trigger}</Trigger>
|
||||||
const onClose = (callback?: () => void) => (): void => {
|
<Portal>
|
||||||
setIsOpen(false);
|
<Overlay className={styles.overlay} />
|
||||||
callback?.();
|
<Content
|
||||||
};
|
className={classNames(styles.content, className)}
|
||||||
|
onEscapeKeyDown={(event): void => {
|
||||||
// radix's autofocus doesn't work for some reason
|
if (onDeny) {
|
||||||
// maybe https://www.radix-ui.com/primitives/docs/guides/composition#your-component-must-forward-ref
|
onDeny();
|
||||||
// when this is replaced with compound's own/wrapped dialog this should be fixed
|
} else {
|
||||||
// until then, focus the cancel button for a deniable modal
|
// if there is no deny callback, we should prevent the escape key from closing the modal
|
||||||
// and continue button otherwise
|
event.preventDefault();
|
||||||
const onOpenAutoFocus = (e: Event): void => {
|
}
|
||||||
const focusButtonKind = onDeny ? "tertiary" : "destructive";
|
}}
|
||||||
(e.target as Element)
|
>
|
||||||
?.querySelector<HTMLButtonElement>(
|
<Title>{title}</Title>
|
||||||
`button[data-kind="${focusButtonKind}"]`,
|
<Description>{children}</Description>
|
||||||
)
|
<div className={styles.buttons}>
|
||||||
?.focus();
|
{onDeny && (
|
||||||
};
|
<Cancel asChild>
|
||||||
return (
|
<Button kind="tertiary" size="sm" onClick={onDeny}>
|
||||||
<Root open={isOpen} onOpenChange={setIsOpen}>
|
Cancel
|
||||||
<Trigger asChild>{trigger}</Trigger>
|
|
||||||
<Portal>
|
|
||||||
<Overlay className={styles.overlay} onClick={onClose(onDeny)} />
|
|
||||||
<Content
|
|
||||||
className={classNames(styles.content, className)}
|
|
||||||
onEscapeKeyDown={onClose(onDeny)}
|
|
||||||
onOpenAutoFocus={onOpenAutoFocus}
|
|
||||||
>
|
|
||||||
<Title>{title}</Title>
|
|
||||||
<Description>{children}</Description>
|
|
||||||
<div className={styles.buttons}>
|
|
||||||
{onDeny && (
|
|
||||||
<Cancel asChild>
|
|
||||||
<Button kind="tertiary" size="sm" onClick={onClose(onDeny)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Cancel>
|
|
||||||
)}
|
|
||||||
<Action asChild>
|
|
||||||
<Button kind="destructive" size="sm" onClick={onClose(onConfirm)}>
|
|
||||||
Continue
|
|
||||||
</Button>
|
</Button>
|
||||||
</Action>
|
</Cancel>
|
||||||
</div>
|
)}
|
||||||
</Content>
|
<Action asChild>
|
||||||
</Portal>
|
<Button kind="destructive" size="sm" onClick={onConfirm}>
|
||||||
</Root>
|
Continue
|
||||||
);
|
</Button>
|
||||||
};
|
</Action>
|
||||||
|
</div>
|
||||||
|
</Content>
|
||||||
|
</Portal>
|
||||||
|
</Root>
|
||||||
|
);
|
||||||
|
|
||||||
export default ConfirmationModal;
|
export default ConfirmationModal;
|
||||||
|
|||||||
Reference in New Issue
Block a user