(demo) add theme selector

As we aims to create several themes for this demo app, we add a select
to easily switch between all existing themes.
This commit is contained in:
jbpenrath
2024-02-14 00:37:50 +01:00
committed by Jean-Baptiste PENRATH
parent be1e2e2614
commit 0ade12251e
2 changed files with 82 additions and 18 deletions

View File

@@ -1,13 +1,24 @@
import { Button, CunninghamProvider } from "@openfun/cunningham-react";
import React, { useEffect, useState } from "react";
import { Button, CunninghamProvider, Select } from "@openfun/cunningham-react";
import React, { useEffect, useMemo, useState } from "react";
import { Create } from "./Create";
import { Home } from "./Home";
enum Theme {
DEFAULT = "default",
CUNNINGHAM = "cunningham",
}
enum Variant {
LIGHT = "light",
DARK = "dark",
}
const THEMES: Record<Theme, Record<Variant, string | undefined>> = {
[Theme.CUNNINGHAM]: {
light: "default",
dark: "dark",
},
};
export enum Page {
HOME,
CREATE,
@@ -19,15 +30,27 @@ export interface PageProps {
const preferredScheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? Theme.DARK
: Theme.DEFAULT;
? { theme: Theme.CUNNINGHAM, variant: Variant.DARK }
: { theme: Theme.CUNNINGHAM, variant: Variant.LIGHT };
export const App = () => {
const [locale] = useState("en-US");
const [theme, setTheme] = useState<Theme>(preferredScheme);
const [theme, setTheme] = useState<Theme>(
(sessionStorage.getItem("c-theme") as Theme | null) ??
preferredScheme.theme,
);
const [variant, setVariant] = useState<Variant>(
(sessionStorage.getItem("c-variant") as Variant | null) ??
preferredScheme.variant,
);
const activeTheme = useMemo(() => THEMES[theme][variant], [theme, variant]);
const [page, setPage] = useState<Page>(Page.HOME);
const handleThemeChange = (event: MediaQueryListEvent) =>
setTheme(event.matches ? Theme.DARK : Theme.DEFAULT);
const handleThemeChange = (event: MediaQueryListEvent) => {
const nextVariant = event.matches ? Variant.DARK : Variant.LIGHT;
if (THEMES[theme][nextVariant] !== undefined) {
setVariant(nextVariant);
}
};
useEffect(() => {
const query = window.matchMedia("(prefers-color-scheme: dark)");
@@ -38,31 +61,66 @@ export const App = () => {
};
}, []);
useEffect(() => {
document.documentElement.setAttribute("data-theme", theme);
document.documentElement.setAttribute("data-variant", variant);
sessionStorage.setItem("c-theme", theme);
sessionStorage.setItem("c-variant", variant);
}, [theme, variant]);
return (
<CunninghamProvider currentLocale={locale} theme={theme}>
<CunninghamProvider currentLocale={locale} theme={activeTheme}>
<div className="container">
{theme === Theme.CUNNINGHAM && (
<img
className="pattern"
src={
theme === Theme.DARK ? "pattern_dark.png" : "pattern_default.png"
variant === Variant.DARK
? "pattern_dark.png"
: "pattern_default.png"
}
alt="Background pattern"
/>
)}
{page === Page.HOME && <Home changePage={(p) => setPage(p)} />}
{page === Page.CREATE && <Create changePage={(p) => setPage(p)} />}
</div>
<div className="theme-switch">
<Select
value={theme}
label="Theme"
clearable={false}
options={Object.keys(THEMES).map((key) => ({
value: key,
label: key[0].toUpperCase() + key.slice(1),
}))}
onChange={(e) => {
setTheme(e.target.value as Theme);
if (THEMES[e.target.value as Theme][variant] === undefined) {
setVariant(
variant === Variant.LIGHT ? Variant.DARK : Variant.LIGHT,
);
}
}}
/>
<Button
color="tertiary"
icon={
<span className="material-icons">
{theme === Theme.DARK ? "light_mode" : "dark_mode"}
{variant === Variant.DARK ? "light_mode" : "dark_mode"}
</span>
}
onClick={() => {
setTheme(theme === Theme.DARK ? Theme.DEFAULT : Theme.DARK);
setVariant(
variant === Variant.LIGHT ? Variant.DARK : Variant.LIGHT,
);
}}
disabled={
THEMES[theme][
variant === Variant.LIGHT ? Variant.DARK : Variant.LIGHT
] === undefined
}
/>
</div>
</CunninghamProvider>

View File

@@ -35,6 +35,12 @@ html {
position: fixed;
right: 1rem;
top: 0.75rem;
display: flex;
align-items: center;
gap: 1rem;
--c--components--forms-field--width: 150px;
}
.card {