Skip to content

Commit cd9b4ec

Browse files
committed
Persistent Theme
1 parent 9dfdc21 commit cd9b4ec

File tree

4 files changed

+42
-24
lines changed

4 files changed

+42
-24
lines changed

src/example/src/app.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ export const globalStore = store({
77
appName: 'haydn comley',
88
isNavOpen: false,
99
globalCount: 0,
10+
theme: '',
1011
});
1112

12-
export default (path?: string) => {
13+
export default ({ path, theme }: { path: string, theme: string }) => {
1314
return niceApp(() => {
1415
let trimmedPath = path?.trim();
1516
if (trimmedPath?.endsWith('/')) trimmedPath = trimmedPath.slice(0, -1);
1617
if (trimmedPath?.startsWith('/')) trimmedPath = trimmedPath.slice(1);
18+
globalStore('theme').set(theme);
1719

1820
switch (trimmedPath) {
1921
default:

src/example/src/components/colour-picker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { component, computed, hasWindow, ref, render, state, type Prop, styler,
22

33
import styles from './colour-picker.module.scss'
44

5-
const colors = [
5+
export const colors = [
66
{ label: 'Red', hex: '#dd1364' },
77
{ label: 'Orange', hex: '#fccb19' },
88
{ label: 'Green', hex: '#07d907' },
+13-18
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,41 @@
1-
import { component, computed, hasWindow, ref, render, state } from "../../../nice";
1+
import { component, computed, hasWindow, ref, render, state, valueOf } from "../../../nice";
2+
import { globalStore } from "../app";
23
import { hexToRgb, rgbToHex, shiftHue } from "../lib/utils";
34
import { Button } from "./button";
45
import { ColourPicker } from "./colour-picker";
56

67
import styles from './theme-widget.module.scss'
78

89
export const ThemeWidget = component(() => {
9-
const inputRef = ref<HTMLInputElement>();
10-
const currentColor = state(hasWindow ? getComputedStyle(document.body).getPropertyValue('--theme-primary') : '');
11-
const currentColorHex = computed(() => rgbToHex(currentColor.get()), [currentColor]);
10+
const currentColor = globalStore('theme');
1211
const colourPickerOpen = state(false);
1312

14-
const onColorChange = computed<MouseEvent>((e) => {
15-
const inputElement = e.target as HTMLInputElement;
16-
currentColor.set(hexToRgb(inputElement.value));
17-
});
18-
1913
computed(() => {
2014
if (hasWindow) {
2115
const body = document.querySelector('body');
22-
body!.style.setProperty('--theme-primary', currentColor.get());
23-
body!.style.setProperty('--theme-secondary', shiftHue(currentColor.get(), .2));
16+
body!.style.setProperty('--theme-primary', hexToRgb(valueOf(currentColor)));
17+
body!.style.setProperty('--theme-secondary', shiftHue(hexToRgb(valueOf(currentColor)), .2));
2418
}
2519
}, [currentColor]);
2620

21+
const buttonLabel = computed(() => {
22+
return valueOf(colourPickerOpen) ? 'Close' : 'Choose Theme' as string;
23+
}, [colourPickerOpen]);
24+
2725
const onClick = computed<MouseEvent>(() => {
28-
const input = inputRef.get();
29-
if (!input) return;
3026
colourPickerOpen.set(!colourPickerOpen.get());
3127
});
3228

3329
const onChange = computed<string>((e) => {
34-
console.log('On Change', e);
35-
currentColor.set(hexToRgb(e));
30+
document.cookie = `theme=${e}`;
31+
currentColor.set(e);
3632
colourPickerOpen.set(false);
3733
});
3834

3935
return render`
4036
<div class="${styles.themeWidget}">
41-
${Button({ label: 'Change Theme', onClick })}
42-
<input type="color" ref=${inputRef} on-input=${onColorChange} set-value=${currentColorHex}>
43-
${ColourPicker({ isOpen: colourPickerOpen, onChange: onChange, selected: currentColorHex })}
37+
${Button({ label: buttonLabel, onClick })}
38+
${ColourPicker({ isOpen: colourPickerOpen, onChange: onChange, selected: currentColor })}
4439
</div>
4540
`
4641
});

src/example/src/pages/[...slug].astro

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
---
22
import "../reset.scss";
33
import "../styles.scss";
4-
import app from "../app";
4+
import myApp from "../app";
5+
import { colors } from "../components/colour-picker.ts";
6+
import { hexToRgb, shiftHue } from "../lib/utils";
57
68
const path = Astro.url.pathname;
9+
const theme = Astro.cookies.get("theme")?.value || colors[0].hex;
10+
11+
const app = myApp({ path, theme })!;
12+
const primary = hexToRgb(theme);
13+
const secondary = shiftHue(hexToRgb(theme), 0.2);
714
---
815

916
<html lang="en">
@@ -22,11 +29,25 @@ const path = Astro.url.pathname;
2229
rel="stylesheet"
2330
/>
2431
</head>
25-
<body set:html={app(path)!.html} id={app(path)!.id}>
32+
<body set:html={app.html} id={app.id}>
2633
<script>
27-
import app from "../app";
34+
import myApp from "../app";
35+
2836
const path = window.location.pathname;
29-
app(path)!.hydrate(app(path)!.id);
37+
const theme =
38+
document.cookie
39+
.split("; ")
40+
.find((row) => row.startsWith("theme="))
41+
?.split("=")[1] ??
42+
getComputedStyle(document.body).getPropertyValue("--theme-primary");
43+
44+
const app = myApp({ path, theme })!;
45+
app.hydrate(app!.id);
3046
</script>
3147
</body>
3248
</html>
49+
50+
<style
51+
lang="scss"
52+
define:vars={{ "theme-primary": primary, "theme-secondary": secondary }}
53+
></style>

0 commit comments

Comments
 (0)