web: fix theming issues when using automatic (#4898)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-03-10 17:33:03 +01:00 committed by GitHub
parent 0ef333f8ea
commit 59e54901fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 35 deletions

View file

@ -70,7 +70,11 @@ export class AdminInterface extends Interface {
display: none; display: none;
} }
.pf-c-page { .pf-c-page {
background-color: transparent !important; background-color: var(--pf-c-page--BackgroundColor) !important;
}
/* Global page background colour */
:host([theme="dark"]) .pf-c-page {
--pf-c-page--BackgroundColor: var(--ak-dark-background);
} }
`, `,
]; ];

View file

@ -17,6 +17,7 @@ export const EVENT_FLOW_ADVANCE = "ak-flow-advance";
export const EVENT_LOCALE_CHANGE = "ak-locale-change"; export const EVENT_LOCALE_CHANGE = "ak-locale-change";
export const EVENT_REQUEST_POST = "ak-request-post"; export const EVENT_REQUEST_POST = "ak-request-post";
export const EVENT_MESSAGE = "ak-message"; export const EVENT_MESSAGE = "ak-message";
export const EVENT_THEME_CHANGE = "ak-theme-change";
export const WS_MSG_TYPE_MESSAGE = "message"; export const WS_MSG_TYPE_MESSAGE = "message";
export const WS_MSG_TYPE_REFRESH = "refresh"; export const WS_MSG_TYPE_REFRESH = "refresh";

View file

@ -1,5 +1,4 @@
import { EVENT_LOCALE_CHANGE } from "@goauthentik/common/constants"; import { EVENT_LOCALE_CHANGE, EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { uiConfig } from "@goauthentik/common/ui/config"; import { uiConfig } from "@goauthentik/common/ui/config";
import { LitElement } from "lit"; import { LitElement } from "lit";
@ -68,6 +67,10 @@ export class AKElement extends LitElement {
return root; return root;
} }
async getTheme(): Promise<UiThemeEnum> {
return rootInterface()?.getTheme() || UiThemeEnum.Automatic;
}
async _initTheme(root: AdoptedStyleSheetsElement): Promise<void> { async _initTheme(root: AdoptedStyleSheetsElement): Promise<void> {
// Early activate theme based on media query to prevent light flash // Early activate theme based on media query to prevent light flash
// when dark is preferred // when dark is preferred
@ -77,7 +80,7 @@ export class AKElement extends LitElement {
? UiThemeEnum.Light ? UiThemeEnum.Light
: UiThemeEnum.Dark, : UiThemeEnum.Dark,
); );
rootInterface()?._initTheme(root); this._applyTheme(root, await this.getTheme());
} }
private async _initCustomCSS(root: ShadowRoot): Promise<void> { private async _initCustomCSS(root: ShadowRoot): Promise<void> {
@ -120,33 +123,36 @@ export class AKElement extends LitElement {
this._activateTheme(root, theme); this._activateTheme(root, theme);
} }
static themeToStylesheet(theme?: UiThemeEnum): CSSStyleSheet | undefined {
if (theme === UiThemeEnum.Dark) {
return ThemeDark;
}
return undefined;
}
_activateTheme(root: AdoptedStyleSheetsElement, theme: UiThemeEnum) { _activateTheme(root: AdoptedStyleSheetsElement, theme: UiThemeEnum) {
if (this._activeTheme === theme) { console.log("activating theme", theme, this._activeTheme, this);
if (theme === this._activeTheme) {
return; return;
} }
// Make sure we only get to this callback once we've picked a concise theme choice // Make sure we only get to this callback once we've picked a concise theme choice
this.dispatchEvent( this.dispatchEvent(
new CustomEvent("themeChange", { new CustomEvent(EVENT_THEME_CHANGE, {
bubbles: true, bubbles: true,
composed: true, composed: true,
detail: theme, detail: theme,
}), }),
); );
this._activeTheme = theme;
this.setAttribute("theme", theme); this.setAttribute("theme", theme);
let stylesheet: CSSStyleSheet | undefined; const stylesheet = AKElement.themeToStylesheet(theme);
if (theme === UiThemeEnum.Dark) { const oldStylesheet = AKElement.themeToStylesheet(this._activeTheme);
stylesheet = ThemeDark; if (stylesheet) {
}
if (!stylesheet) {
return;
}
if (root.adoptedStyleSheets.indexOf(stylesheet) === -1) {
root.adoptedStyleSheets = [...root.adoptedStyleSheets, stylesheet]; root.adoptedStyleSheets = [...root.adoptedStyleSheets, stylesheet];
} else {
root.adoptedStyleSheets = root.adoptedStyleSheets.filter((v) => v !== stylesheet);
} }
this.requestUpdate(); if (oldStylesheet) {
root.adoptedStyleSheets = root.adoptedStyleSheets.filter((v) => v !== oldStylesheet);
}
this._activeTheme = theme;
} }
disconnectedCallback() { disconnectedCallback() {
@ -161,13 +167,8 @@ export class Interface extends AKElement {
super._activateTheme(document, theme); super._activateTheme(document, theme);
} }
async _initTheme(root: AdoptedStyleSheetsElement): Promise<void> { async getTheme(): Promise<UiThemeEnum> {
const bootstrapTheme = globalAK()?.tenant.uiTheme || UiThemeEnum.Automatic; const config = await uiConfig();
this._applyTheme(root, bootstrapTheme); return config.theme.base;
uiConfig().then((config) => {
if (config.theme.base) {
this._applyTheme(root, config.theme.base);
}
});
} }
} }

