diff --git a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts index b4eeed7728..53f9c37dd0 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2023 Suguru Hirahara SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -50,8 +50,8 @@ test.describe("Appearance user settings tab", () => { // Click "Show advanced" link button await tab.getByRole("button", { name: "Show advanced" }).click(); - await tab.locator(".mx_Checkbox", { hasText: "Use bundled emoji font" }).click(); - await tab.locator(".mx_Checkbox", { hasText: "Use a system font" }).click(); + await tab.getByLabel("Use bundled emoji font").click(); + await tab.getByLabel("Use a system font").click(); // Assert that the font-family value was removed await expect(page.locator("body")).toHaveCSS("font-family", '""'); diff --git a/playwright/e2e/spaces/spaces.spec.ts b/playwright/e2e/spaces/spaces.spec.ts index dce7515ef0..56c8ae22b8 100644 --- a/playwright/e2e/spaces/spaces.spec.ts +++ b/playwright/e2e/spaces/spaces.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -35,17 +35,18 @@ function spaceCreateOptions(spaceName: string, roomIds: string[] = []): ICreateR name: spaceName, }, }, - ...roomIds.map(spaceChildInitialState), + ...roomIds.map((r) => spaceChildInitialState(r)), ], }; } -function spaceChildInitialState(roomId: string): ICreateRoomOpts["initial_state"]["0"] { +function spaceChildInitialState(roomId: string, order?: string): ICreateRoomOpts["initial_state"]["0"] { return { type: "m.space.child", state_key: roomId, content: { via: [roomId.split(":")[1]], + order, }, }; } @@ -121,9 +122,10 @@ test.describe("Spaces", () => { await page.getByRole("button", { name: "Skip for now" }).click(); // Assert rooms exist in the room list - await expect(page.getByRole("treeitem", { name: "General", exact: true })).toBeVisible(); - await expect(page.getByRole("treeitem", { name: "Random", exact: true })).toBeVisible(); - await expect(page.getByRole("treeitem", { name: "Projects", exact: true })).toBeVisible(); + const roomList = page.getByRole("tree", { name: "Rooms" }); + await expect(roomList.getByRole("treeitem", { name: "General", exact: true })).toBeVisible(); + await expect(roomList.getByRole("treeitem", { name: "Random", exact: true })).toBeVisible(); + await expect(roomList.getByRole("treeitem", { name: "Projects", exact: true })).toBeVisible(); // Assert rooms exist in the space explorer await expect( @@ -155,7 +157,7 @@ test.describe("Spaces", () => { await page.getByRole("button", { name: "Just me" }).click(); - await page.getByText("Sample Room").click({ force: true }); // force click as checkbox size is zero + await page.getByRole("checkbox", { name: "Sample Room" }).click(); // Temporal implementation as multiple elements with the role "button" and name "Add" are found await page.locator(".mx_AddExistingToSpace_footer").getByRole("button", { name: "Add" }).click(); @@ -165,6 +167,50 @@ test.describe("Spaces", () => { ).toBeVisible(); }); + test( + "should allow user to add an existing room to a space after creation", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + await app.client.createRoom({ + name: "Sample Room", + }); + await app.client.createRoom({ + name: "A Room that will not be selected", + }); + + const menu = await openSpaceCreateMenu(page); + await menu.getByRole("button", { name: "Private" }).click(); + + await menu + .locator('.mx_SpaceBasicSettings_avatarContainer input[type="file"]') + .setInputFiles("playwright/sample-files/riot.png"); + await expect(menu.getByRole("textbox", { name: "Address" })).not.toBeVisible(); + await menu + .getByRole("textbox", { name: "Description" }) + .fill("This is a personal space to mourn Riot.im..."); + await menu.getByRole("textbox", { name: "Name" }).fill("This is my Riot"); + await menu.getByRole("textbox", { name: "Name" }).press("Enter"); + + await page.getByRole("button", { name: "Just me" }).click(); + + await page.getByRole("button", { name: "Skip for now" }).click(); + + await page.getByRole("button", { name: "Add room" }).click(); + await page.getByRole("menuitem", { name: "Add existing room" }).click(); + + await page.getByRole("checkbox", { name: "Sample Room" }).click(); + + await expect(page.getByRole("dialog", { name: "Avatar Add existing rooms" })).toMatchScreenshot( + "add-existing-rooms-dialog.png", + ); + + await page.getByRole("button", { name: "Add" }).click(); + await expect( + page.locator(".mx_SpaceHierarchy_list").getByRole("treeitem", { name: "Sample Room" }), + ).toBeVisible(); + }, + ); + test("should allow user to invite another to a space", { tag: "@no-webkit" }, async ({ page, app, user, bot }) => { await app.client.createSpace({ visibility: "public" as any, @@ -291,4 +337,36 @@ test.describe("Spaces", () => { // Assert we get shown the new room intro, and thus not the soft crash screen await expect(page.locator(".mx_NewRoomIntro")).toBeVisible(); }); + + test("should render spaces view", { tag: "@screenshot" }, async ({ page, app, user, axe }) => { + axe.disableRules([ + // Disable this check as it triggers on nested roving tab index elements which are in practice fine + "nested-interactive", + // XXX: We have some known contrast issues here + "color-contrast", + ]); + + const childSpaceId1 = await app.client.createSpace({ + name: "Child Space 1", + initial_state: [], + }); + const childSpaceId2 = await app.client.createSpace({ + name: "Child Space 2", + initial_state: [], + }); + const childSpaceId3 = await app.client.createSpace({ + name: "Child Space 3", + initial_state: [], + }); + await app.client.createSpace({ + name: "Root Space", + initial_state: [ + spaceChildInitialState(childSpaceId1, "a"), + spaceChildInitialState(childSpaceId2, "b"), + spaceChildInitialState(childSpaceId3, "c"), + ], + }); + await app.viewSpaceByName("Root Space"); + await expect(page.locator(".mx_SpaceRoomView")).toMatchScreenshot("space-room-view.png"); + }); }); diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png index d1c320bff1..88d7919dcc 100644 Binary files a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png and b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png differ diff --git a/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png b/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png index 135c669fb0..b40d183830 100644 Binary files a/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png and b/playwright/snapshots/settings/quick-settings-menu.spec.ts/quick-settings-linux.png differ diff --git a/playwright/snapshots/spaces/spaces.spec.ts/add-existing-rooms-dialog-linux.png b/playwright/snapshots/spaces/spaces.spec.ts/add-existing-rooms-dialog-linux.png new file mode 100644 index 0000000000..53ccabf4f2 Binary files /dev/null and b/playwright/snapshots/spaces/spaces.spec.ts/add-existing-rooms-dialog-linux.png differ diff --git a/playwright/snapshots/spaces/spaces.spec.ts/space-room-view-linux.png b/playwright/snapshots/spaces/spaces.spec.ts/space-room-view-linux.png new file mode 100644 index 0000000000..8e627ec9f2 Binary files /dev/null and b/playwright/snapshots/spaces/spaces.spec.ts/space-room-view-linux.png differ diff --git a/res/css/_components.pcss b/res/css/_components.pcss index a3284fb379..bd927c9843 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -128,7 +128,6 @@ @import "./views/dialogs/_AddExistingToSpaceDialog.pcss"; @import "./views/dialogs/_AnalyticsLearnMoreDialog.pcss"; @import "./views/dialogs/_BugReportDialog.pcss"; -@import "./views/dialogs/_BulkRedactDialog.pcss"; @import "./views/dialogs/_ChangelogDialog.pcss"; @import "./views/dialogs/_CompoundDialog.pcss"; @import "./views/dialogs/_ConfirmSpaceUserActionDialog.pcss"; @@ -212,7 +211,6 @@ @import "./views/elements/_ServerPicker.pcss"; @import "./views/elements/_SettingsFlag.pcss"; @import "./views/elements/_Spinner.pcss"; -@import "./views/elements/_StyledCheckbox.pcss"; @import "./views/elements/_StyledRadioButton.pcss"; @import "./views/elements/_SyntaxHighlight.pcss"; @import "./views/elements/_TagComposer.pcss"; diff --git a/res/css/components/views/settings/devices/_SelectableDeviceTile.pcss b/res/css/components/views/settings/devices/_SelectableDeviceTile.pcss index 927a53937f..6743410f80 100644 --- a/res/css/components/views/settings/devices/_SelectableDeviceTile.pcss +++ b/res/css/components/views/settings/devices/_SelectableDeviceTile.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -16,9 +16,9 @@ Please see LICENSE files in the repository root for full details. .mx_SelectableDeviceTile_checkbox { flex: 1 0; - .mx_Checkbox_background + div { - flex: 1 0; - /* override more specific selector */ - margin-left: $spacing-16 !important; + > div { + margin-top: auto; + margin-bottom: auto; + margin-right: var(--cpd-space-1x); } } diff --git a/res/css/structures/_QuickSettingsButton.pcss b/res/css/structures/_QuickSettingsButton.pcss index 52aa2377ac..f4b881f955 100644 --- a/res/css/structures/_QuickSettingsButton.pcss +++ b/res/css/structures/_QuickSettingsButton.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -70,38 +70,26 @@ Please see LICENSE files in the repository root for full details. text-transform: uppercase; color: var(--cpd-color-text-secondary); margin: 20px 0 12px; - } - - .mx_QuickSettingsButton_pinToSidebarHeading { - padding-left: 24px; position: relative; - } - - .mx_Checkbox { - margin-bottom: 8px; - } - - .mx_QuickSettingsButton_favouritesCheckbox, - .mx_QuickSettingsButton_peopleCheckbox { - .mx_Checkbox_background + div { - padding-left: 22px; - position: relative; - margin-left: 6px; - font-size: $font-15px; - line-height: $font-24px; - color: var(--cpd-color-text-primary); - } + display: flex; } .mx_QuickSettingsButton_moreOptionsButton { - padding-left: 22px; - margin-left: 22px; + margin-left: var(--cpd-space-7x); font-size: $font-15px; line-height: $font-24px; color: var(--cpd-color-text-primary); position: relative; margin-bottom: 16px; } + + .mx_QuickSettingsButton_option { + margin-bottom: var(--cpd-space-3x); + label { + /* Correctly line up icons and text. */ + display: flex; + } + } } .mx_QuickSettingsButton_ContextMenuWrapper_new_room_list { @@ -111,15 +99,10 @@ Please see LICENSE files in the repository root for full details. } .mx_QuickSettingsButton_icon { - // TODO remove when all icons have fill=currentColor - * { - fill: $secondary-content; - } + margin-right: var(--cpd-space-1x); color: $secondary-content; - width: 16px; - height: 16px; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); + width: 18px; + height: 18px; + margin-top: auto; + margin-bottom: auto; } diff --git a/res/css/structures/_SpaceHierarchy.pcss b/res/css/structures/_SpaceHierarchy.pcss index 02f39a0b72..c1be2eb142 100644 --- a/res/css/structures/_SpaceHierarchy.pcss +++ b/res/css/structures/_SpaceHierarchy.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -247,15 +247,6 @@ Please see LICENSE files in the repository root for full details. .mx_AccessibleButton_kind_primary_outline { padding: 3px 16px; /* to account for the 1px border */ } - - .mx_Checkbox { - display: inline-flex; - - label { - width: 16px; - height: 16px; - } - } } &:hover, diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.pcss b/res/css/views/dialogs/_AddExistingToSpaceDialog.pcss index 7dc25d6811..cd5cff94a0 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.pcss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -32,6 +32,11 @@ Please see LICENSE files in the repository root for full details. .mx_AddExistingToSpace_section { margin-right: 12px; + ul { + list-style: none; + padding-left: 0; + } + // provides space for scrollbar so that checkbox and scrollbar do not collide &:not(:first-child) { @@ -214,6 +219,12 @@ Please see LICENSE files in the repository root for full details. display: flex; margin-top: 12px; + form { + /* Align checkboxes. */ + margin-top: auto; + margin-bottom: auto; + } + .mx_DecoratedRoomAvatar, /* we can't target .mx_BaseAvatar here as it'll break the decorated avatar styling */ { margin-right: 12px; } @@ -227,8 +238,4 @@ Please see LICENSE files in the repository root for full details. text-overflow: ellipsis; margin-right: 12px; } - - .mx_Checkbox { - align-items: center; - } } diff --git a/res/css/views/dialogs/_BulkRedactDialog.pcss b/res/css/views/dialogs/_BulkRedactDialog.pcss deleted file mode 100644 index 3e274798eb..0000000000 --- a/res/css/views/dialogs/_BulkRedactDialog.pcss +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2021 Robin Townsend - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -.mx_BulkRedactDialog { - .mx_Checkbox, - .mx_BulkRedactDialog_checkboxMicrocopy { - line-height: $font-20px; - } - - .mx_BulkRedactDialog_checkboxMicrocopy { - margin-left: 26px; - color: $secondary-content; - } -} diff --git a/res/css/views/dialogs/_ExportDialog.pcss b/res/css/views/dialogs/_ExportDialog.pcss index 46c0c578c6..cda2fab55f 100644 --- a/res/css/views/dialogs/_ExportDialog.pcss +++ b/res/css/views/dialogs/_ExportDialog.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -43,11 +43,6 @@ Please see LICENSE files in the repository root for full details. .mx_Field_valid.mx_Field:focus-within { border-color: $input-border-color; } - - .mx_Checkbox input[type="checkbox"]:checked + label > .mx_Checkbox_background { - background: $info-plinth-fg-color; - border-color: $info-plinth-fg-color; - } } .mx_ExportDialog_progress { diff --git a/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.pcss b/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.pcss index f77ebf7b6b..ed51968dec 100644 --- a/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.pcss +++ b/res/css/views/dialogs/_ManageRestrictedJoinRuleDialog.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -74,10 +74,6 @@ Please see LICENSE files in the repository root for full details. line-height: $font-15px; color: $tertiary-content; } - - .mx_Checkbox { - align-items: center; - } } } diff --git a/res/css/views/dialogs/_WidgetCapabilitiesPromptDialog.pcss b/res/css/views/dialogs/_WidgetCapabilitiesPromptDialog.pcss index 9e1024b9a4..62805a24ae 100644 --- a/res/css/views/dialogs/_WidgetCapabilitiesPromptDialog.pcss +++ b/res/css/views/dialogs/_WidgetCapabilitiesPromptDialog.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -19,13 +19,6 @@ Please see LICENSE files in the repository root for full details. margin-top: 20px; font-size: $font-15px; line-height: $font-15px; - - .mx_WidgetCapabilitiesPromptDialog_byline { - color: $muted-fg-color; - margin-left: 26px; - font-size: $font-12px; - line-height: $font-12px; - } } .mx_Dialog_buttons { diff --git a/res/css/views/elements/_LabelledCheckbox.pcss b/res/css/views/elements/_LabelledCheckbox.pcss index add8f14998..ffbf749dab 100644 --- a/res/css/views/elements/_LabelledCheckbox.pcss +++ b/res/css/views/elements/_LabelledCheckbox.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -7,26 +7,5 @@ Please see LICENSE files in the repository root for full details. */ .mx_LabelledCheckbox { - display: flex; - gap: 8px; - flex-direction: row; - - .mx_Checkbox { - margin-top: 3px; /* visually align with label text */ - } - - .mx_LabelledCheckbox_labels { - flex: 1; - - .mx_LabelledCheckbox_label { - vertical-align: middle; - } - - .mx_LabelledCheckbox_byline { - display: block; - padding-top: $spacing-4; - color: $muted-fg-color; - font-size: $font-11px; - } - } + margin-top: var(--cpd-space-2x); } diff --git a/res/css/views/elements/_StyledCheckbox.pcss b/res/css/views/elements/_StyledCheckbox.pcss deleted file mode 100644 index 77382d711c..0000000000 --- a/res/css/views/elements/_StyledCheckbox.pcss +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2020 The Matrix.org Foundation C.I.C. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -.mx_Checkbox { - $size: $font-16px; - $border-radius: 0.27rem; - - display: flex; - align-items: flex-start; - - input[type="checkbox"] { - appearance: none; - margin: 0; - padding: 0; - - & + label { - display: flex; - align-items: center; - - flex-grow: 1; - } - - & + label > .mx_Checkbox_background { - display: inline-flex; - position: relative; - - flex-shrink: 0; - - height: $size; - width: $size; - size: 0.5rem; - border: 1px solid var(--cpd-color-border-interactive-primary); - box-sizing: border-box; - border-radius: $border-radius; - - .mx_Checkbox_checkmark { - display: none; - - height: 100%; - width: 100%; - mask-image: url("@vector-im/compound-design-tokens/icons/check.svg"); - mask-position: center; - mask-size: 100%; - mask-repeat: no-repeat; - } - } - - &:checked + label > .mx_Checkbox_background .mx_Checkbox_checkmark { - display: block; - } - - & + label > *:not(.mx_Checkbox_background) { - margin-left: 10px; - } - - &:disabled + label { - cursor: not-allowed; - } - - &:focus-visible { - & + label .mx_Checkbox_background { - @mixin unreal-focus; - } - } - } -} - -.mx_Checkbox.mx_Checkbox_kind_solid input[type="checkbox"] { - & + label > .mx_Checkbox_background .mx_Checkbox_checkmark { - background: var(--cpd-color-icon-on-solid-primary); - } - - &:checked + label > .mx_Checkbox_background { - background: var(--cpd-color-bg-accent-rest); - border-color: var(--cpd-color-bg-accent-rest); - } - - &:checked:disabled + label > .mx_Checkbox_background { - background: var(--cpd-color-bg-action-primary-disabled); - border-color: var(--cpd-color-bg-action-primary-disabled); - } -} - -.mx_Checkbox.mx_Checkbox_kind_outline input[type="checkbox"] { - & + label > .mx_Checkbox_background .mx_Checkbox_checkmark { - background: var(--cpd-color-bg-accent-rest); - } - - &:checked + label > .mx_Checkbox_background { - background: transparent; - border-color: var(--cpd-color-bg-accent-rest); - } -} diff --git a/res/css/views/rooms/_RoomSublist.pcss b/res/css/views/rooms/_RoomSublist.pcss index f5d0e4ed91..7b0da5608e 100644 --- a/res/css/views/rooms/_RoomSublist.pcss +++ b/res/css/views/rooms/_RoomSublist.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -393,8 +393,7 @@ Please see LICENSE files in the repository root for full details. margin-bottom: 4px; } - .mx_StyledRadioButton, - .mx_Checkbox { + .mx_StyledRadioButton { margin-top: 8px; } } diff --git a/res/css/views/settings/tabs/user/_SidebarUserSettingsTab.pcss b/res/css/views/settings/tabs/user/_SidebarUserSettingsTab.pcss index cb360cc898..a8d45f9f77 100644 --- a/res/css/views/settings/tabs/user/_SidebarUserSettingsTab.pcss +++ b/res/css/views/settings/tabs/user/_SidebarUserSettingsTab.pcss @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -14,17 +14,12 @@ Please see LICENSE files in the repository root for full details. } } -.mx_SidebarUserSettingsTab_checkbox { - margin-bottom: $spacing-8; - /* override checkbox styles */ - label { - align-items: flex-start !important; - } - - svg { - height: 16px; - width: 16px; - margin-right: $spacing-8; - margin-bottom: -1px; - } +.mx_SidebarUserSettingsTab_icon { + margin-right: var(--cpd-space-2x); + margin-top: auto; + margin-bottom: auto; +} + +.mx_SidebarUserSettingsTab_checkbox label { + display: flex; } diff --git a/src/accessibility/context_menu/StyledMenuItemCheckbox.tsx b/src/accessibility/context_menu/StyledMenuItemCheckbox.tsx index 472e7bcae2..f208eb1091 100644 --- a/src/accessibility/context_menu/StyledMenuItemCheckbox.tsx +++ b/src/accessibility/context_menu/StyledMenuItemCheckbox.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2019 The Matrix.org Foundation C.I.C. Copyright 2018 New Vector Ltd Copyright 2015, 2016 OpenMarket Ltd @@ -16,13 +16,12 @@ import { KeyBindingAction } from "../KeyboardShortcuts"; import { getKeyBindingsManager } from "../../KeyBindingsManager"; interface IProps extends React.ComponentProps { - label?: string; onChange(): void; // we handle keyup/down ourselves so lose the ChangeEvent onClose(): void; // gets called after onChange on KeyBindingAction.ActivateSelectedButton } // Semantic component for representing a styled role=menuitemcheckbox -export const StyledMenuItemCheckbox: React.FC = ({ children, label, onChange, onClose, ...props }) => { +export const StyledMenuItemCheckbox: React.FC = ({ children, onChange, onClose, ...props }) => { const [onFocus, isActive, ref] = useRovingTabIndex(); const onKeyDown = (e: React.KeyboardEvent): void => { @@ -63,7 +62,6 @@ export const StyledMenuItemCheckbox: React.FC = ({ children, label, onCh = ({ const [showChildren, toggleShowChildren] = useStateToggle(true); const [onFocus, isActive, ref, nodeRef] = useRovingTabIndex(); const [busy, setBusy] = useState(false); + const checkboxLabelId = useId(); const onPreviewClick = (ev: ButtonEvent): void => { ev.preventDefault(); @@ -172,7 +174,14 @@ const Tile: React.FC = ({ let checkbox: ReactElement | undefined; if (onToggleClick) { if (hasPermissions) { - checkbox = ; + checkbox = ( + + ); } else { checkbox = ( = ({ ev.stopPropagation(); }} > - + ); } @@ -248,7 +262,7 @@ const Tile: React.FC = ({
{avatar}
- {name} + {name} {joinedSection} {suggestedSection}
@@ -330,11 +344,14 @@ const Tile: React.FC = ({ }; } + const shouldToggle = hasPermissions && onToggleClick; + return (
  • = ({ mx_SpaceHierarchy_subspace: room.room_type === RoomType.Space, mx_SpaceHierarchy_joining: busy, })} - onClick={hasPermissions && onToggleClick ? onToggleClick : onPreviewClick} + onClick={shouldToggle ? onToggleClick : onPreviewClick} onKeyDown={onKeyDown} ref={ref} onFocus={onFocus} diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 2397c5f81e..c247c3aea9 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -1,12 +1,12 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ -import React, { type ReactElement, type ReactNode, useContext, useMemo, useRef, useState } from "react"; +import React, { type ReactElement, type ReactNode, useContext, useId, useMemo, useRef, useState } from "react"; import classNames from "classnames"; import { type Room, EventType } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; @@ -53,8 +53,9 @@ export const Entry: React.FC<{ checked: boolean; onChange?(value: boolean): void; }> = ({ room, checked, onChange }) => { + const id = useId(); return ( -
  • {room?.isSpaceRoom() ? ( ) : ( @@ -62,11 +63,12 @@ export const Entry: React.FC<{ )} {room.name} onChange(e.currentTarget.checked) : undefined} checked={checked} disabled={!onChange} /> - +
  • ); }; @@ -357,6 +359,7 @@ const defaultRendererFactory =

    {_t(title)}

    = (props) => {

    {_t("user_info|redact|confirm_description_1", { count, user })}

    {_t("user_info|redact|confirm_description_2")}

    - setKeepStateEvents(e.target.checked)}> + setKeepStateEvents(e.target.checked)} + > {_t("user_info|redact|confirm_keep_state_label")} -
    - {_t("user_info|redact|confirm_keep_state_explainer")} -
    = ({ }} autoFocus={true} /> - setCanContact((e.target as HTMLInputElement).checked)} diff --git a/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx b/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx index 7a2e3b35ef..0f16d3d6f6 100644 --- a/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx +++ b/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -44,22 +44,23 @@ const Entry: React.FC<{ } return ( - - - {_t("space|preferences|show_people_in_space", { - spaceName: space.name, - })} - + diff --git a/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx b/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx index bde310788c..2837701673 100644 --- a/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx +++ b/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2020, 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -100,16 +100,12 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent< }); const checkboxRows = orderedCapabilities.map(([cap, isChecked], i) => { const text = CapabilityText.for(cap, this.props.widgetKind); - const byline = text.byline ? ( - {text.byline} - ) : null; return (
    - this.onToggle(cap)}> + this.onToggle(cap)} description={text.byline}> {text.primary} - {byline}
    ); }); diff --git a/src/components/views/elements/LabelledCheckbox.tsx b/src/components/views/elements/LabelledCheckbox.tsx index ea7b5d2b04..ba07ed9201 100644 --- a/src/components/views/elements/LabelledCheckbox.tsx +++ b/src/components/views/elements/LabelledCheckbox.tsx @@ -1,5 +1,5 @@ /* -Copyright 2024 New Vector Ltd. +Copyright 2024,2025 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial @@ -28,13 +28,16 @@ interface IProps { const LabelledCheckbox: React.FC = ({ value, label, byline, disabled, onChange, className }) => { return ( -
  • @@ -226,7 +283,11 @@ exports[`SpaceHierarchy renders 1`] = `
    - Knock room + + Knock room +
    renders 1`] = ` > View
    - - - - +
    +
    +
  • @@ -297,7 +382,11 @@ exports[`SpaceHierarchy renders 1`] = `
    - Nested space + + Nested space +
    renders 1`] = ` > Join
    - - - - +
    +
    +
    renders 1`] = ` />
  • @@ -374,7 +487,11 @@ exports[`SpaceHierarchy renders 1`] = `
    - Nested room + + Nested room +
    renders 1`] = ` Join
    - - - - +
    +
    +
    diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap index 4d2a2d54a4..bb11ed96b2 100644 --- a/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap +++ b/test/unit-tests/components/views/dialogs/__snapshots__/ExportDialog-test.tsx.snap @@ -150,28 +150,53 @@ exports[` renders export dialog 1`] = ` - - -