From 4958dad672907f17d47968a2ed52b3e9ca1cf4b3 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 4 Dec 2024 14:35:24 +0100 Subject: [PATCH] Refine `SettingsSection` & `SettingsTab` --- res/css/_components.pcss | 1 + res/css/views/settings/_SettingsHeader.pcss | 19 ++++++++ .../views/settings/tabs/_SettingsSection.pcss | 14 ++++++ .../views/settings/SettingsHeader.tsx | 33 +++++++++++++ .../views/settings/shared/SettingsSection.tsx | 46 ++++++++++++++++--- .../views/settings/tabs/SettingsTab.tsx | 7 +-- src/i18n/strings/en_EN.json | 1 + 7 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 res/css/views/settings/_SettingsHeader.pcss create mode 100644 src/components/views/settings/SettingsHeader.tsx diff --git a/res/css/_components.pcss b/res/css/_components.pcss index e9a53cd43c..7426f40799 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -346,6 +346,7 @@ @import "./views/settings/_SetIdServer.pcss"; @import "./views/settings/_SetIntegrationManager.pcss"; @import "./views/settings/_SettingsFieldset.pcss"; +@import "./views/settings/_SettingsHeader.pcss"; @import "./views/settings/_SpellCheckLanguages.pcss"; @import "./views/settings/_ThemeChoicePanel.pcss"; @import "./views/settings/_UpdateCheckButton.pcss"; diff --git a/res/css/views/settings/_SettingsHeader.pcss b/res/css/views/settings/_SettingsHeader.pcss new file mode 100644 index 0000000000..56b3ccea4e --- /dev/null +++ b/res/css/views/settings/_SettingsHeader.pcss @@ -0,0 +1,19 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only + * Please see LICENSE files in the repository root for full details. + */ + +.mx_SettingsHeader { + display: flex; + align-items: center; + gap: var(--cpd-space-2x); + /* Override margin from common.pcss */ + margin: 0; + + > span { + font: var(--cpd-font-body-sm-medium); + color: var(--cpd-color-text-action-accent); + } +} diff --git a/res/css/views/settings/tabs/_SettingsSection.pcss b/res/css/views/settings/tabs/_SettingsSection.pcss index a00350c082..d71a32f484 100644 --- a/res/css/views/settings/tabs/_SettingsSection.pcss +++ b/res/css/views/settings/tabs/_SettingsSection.pcss @@ -15,6 +15,20 @@ Please see LICENSE files in the repository root for full details. a { color: $links; } + + &.mx_SettingsSection_newUi { + display: flex; + flex-direction: column; + gap: var(--cpd-space-6x); + align-items: start; + } + + .mx_SettingsSection_header { + display: flex; + flex-direction: column; + gap: var(--cpd-space-3x); + color: var(--cpd-color-text-secondary); + } } .mx_SettingsSection_subSections { diff --git a/src/components/views/settings/SettingsHeader.tsx b/src/components/views/settings/SettingsHeader.tsx new file mode 100644 index 0000000000..413fb8ffa5 --- /dev/null +++ b/src/components/views/settings/SettingsHeader.tsx @@ -0,0 +1,33 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only + * Please see LICENSE files in the repository root for full details. + */ + +import React, { JSX } from "react"; +import { Heading } from "@vector-im/compound-web"; + +import { _t } from "../../../languageHandler"; + +/** + * The heading for a settings section. + */ +interface SettingsHeaderProps { + /** + * Whether the user has a recommended tag. + */ + hasRecommendedTag?: boolean; + /** + * The label for the header. + */ + label: string; +} + +export function SettingsHeader({ hasRecommendedTag = false, label }: SettingsHeaderProps): JSX.Element { + return ( + + {label} {hasRecommendedTag && {_t("common|recommended")}} + + ); +} diff --git a/src/components/views/settings/shared/SettingsSection.tsx b/src/components/views/settings/shared/SettingsSection.tsx index a42a2a9b78..2ffc14c459 100644 --- a/src/components/views/settings/shared/SettingsSection.tsx +++ b/src/components/views/settings/shared/SettingsSection.tsx @@ -10,19 +10,24 @@ import classnames from "classnames"; import React, { HTMLAttributes } from "react"; import Heading from "../../typography/Heading"; +import { SettingsHeader } from "../SettingsHeader"; export interface SettingsSectionProps extends HTMLAttributes { heading?: string | React.ReactNode; + subHeading?: string | React.ReactNode; children?: React.ReactNode; + legacy?: boolean; } -function renderHeading(heading: string | React.ReactNode | undefined): React.ReactNode | undefined { +function renderHeading(heading: string | React.ReactNode | undefined, legacy: boolean): React.ReactNode | undefined { switch (typeof heading) { case "string": - return ( + return legacy ? ( {heading} + ) : ( + ); case "undefined": return undefined; @@ -31,6 +36,15 @@ function renderHeading(heading: string | React.ReactNode | undefined): React.Rea } } +function renderSubHeading(subHeading: string | React.ReactNode | undefined): React.ReactNode | undefined { + switch (typeof subHeading) { + case "undefined": + return undefined; + default: + return subHeading; + } +} + /** * A section of settings content * A SettingsTab may contain one or more SettingsSections @@ -48,9 +62,29 @@ function renderHeading(heading: string | React.ReactNode | undefined): React.Rea * * ``` */ -export const SettingsSection: React.FC = ({ className, heading, children, ...rest }) => ( -
- {renderHeading(heading)} -
{children}
+export const SettingsSection: React.FC = ({ + className, + heading, + subHeading, + legacy = true, + children, + ...rest +}) => ( +
+ {heading && + (subHeading ? ( +
+ {renderHeading(heading, legacy)} + {renderSubHeading(subHeading)} +
+ ) : ( + renderHeading(heading, legacy) + ))} + {legacy ?
{children}
: children}
); diff --git a/src/components/views/settings/tabs/SettingsTab.tsx b/src/components/views/settings/tabs/SettingsTab.tsx index 7472da22e7..bf6545f2e4 100644 --- a/src/components/views/settings/tabs/SettingsTab.tsx +++ b/src/components/views/settings/tabs/SettingsTab.tsx @@ -6,8 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ import React, { HTMLAttributes } from "react"; +import classNames from "classnames"; -export interface SettingsTabProps extends Omit, "className"> { +export interface SettingsTabProps extends HTMLAttributes { children?: React.ReactNode; } @@ -29,8 +30,8 @@ export interface SettingsTabProps extends Omit, " * * ``` */ -const SettingsTab: React.FC = ({ children, ...rest }) => ( -
+const SettingsTab: React.FC = ({ children, className, ...rest }) => ( +
{children}
); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e9ac73b48b..e53d675e2a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -542,6 +542,7 @@ "qr_code": "QR Code", "random": "Random", "reactions": "Reactions", + "recommended": "Recommended", "report_a_bug": "Report a bug", "room": "Room", "room_name": "Room name",