Dark Mode Persistence
In Your Web Application

In Your Login Theme
Last updated
Was this helpful?

Last updated
Was this helpful?
Was this helpful?
import { useOidc } from "oidc";
import { useTheme } from "@mui/material/styles";
import Button from "@mui/material/Button";
import { assert } from "tsafe/assert";
export function AuthButtons() {
const { isUserLoggedIn, login } = useOidc();
assert(
!isUserLoggedIn,
"If this component is rendered, the user should not be logged in"
);
const theme = useTheme();
const extraQueryParams = {
dark: theme.palette.mode === "dark" ? "true" : "false",
// ui_locales is a special query param that Keycloak recognizes.
// You can set it to make sure the login pages are
// displayed in the correct language.
ui_locales: "en"
};
return (
<>
<Button
onClick={() =>
login({
doesCurrentHrefRequiresAuth: false,
extraQueryParams
})
}
>
Login
</Button>
<Button
variant="contained"
onClick={() =>
login({
doesCurrentHrefRequiresAuth: false,
transformUrlBeforeRedirect: url => {
const urlObj = new URL(url);
urlObj.pathname = urlObj.pathname.replace(
/\/auth$/,
"/registrations"
);
return urlObj.href;
},
extraQueryParams
})
}
>
Register
</Button>
</>
);
}const SESSION_STORAGE_KEY = "isDark";
function getIsDark(): boolean {
from_url: {
const url = new URL(window.location.href);
const value = url.searchParams.get("dark");
if (value === null) {
// There was no &dark= query param in the URL,
// so we check session storage next.
break from_url;
}
// Remove &dark= from the URL (just to keep it clean)
url.searchParams.delete("dark");
window.history.replaceState({}, "", url.toString());
const isDark = value === "true";
// Persist the value in session storage so that
// if the user navigates, for example, from login.ftl to
// register.ftl, we don’t lose the state.
sessionStorage.setItem(SESSION_STORAGE_KEY, `${isDark}`);
return isDark;
}
from_session_storage: {
const value = sessionStorage.getItem(SESSION_STORAGE_KEY);
if (value === null) {
break from_session_storage;
}
return value === "true";
}
// Return the browser preference
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}import type { KcContext } from "./KcContext";
import { useI18n } from "./i18n";
import DefaultPage from "keycloakify/login/DefaultPage";
import Template from "keycloakify/login/Template";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { getIsDark } from "../shared/isDark";
const UserProfileFormFields = lazy(() => import("keycloakify/login/UserProfileFormFields"));
const doMakeUserConfirmPassword = true;
const theme_dark = createTheme({
palette: {
mode: "dark"
}
});
const theme_light = createTheme({
palette: {
mode: "light"
}
});
export default function KcPage(props: { kcContext: KcContext }) {
return (
<ThemeProvider theme={getIsDark() ? theme_dark : theme_light}>
<KcPageContextualized {...props} />
</ThemeProvider>
);
}
function KcPageContextualized(props: { kcContext: KcContext }) {
const { kcContext } = props;
const { i18n } = useI18n({ kcContext });
return (
<Suspense>
{(() => {
switch (kcContext.pageId) {
default:
return (
<DefaultPage
kcContext={kcContext}
i18n={i18n}
classes={classes}
Template={Template}
doUseDefaultCss={true}
UserProfileFormFields={UserProfileFormFields}
doMakeUserConfirmPassword={doMakeUserConfirmPassword}
/>
);
}
})()}
</Suspense>
);
}