Skip to content

Update settings toggles to use consistent design across app. #30169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 57 commits into
base: develop
Choose a base branch
from

Conversation

Half-Shot
Copy link
Member

@Half-Shot Half-Shot commented Jun 19, 2025

Needs element-hq/compound-web#358

This PR effectively changes all the various places we expose a ToggleSwitch (or a handful of places we used a checkbox) to use a standard SettingsToggle switch that always keeps the settings toggle to the left of the label, which provides the best accessibility. This also ensures that all toggles have their descriptions and disabled messages where possible.

This PR is absolutely enormous (sorry!!!!) due to the number of places require to change, so to break the changes down further the following things have been changed:

  • All areas of Element with a toggle switch, which do not have playwright tests, now have playwright tests.
  • Some playwright/jest tests have been adjusted to use the "switch" role, rather than "checkbox" or other less-ideal ways to identify a setting switch.
  • Some areas of Element, such as the legacy settings panel did not use our SettingsFlag component where they could trivially include it. This has been fixed.
  • LabelledToggleSwitch has been removed in favour of Compound's SettingsToggle
  • Due to Radix inputs (from Compouund) requiring components be wrapped in Forms, a careful dance of wrapping aspects of the settings components in forms has been performed.

I'd suggest reviewing by checking the code changes first, then jest, then playwright changes in that order which will make the most sense. While the PR is huge, the majority of the trivial changes are component swicheroos or screenshot tests.

Changes areas with screenshot test:

  • ApperanceTab
  • CreateRoomDialog
  • DeclineInviteDialog
  • DevToolsDialog
  • ReportRoomDialog
  • RoomUpgradeWarningDialog
  • WidgetCapabilitiesPromptDialog
  • WidgetOpenIDPermissionsDialog
    • Looks hard to actually prompt, maybe skip?
  • EnableLiveShare
  • General Room Tab
  • Notifications
  • NotificationSettings (new)
  • SecurityTab
  • RoomSecurityTab
  • VoipRoomSettingsTab
  • PreferencesTab
  • VoiceUserSettingsTab
  • SpaceSettingsVisibilityTab

Checklist

  • Tests written for new code (and old code if feasible).
  • New or updated public/exported symbols have accurate TSDoc documentation.
  • Linter and other CI checks pass.
  • I have licensed the changes to Element by completing the Contributor License Agreement (CLA)

prettier

Updates some more playwright tests

Update more snapshots

Update switch

more fixes

drop .only

last screenshot round

fix video room flake

Remove console.logs

Remove roomId from devtools view.

lint

final screenshot
@Half-Shot Half-Shot force-pushed the hs/update-toggles-to-use-consistent-style branch from 90b60cf to 59df028 Compare July 14, 2025 18:14
@Half-Shot Half-Shot marked this pull request as ready for review July 14, 2025 18:15
Comment on lines +240 to +242
<form
class="_root_19upo_16"
/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea why there's an empty form here? seems odd

@@ -369,4 +369,16 @@ test.describe("Spaces", () => {
await app.viewSpaceByName("Root Space");
await expect(page.locator(".mx_SpaceRoomView")).toMatchScreenshot("space-room-view.png");
});

test("should render spaces visibility settings", { tag: "@screenshot" }, async ({ page, app, user, bot }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could/should we also run the axe a11y suite in the new tests?

{secureBackup}
{eventIndex}
</SettingsSection>
<Form.Root
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be saner to just have a form root span the whole settings tab rather than some things needing one and some things bringing their own?

class="_control_sqdq4_10"
id="radix-«ra»"
name="input"
title=""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems odd, surely if there's no title the attribute should be omitted rather than an empty string?

@@ -310,7 +310,7 @@ describe("<LocationShareMenu />", () => {

fireEvent.click(getByLabelText("Enable live location sharing"));

expect(getByText("OK").hasAttribute("disabled")).toBeFalsy();
expect(getByText("OK")).not.toHaveAttribute("aria-disabled", "true");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did all other tests move to toBeDisabled except this one?

Comment on lines +112 to +113
</form>
</form>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick google suggests nesting forms is not ok https://www.w3.org/TR/html5/forms.html#the-form-element

Flow content, but with no form element descendants.

class="_message_19upo_85 _help-message_19upo_91"
id="radix-«rg»"
>
settings|send_read_receipts_unsupported
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right

Comment on lines +1349 to +1355
<input
class="_input_19o42_24"
disabled=""
id="mx_SettingsFlag_cmt3PZSyNp3v"
role="switch"
type="checkbox"
/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any clue why some switches snapshot with checked="" some without any checked attribute?

await encryptedToggle.click();

// Accept the dialog.
await page.getByRole("button", { name: "Ok " }).click();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the name have a trailing space?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The margin between the switches & global seems to have gone walkies

image

Also between Global & M&K sections

Copy link
Member

@andybalaam andybalaam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from a purely crypto point of view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants