diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 2bc48d4907..adb30ad194 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -344,7 +344,6 @@ @import "./views/settings/tabs/user/_GeneralUserSettingsTab.pcss"; @import "./views/settings/tabs/user/_HelpUserSettingsTab.pcss"; @import "./views/settings/tabs/user/_KeyboardUserSettingsTab.pcss"; -@import "./views/settings/tabs/user/_LabsUserSettingsTab.pcss"; @import "./views/settings/tabs/user/_MjolnirUserSettingsTab.pcss"; @import "./views/settings/tabs/user/_PreferencesUserSettingsTab.pcss"; @import "./views/settings/tabs/user/_SecurityUserSettingsTab.pcss"; diff --git a/res/css/components/views/settings/shared/_SettingsSubsection.pcss b/res/css/components/views/settings/shared/_SettingsSubsection.pcss index e90585122b..9ab33c9353 100644 --- a/res/css/components/views/settings/shared/_SettingsSubsection.pcss +++ b/res/css/components/views/settings/shared/_SettingsSubsection.pcss @@ -46,4 +46,8 @@ limitations under the License. margin-bottom: $spacing-8; } } + + &.mx_SettingsSubsection_contentStretch { + justify-items: stretch; + } } diff --git a/res/css/views/beta/_BetaCard.pcss b/res/css/views/beta/_BetaCard.pcss index 591fff2d95..62f7d7b93a 100644 --- a/res/css/views/beta/_BetaCard.pcss +++ b/res/css/views/beta/_BetaCard.pcss @@ -15,7 +15,6 @@ limitations under the License. */ .mx_BetaCard { - margin-bottom: $spacing-20; padding: $spacing-24; background-color: $system; border-radius: 8px; @@ -114,10 +113,6 @@ limitations under the License. } } } - - &:last-child { - margin-bottom: 0; - } } .mx_BetaCard_betaPill { diff --git a/res/css/views/elements/_SettingsFlag.pcss b/res/css/views/elements/_SettingsFlag.pcss index b3908a158a..16be54ef3c 100644 --- a/res/css/views/elements/_SettingsFlag.pcss +++ b/res/css/views/elements/_SettingsFlag.pcss @@ -20,6 +20,7 @@ limitations under the License. align-items: flex-start; justify-content: space-between; margin-bottom: 4px; + width: 100%; .mx_ToggleSwitch { flex: 0 0 auto; diff --git a/res/css/views/settings/tabs/user/_LabsUserSettingsTab.pcss b/res/css/views/settings/tabs/user/_LabsUserSettingsTab.pcss deleted file mode 100644 index f10b681668..0000000000 --- a/res/css/views/settings/tabs/user/_LabsUserSettingsTab.pcss +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2021 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. -*/ - -.mx_LabsUserSettingsTab { - .mx_SettingsTab_subsectionText, - .mx_SettingsTab_section { - margin-bottom: var(--SettingsTab_section-margin-bottom-preferences-labs); - } - - .mx_SettingsFlag { - margin-right: 0; /* remove right margin to align with beta cards */ - align-items: center; - } -} diff --git a/src/components/views/settings/shared/SettingsSubsection.tsx b/src/components/views/settings/shared/SettingsSubsection.tsx index 8fcdf327a9..eaf534cab0 100644 --- a/src/components/views/settings/shared/SettingsSubsection.tsx +++ b/src/components/views/settings/shared/SettingsSubsection.tsx @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import classNames from "classnames"; import React, { HTMLAttributes } from "react"; import { SettingsSubsectionHeading } from "./SettingsSubsectionHeading"; @@ -22,6 +23,8 @@ export interface SettingsSubsectionProps extends HTMLAttributes heading: string | React.ReactNode; description?: string | React.ReactNode; children?: React.ReactNode; + // when true content will be justify-items: stretch, which will make items within the section stretch to full width. + stretchContent?: boolean; } export const SettingsSubsectionText: React.FC> = ({ children, ...rest }) => ( @@ -30,7 +33,13 @@ export const SettingsSubsectionText: React.FC> = ); -export const SettingsSubsection: React.FC = ({ heading, description, children, ...rest }) => ( +export const SettingsSubsection: React.FC = ({ + heading, + description, + children, + stretchContent, + ...rest +}) => (
{typeof heading === "string" ? : <>{heading}} {!!description && ( @@ -38,7 +47,13 @@ export const SettingsSubsection: React.FC = ({ heading, {description}
)} -
{children}
+
+ {children} +
); diff --git a/src/components/views/settings/tabs/SettingsTab.tsx b/src/components/views/settings/tabs/SettingsTab.tsx index e9f25ec740..7ecd4d3c5a 100644 --- a/src/components/views/settings/tabs/SettingsTab.tsx +++ b/src/components/views/settings/tabs/SettingsTab.tsx @@ -13,9 +13,9 @@ 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 React from "react"; +import React, { HTMLAttributes } from "react"; -export interface SettingsTabProps { +export interface SettingsTabProps extends Omit, "className"> { children?: React.ReactNode; } @@ -37,8 +37,8 @@ export interface SettingsTabProps { * * ``` */ -const SettingsTab: React.FC = ({ children }) => ( -
+const SettingsTab: React.FC = ({ children, ...rest }) => ( +
{children}
); diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx index f505ebb76f..da6f614780 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx @@ -25,6 +25,9 @@ import BetaCard from "../../../beta/BetaCard"; import SettingsFlag from "../../../elements/SettingsFlag"; import { LabGroup, labGroupNames } from "../../../../../settings/Settings"; import { EnhancedMap } from "../../../../../utils/maps"; +import { SettingsSection } from "../../shared/SettingsSection"; +import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; +import SettingsTab from "../SettingsTab"; export default class LabsUserSettingsTab extends React.Component<{}> { private readonly labs: string[]; @@ -54,11 +57,11 @@ export default class LabsUserSettingsTab extends React.Component<{}> { let betaSection: JSX.Element | undefined; if (this.betas.length) { betaSection = ( -
+ <> {this.betas.map((f) => ( ))} -
+ ); } @@ -93,31 +96,35 @@ export default class LabsUserSettingsTab extends React.Component<{}> { labsSections = ( <> {sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => ( -
- {_t(labGroupNames[group])} + {flags} -
+ ))} ); } return ( -
-
{_t("Upcoming features")}
-
- {_t( - "What's next for %(brand)s? " + - "Labs are the best way to get things early, " + - "test out new features and help shape them before they actually launch.", - { brand: SdkConfig.get("brand") }, - )} -
- {betaSection} + + + + {_t( + "What's next for %(brand)s? " + + "Labs are the best way to get things early, " + + "test out new features and help shape them before they actually launch.", + { brand: SdkConfig.get("brand") }, + )} + + {betaSection} + + {labsSections && ( - <> -
{_t("Early previews")}
-
+ + {_t( "Feeling experimental? " + "Try out our latest ideas in development. " + @@ -139,11 +146,11 @@ export default class LabsUserSettingsTab extends React.Component<{}> { }, }, )} -
+ {labsSections} - + )} -
+ ); } } diff --git a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx index a8001481f6..ead079cdf0 100644 --- a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx +++ b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { render, waitFor } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { defer } from "matrix-js-sdk/src/utils"; import LabsUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab"; @@ -51,17 +51,16 @@ describe("", () => { }); it("renders settings marked as beta as beta cards", () => { - const { getByTestId } = render(getComponent()); - expect(getByTestId("labs-beta-section")).toMatchSnapshot(); + render(getComponent()); + expect(screen.getByText("Upcoming features").parentElement!).toMatchSnapshot(); }); it("does not render non-beta labs settings when disabled in config", () => { - const { container } = render(getComponent()); + render(getComponent()); expect(sdkConfigSpy).toHaveBeenCalledWith("show_labs_settings"); - const labsSections = container.getElementsByClassName("mx_SettingsTab_section"); // only section is beta section - expect(labsSections.length).toEqual(1); + expect(screen.queryByText("Early previews")).not.toBeInTheDocument(); }); it("renders non-beta labs settings when enabled in config", () => { @@ -69,8 +68,10 @@ describe("", () => { sdkConfigSpy.mockImplementation((configName) => configName === "show_labs_settings"); const { container } = render(getComponent()); - const labsSections = container.getElementsByClassName("mx_SettingsTab_section"); - expect(labsSections).toHaveLength(11); + // non-beta labs section + expect(screen.getByText("Early previews")).toBeInTheDocument(); + const labsSections = container.getElementsByClassName("mx_SettingsSubsection"); + expect(labsSections).toHaveLength(10); }); it("allow setting a labs flag which requires unstable support once support is confirmed", async () => { diff --git a/test/components/views/settings/tabs/user/__snapshots__/LabsUserSettingsTab-test.tsx.snap b/test/components/views/settings/tabs/user/__snapshots__/LabsUserSettingsTab-test.tsx.snap index 2d562b8c32..8d7d562809 100644 --- a/test/components/views/settings/tabs/user/__snapshots__/LabsUserSettingsTab-test.tsx.snap +++ b/test/components/views/settings/tabs/user/__snapshots__/LabsUserSettingsTab-test.tsx.snap @@ -2,121 +2,134 @@ exports[` renders settings marked as beta as beta cards 1`] = `
+

+ Upcoming features +

+ What's next for false? Labs are the best way to get things early, test out new features and help shape them before they actually launch. +
+
-

- - Video rooms - - - Beta - -

-
-

- A new way to chat over voice and video in . -

-

- Video rooms are always-on VoIP channels embedded within a room in . -

-
-
+ + Video rooms + + + Beta + +
- Join the beta +

+ A new way to chat over voice and video in . +

+

+ Video rooms are always-on VoIP channels embedded within a room in . +

+
+
+ Join the beta +
+
+
+ Joining the beta will reload . +
+
- Joining the beta will reload . +
-
-
-
-
-
-
-

- - New session manager - - - Beta - -

-
-

- Have greater visibility and control over all your sessions. -

-

- Our new sessions manager provides better visibility of all your sessions, and greater control over them including the ability to remotely toggle push notifications. -

-
-
+ + New session manager + + + Beta + +
- Join the beta +

+ Have greater visibility and control over all your sessions. +

+

+ Our new sessions manager provides better visibility of all your sessions, and greater control over them including the ability to remotely toggle push notifications. +

+
+
+
+ Join the beta +
-
-
- +
+ +