View file

@ -13,6 +13,7 @@ import * as yamlMode from "@codemirror/legacy-modes/mode/yaml";
import { Compartment, EditorState, Extension } from "@codemirror/state"; import { Compartment, EditorState, Extension } from "@codemirror/state";
import { oneDark } from "@codemirror/theme-one-dark"; import { oneDark } from "@codemirror/theme-one-dark";
import { EditorView, drawSelection, keymap, lineNumbers } from "@codemirror/view"; import { EditorView, drawSelection, keymap, lineNumbers } from "@codemirror/view";
import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import YAML from "yaml"; import YAML from "yaml";
@ -128,7 +129,7 @@ export class CodeMirrorTextarea<T> extends AKElement {
} }
firstUpdated(): void { firstUpdated(): void {
this.addEventListener("themeChange", ((ev: CustomEvent<UiThemeEnum>) => { this.addEventListener(EVENT_THEME_CHANGE, ((ev: CustomEvent<UiThemeEnum>) => {
if (ev.detail === UiThemeEnum.Dark) { if (ev.detail === UiThemeEnum.Dark) {
this.editor?.dispatch({ this.editor?.dispatch({
effects: this.theme.reconfigure(this.themeDark), effects: this.theme.reconfigure(this.themeDark),

View file

@ -1,4 +1,4 @@
import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { EVENT_REFRESH, EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/EmptyState";
import mermaid, { MermaidConfig } from "mermaid"; import mermaid, { MermaidConfig } from "mermaid";
@ -53,7 +53,7 @@ export class Diagram extends AKElement {
firstUpdated(): void { firstUpdated(): void {
if (this.handlerBound) return; if (this.handlerBound) return;
window.addEventListener(EVENT_REFRESH, this.refreshHandler); window.addEventListener(EVENT_REFRESH, this.refreshHandler);
this.addEventListener("themeChange", ((ev: CustomEvent<UiThemeEnum>) => { this.addEventListener(EVENT_THEME_CHANGE, ((ev: CustomEvent<UiThemeEnum>) => {
if (ev.detail === UiThemeEnum.Dark) { if (ev.detail === UiThemeEnum.Dark) {
this.config.theme = "dark"; this.config.theme = "dark";
} else { } else {

View file

@ -1,4 +1,4 @@
import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { EVENT_REFRESH, EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/EmptyState";
import { import {
@ -93,7 +93,7 @@ export abstract class AKChart<T> extends AKElement {
super.connectedCallback(); super.connectedCallback();
window.addEventListener("resize", this.resizeHandler); window.addEventListener("resize", this.resizeHandler);
this.addEventListener(EVENT_REFRESH, this.refreshHandler); this.addEventListener(EVENT_REFRESH, this.refreshHandler);
this.addEventListener("themeChange", ((ev: CustomEvent<UiThemeEnum>) => { this.addEventListener(EVENT_THEME_CHANGE, ((ev: CustomEvent<UiThemeEnum>) => {
if (ev.detail === UiThemeEnum.Light) { if (ev.detail === UiThemeEnum.Light) {
this.fontColour = FONT_COLOUR_LIGHT_MODE; this.fontColour = FONT_COLOUR_LIGHT_MODE;
} else { } else {

View file

@ -8,7 +8,7 @@ import { globalAK } from "@goauthentik/common/global";
import { configureSentry } from "@goauthentik/common/sentry"; import { configureSentry } from "@goauthentik/common/sentry";
import { first } from "@goauthentik/common/utils"; import { first } from "@goauthentik/common/utils";
import { WebsocketClient } from "@goauthentik/common/ws"; import { WebsocketClient } from "@goauthentik/common/ws";
import { AdoptedStyleSheetsElement, Interface } from "@goauthentik/elements/Base"; import { Interface } from "@goauthentik/elements/Base";
import "@goauthentik/elements/LoadingOverlay"; import "@goauthentik/elements/LoadingOverlay";
import "@goauthentik/flow/stages/FlowErrorStage"; import "@goauthentik/flow/stages/FlowErrorStage";
import "@goauthentik/flow/stages/RedirectStage"; import "@goauthentik/flow/stages/RedirectStage";
@ -182,9 +182,8 @@ export class FlowExecutor extends Interface implements StageHost {
tenant().then((tenant) => (this.tenant = tenant)); tenant().then((tenant) => (this.tenant = tenant));
} }
async _initTheme(root: AdoptedStyleSheetsElement): Promise<void> { async getTheme(): Promise<UiThemeEnum> {
const bootstrapTheme = globalAK()?.tenant.uiTheme || UiThemeEnum.Automatic; return globalAK()?.tenant.uiTheme || UiThemeEnum.Automatic;
this._applyTheme(root, bootstrapTheme);
} }
submit(payload?: FlowChallengeResponseRequest): Promise<boolean> { submit(payload?: FlowChallengeResponseRequest): Promise<boolean> {