diff --git a/frontend/locales/en.json b/frontend/locales/en.json
index 79bf8ee91..4d30b7e28 100644
--- a/frontend/locales/en.json
+++ b/frontend/locales/en.json
@@ -20,6 +20,7 @@
}
},
"common": {
+ "e2ee": "End-to-end encryption",
"loading": "Loading…",
"next": "Next",
"previous": "Previous",
@@ -185,17 +186,28 @@
}
},
"reset_cross_signing": {
- "button": "Allow crypto identity reset",
- "description": "If you are not signed in anywhere else, and have forgotten or lost all recovery options you’ll need to reset your crypto identity. This means you will lose your existing message history, other users will see that you have reset your identity and you will need to verify your existing devices again.",
+ "button": "Reset identity",
+ "cancelled": {
+ "description_1": "You can close this window and go back to the app to continue.",
+ "description_2": "If you're signed out everywhere and don't remember your recovery code, you'll still need to reset your identity.",
+ "heading": "Identity reset cancelled."
+ },
+ "description": "If you're not signed in to any other devices and you've lost your recovery key, then you'll need to reset your identity to continue using the app.",
+ "effect_list": {
+ "negative_1": "You will lose your existing message history",
+ "negative_2": "You will need to verify all your existing devices and contacts again",
+ "positive_1": "Your account details, contacts, preferences, and chat list will be kept"
+ },
"failure": {
"description": "This might be a temporary problem, so please try again later. If the problem persists, please contact your server administrator.",
- "title": "Failed to allow crypto identity"
+ "heading": "Failed to allow crypto identity reset"
},
- "heading": "Reset crypto identity",
+ "heading": "Reset your identity in case you can't confirm another way",
"success": {
- "description": "A client can now temporarily reset your account crypto identity. Follow the instructions in your client to complete the process.",
- "title": "Crypto identity reset temporarily allowed"
- }
+ "description": "The identity reset has been approved for the next {{minutes}} minutes. You can close this window and go back to the app to continue.",
+ "heading": "Identity reset successfully. Go back to the app to finish the process."
+ },
+ "warning": "Only reset your identity if you don't have access to another signed-in device and you've lost your recovery key."
},
"session": {
"client_id_label": "Client ID",
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 35110d16a..c9a35d484 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@fontsource/inconsolata": "^5.0.18",
"@fontsource/inter": "^5.0.20",
+ "@radix-ui/react-collapsible": "1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@tanstack/react-router": "^1.46.7",
"@urql/core": "^5.0.5",
@@ -5211,6 +5212,37 @@
}
}
},
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz",
+ "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-id": "1.0.1",
+ "@radix-ui/react-presence": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-controllable-state": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-collection": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 3e39c8077..351797751 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -19,6 +19,7 @@
"dependencies": {
"@fontsource/inconsolata": "^5.0.18",
"@fontsource/inter": "^5.0.20",
+ "@radix-ui/react-collapsible": "1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@tanstack/react-router": "^1.46.7",
"@urql/core": "^5.0.5",
diff --git a/frontend/src/components/BlockList/BlockList.module.css b/frontend/src/components/BlockList/BlockList.module.css
index 644deeec9..ffaa3099f 100644
--- a/frontend/src/components/BlockList/BlockList.module.css
+++ b/frontend/src/components/BlockList/BlockList.module.css
@@ -17,5 +17,5 @@
display: flex;
flex-direction: column;
align-content: flex-start;
- gap: var(--cpd-space-8x);
+ gap: var(--cpd-space-6x);
}
diff --git a/frontend/src/components/Collapsible/Collapsible.module.css b/frontend/src/components/Collapsible/Collapsible.module.css
new file mode 100644
index 000000000..299daaf6d
--- /dev/null
+++ b/frontend/src/components/Collapsible/Collapsible.module.css
@@ -0,0 +1,32 @@
+/* Copyright 2024 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.trigger {
+ display: flex;
+ width: 100%;
+}
+
+.trigger-title {
+ flex-grow: 1;
+ text-align: start;
+}
+
+[data-state="closed"] .trigger-icon {
+ transform: rotate(180deg);
+}
+
+.content {
+ margin-top: var(--cpd-space-2x);
+}
diff --git a/frontend/src/components/Collapsible/Collapsible.tsx b/frontend/src/components/Collapsible/Collapsible.tsx
new file mode 100644
index 000000000..b1c651cba
--- /dev/null
+++ b/frontend/src/components/Collapsible/Collapsible.tsx
@@ -0,0 +1,50 @@
+// Copyright 2024 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as Collapsible from "@radix-ui/react-collapsible";
+import IconChevronUp from "@vector-im/compound-design-tokens/assets/web/icons/chevron-up";
+import classNames from "classnames";
+
+import styles from "./Collapsible.module.css";
+
+export const Trigger: React.FC<
+ React.ComponentProps
+> = ({ children, className, ...props }) => {
+ return (
+
+
{children}
+
+
+ );
+};
+
+export const Content: React.FC<
+ React.ComponentProps
+> = ({ className, ...props }) => {
+ return (
+
+ );
+};
+
+export const Root = Collapsible.Root;
diff --git a/frontend/src/components/Collapsible/index.ts b/frontend/src/components/Collapsible/index.ts
new file mode 100644
index 000000000..6d8244333
--- /dev/null
+++ b/frontend/src/components/Collapsible/index.ts
@@ -0,0 +1,15 @@
+// Copyright 2024 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+export * from "./Collapsible";
diff --git a/frontend/src/components/PageHeading/PageHeading.module.css b/frontend/src/components/PageHeading/PageHeading.module.css
index 3e043364c..7aa64941d 100644
--- a/frontend/src/components/PageHeading/PageHeading.module.css
+++ b/frontend/src/components/PageHeading/PageHeading.module.css
@@ -63,7 +63,7 @@
text-align: center;
& .title {
- font: var(--cpd-font-heading-lg-semibold);
+ font: var(--cpd-font-heading-md-semibold);
letter-spacing: var(--cpd-font-letter-spacing-heading-xl);
color: var(--cpd-color-text-primary);
text-wrap: balance;
diff --git a/frontend/src/components/SessionDetail/SessionDetails.module.css b/frontend/src/components/SessionDetail/SessionDetails.module.css
index ab72b91c3..101f31392 100644
--- a/frontend/src/components/SessionDetail/SessionDetails.module.css
+++ b/frontend/src/components/SessionDetail/SessionDetails.module.css
@@ -39,25 +39,3 @@
text-overflow: ellipsis;
overflow: hidden;
}
-
-.scope-list {
- display: flex;
- flex-direction: column;
- gap: var(--cpd-space-scale);
- border-radius: var(--cpd-space-5x);
- overflow: hidden;
-}
-
-.scope {
- background: var(--cpd-color-bg-subtle-secondary);
- padding: var(--cpd-space-3x) var(--cpd-space-5x);
- display: flex;
- align-items: center;
- gap: var(--cpd-space-3x);
-}
-
-.scope svg {
- inline-size: var(--cpd-space-6x);
- block-size: var(--cpd-space-6x);
- color: var(--cpd-color-icon-tertiary);
-}
diff --git a/frontend/src/components/SessionDetail/SessionDetails.tsx b/frontend/src/components/SessionDetail/SessionDetails.tsx
index 4027abdf9..ed4df3add 100644
--- a/frontend/src/components/SessionDetail/SessionDetails.tsx
+++ b/frontend/src/components/SessionDetail/SessionDetails.tsx
@@ -25,6 +25,7 @@ import { useTranslation } from "react-i18next";
import Block from "../Block/Block";
import DateTime from "../DateTime";
import LastActive from "../Session/LastActive";
+import { VisualList, VisualListItem } from "../VisualList/VisualList";
import styles from "./SessionDetails.module.css";
@@ -68,12 +69,7 @@ const Scope: React.FC<{ scope: string }> = ({ scope }) => {
return (
<>
{mappedScopes.map(([Icon, text], i) => (
-