Allow the Login screen to use the dark theme (#31293)

* Allow the Login screen to use the dark theme

There is a whole bunch of code dedicated to attempting to force a "light" theme
onto the login view, even if the deployment is configured to prioritise the
dark theme.

Apparently this was done because, in the old days, the
login view looked rubbish with the dark theme, but now it looks fine.

Fixes https://github.com/element-hq/element-web/issues/31292

* Fix up background colour of auth screen in dark theme

In dark theme, the background of the login/register/welcome box needs to be
translucent black rather than translucent white.

To make this work, I've moved the style from inline to CSS, and used a PostCSS
variable to define the colour.

* Fix up Welcome page colours in dark theme

Make the text and image white, not black, in short.

* Fix incorrect merge

that will teach me to use the Github UI to address merge conflicts.
This commit is contained in:
Richard van der Hoff 2025-11-26 07:54:40 +00:00 committed by GitHub
parent 8753a9136f
commit 5f07fbbc1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 21 additions and 50 deletions

View File

@ -29,8 +29,13 @@ Please see LICENSE files in the repository root for full details.
margin-top: 0;
}
/* Apply a blurred shadow around the modal */
&.mx_AuthPage_modal_withBlur {
/* Apply a blurred shadow around the modal */
box-shadow: 0 2px 4px 0 rgb(0, 0, 0, 0.33);
.mx_AuthPage_modalContent {
/* Make the modal's background semitransparent */
background-color: $authpage-modal-content-with-blur-bg-color;
}
}
}

View File

@ -20,3 +20,8 @@ Please see LICENSE files in the repository root for full details.
width: 160px;
margin-bottom: 10px;
}
/* Invert image colours in dark mode. */
.cpd-theme-dark .mx_WelcomePage_logo {
filter: invert(1);
}

View File

@ -176,6 +176,8 @@ $togglesw-off-color: $room-highlight-color;
/* Authpage */
/* ******************** */
$authpage-primary-color: $primary-content;
/* background colour of the modal, when the background is blurred */
$authpage-modal-content-with-blur-bg-color: rgb(0, 0, 0, 0.59);
/* ******************** */
/* Message action bar */

View File

@ -275,6 +275,7 @@ $progressbar-bg-color: rgba(141, 151, 165, 0.2);
$authpage-bg-color: #2e3649;
$authpage-modal-bg-color: rgba(255, 255, 255, 0.59);
$authpage-modal-content-with-blur-bg-color: rgb(255, 255, 255, 0.59);
$authpage-focus-bg-color: #dddddd;
$authpage-lang-color: $secondary-content;
$authpage-primary-color: $primary-content;

View File

@ -245,6 +245,8 @@ $togglesw-ball-color: var(--cpd-color-bg-action-primary-rest);
$authpage-primary-color: #232f32;
$authpage-bg-color: #2e3649;
$authpage-modal-bg-color: $roomlist-bg-color;
/* background colour of the modal, when the background is blurred */
$authpage-modal-content-with-blur-bg-color: rgb(255, 255, 255, 0.59);
$authpage-focus-bg-color: $focus-bg-color;
$authpage-lang-color: $secondary-content;
$authpage-primary-color: $primary-content;

View File

@ -27,7 +27,6 @@
align-items: center;
text-align: center;
padding: 25px 35px;
color: #2e2f32;
}
.mx_Logo {

View File

@ -47,7 +47,6 @@ import PageType from "../../PageTypes";
import createRoom, { type IOpts } from "../../createRoom";
import { _t, _td } from "../../languageHandler";
import SettingsStore from "../../settings/SettingsStore";
import ThemeController from "../../settings/controllers/ThemeController";
import { startAnyRegistrationFlow } from "../../Registration";
import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
import { calculateRoomVia, makeRoomPermalink } from "../../utils/permalinks/Permalinks";
@ -1016,8 +1015,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
newState.isMobileRegistration = isMobileRegistration;
this.setStateForNewView(newState);
ThemeController.isLogin = true;
this.themeWatcher?.recheck();
this.notifyNewScreen(isMobileRegistration ? "mobile_register" : "register");
}
@ -1089,8 +1086,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
roomJustCreatedOpts: roomInfo.justCreatedOpts,
},
() => {
ThemeController.isLogin = false;
this.themeWatcher?.recheck();
this.notifyNewScreen("room/" + presentedId, replaceLast);
},
);
@ -1115,8 +1110,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
view: Views.WELCOME,
});
this.notifyNewScreen("welcome");
ThemeController.isLogin = true;
this.themeWatcher?.recheck();
}
private viewLogin(otherState?: any): void {
@ -1125,8 +1118,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
...otherState,
});
this.notifyNewScreen("login");
ThemeController.isLogin = true;
this.themeWatcher?.recheck();
}
private viewHome(justRegistered = false): void {
@ -1138,8 +1129,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
});
this.setPage(PageType.HomePage);
this.notifyNewScreen("home");
ThemeController.isLogin = false;
this.themeWatcher?.recheck();
}
private viewUser(userId: string, subAction: string): void {
@ -1414,8 +1403,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
* crypto is disabled.) XXX: is this a bug or a feature?
*/
private async onLoggedIn(): Promise<void> {
ThemeController.isLogin = false;
this.themeWatcher?.recheck();
StorageManager.tryPersistStorage();
await this.onShowPostLoginScreen();

View File

@ -14,5 +14,5 @@ const matrixSvg = require("../../../res/img/matrix.svg").default;
* Intended to replace $matrixLogo in the welcome page.
*/
export const MATRIX_LOGO_HTML = `<a href="https://matrix.org" target="_blank" rel="noreferrer noopener">
<img width="79" height="34" alt="Matrix" style="padding-left: 1px;vertical-align: middle" src="${matrixSvg}"/>
<img class="mx_WelcomePage_logo" width="79" height="34" alt="Matrix" style="padding-left: 1px;vertical-align: middle" src="${matrixSvg}"/>
</a>`;

View File

@ -75,9 +75,8 @@ export default class AuthPage extends React.PureComponent<React.PropsWithChildre
let modalBlur;
if (this.props.addBlur !== false) {
// Blur out the background: add a `div` which covers the content behind the modal,
// and blurs it out, and make the modal's background semitransparent.
// and blurs it out.
modalBlur = <div className="mx_AuthPage_modalBlur" style={blurStyle} />;
modalContentStyle.background = "rgba(255, 255, 255, 0.59)";
}
const modalClasses = classNames({

View File

@ -12,8 +12,6 @@ import { DEFAULT_THEME, enumerateThemes } from "../../theme";
import { type SettingLevel } from "../SettingLevel";
export default class ThemeController extends SettingController {
public static isLogin = false;
public getValueOverride(
level: SettingLevel,
roomId: string,
@ -22,8 +20,6 @@ export default class ThemeController extends SettingController {
): any {
if (!calculatedValue) return null; // Don't override null themes
if (ThemeController.isLogin) return "light";
const themes = enumerateThemes();
// Override in case some no longer supported theme is stored here
if (!themes[calculatedValue]) {

View File

@ -13,7 +13,6 @@ import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
import SettingsStore from "../SettingsStore";
import dis from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions";
import ThemeController from "../controllers/ThemeController";
import { findHighContrastTheme } from "../../theme";
import { type ActionPayload } from "../../dispatcher/payloads";
import { SettingLevel } from "../SettingLevel";
@ -88,15 +87,6 @@ export default class ThemeWatcher extends TypedEventEmitter<ThemeWatcherEvent, T
public getEffectiveTheme(): string {
// Dev note: Much of this logic is replicated in the AppearanceUserSettingsTab
// XXX: checking the isLight flag here makes checking it in the ThemeController
// itself completely redundant since we just override the result here and we're
// now effectively just using the ThemeController as a place to store the static
// variable. The system theme setting probably ought to have an equivalent
// controller that honours the same flag, although probably better would be to
// have the theme logic in one place rather than split between however many
// different places.
if (ThemeController.isLogin) return "light";
// If the user has specifically enabled the system matching option (excluding default),
// then use that over anything else. We pick the lowest possible level for the setting
// to ensure the ordering otherwise works.

View File

@ -123,7 +123,7 @@ exports[`<MatrixChat /> Multi-tab lockout waits for other tab to stop during sta
<main
aria-live="polite"
class="mx_AuthPage_modalContent"
style="display: flex; z-index: 1; border-radius: inherit; background: rgba(255, 255, 255, 0.59);"
style="display: flex; z-index: 1; border-radius: inherit;"
tabindex="-1"
>
<div
@ -243,7 +243,7 @@ exports[`<MatrixChat /> with a soft-logged-out session should show the soft-logo
<main
aria-live="polite"
class="mx_AuthPage_modalContent"
style="display: flex; z-index: 1; border-radius: inherit; background: rgba(255, 255, 255, 0.59);"
style="display: flex; z-index: 1; border-radius: inherit;"
tabindex="-1"
>
<div

View File

@ -16,7 +16,7 @@ exports[`<AuthPage /> should match snapshot 1`] = `
<main
aria-live="polite"
class="mx_AuthPage_modalContent"
style="display: flex; z-index: 1; border-radius: inherit; background: rgba(255, 255, 255, 0.59);"
style="display: flex; z-index: 1; border-radius: inherit;"
tabindex="-1"
/>
</div>

View File

@ -14,11 +14,6 @@ import { DEFAULT_THEME } from "../../../../src/theme";
describe("ThemeController", () => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue([]);
afterEach(() => {
// reset
ThemeController.isLogin = false;
});
it("returns null when calculatedValue is falsy", () => {
const controller = new ThemeController();
@ -32,16 +27,6 @@ describe("ThemeController", () => {
).toEqual(null);
});
it("returns light when login flag is set", () => {
const controller = new ThemeController();
ThemeController.isLogin = true;
expect(controller.getValueOverride(SettingLevel.ACCOUNT, "$room:server", "dark", SettingLevel.ACCOUNT)).toEqual(
"light",
);
});
it("returns default theme when value is not a valid theme", () => {
const controller = new ThemeController();