+
{props.header}
diff --git a/src/store/theme.ts b/src/store/theme.ts
new file mode 100644
index 00000000..82506a94
--- /dev/null
+++ b/src/store/theme.ts
@@ -0,0 +1,162 @@
+import { proxy, subscribe, useSnapshot } from "valtio"
+
+export type ThemeName = "default" | "contrast"
+export type ColorSchemeVariant = "black-on-white" | "white-on-black" | "blue-on-blue" | "brown-on-yellow" | "green-on-brown"
+
+const MIN_FONT_SIZE = 8
+const MAX_FONT_SIZE = 48
+const CHANGE_FONT_SIZE_DELTA = 0.2
+
+function clamp(val: number, min: number, max: number): number {
+ if (val < min) {
+ return min
+ }
+ if (val > max) {
+ return max
+ }
+ return val
+}
+
+export type ThemeOptions = {
+ theme: ThemeName
+ fontType: string
+ fontSize: number
+ lineHeight: number
+ letterSpacing: number
+ showImages: boolean
+ colorScheme: ColorSchemeVariant
+}
+
+export const theme = proxy({
+ theme: "default",
+ fontSize: 14,
+ lineHeight: 1.5,
+ letterSpacing: 1,
+ fontType: "Times New Roman",
+ showImages: true,
+ colorScheme: "black-on-white",
+})
+
+export function reset() {
+ theme.fontSize = 14
+ theme.lineHeight = 1.5
+ theme.letterSpacing = 1
+ theme.fontType = "Times New Roman"
+ theme.showImages = true
+ theme.colorScheme = "black-on-white"
+}
+
+export function setDefaultTheme() {
+ theme.theme = "default"
+ reset()
+}
+
+export function toggleTheme() {
+ theme.theme = theme.theme === "default" ? "contrast" : "default"
+}
+
+export function increaseFontSize() {
+ theme.fontSize = clamp(theme.fontSize + CHANGE_FONT_SIZE_DELTA, MIN_FONT_SIZE, MAX_FONT_SIZE)
+}
+
+export function decreaseFontSize() {
+ theme.fontSize = clamp(theme.fontSize - CHANGE_FONT_SIZE_DELTA, MIN_FONT_SIZE, MAX_FONT_SIZE)
+}
+
+export function setSerifFont() {
+ theme.fontType = "sans-serif"
+}
+
+export function setSansFont() {
+ theme.fontType = "Times New Roman"
+}
+
+export function showImages() {
+ theme.showImages = true
+}
+
+export function hideImages() {
+ theme.showImages = false
+}
+
+export function setBlackOnWhite() {
+ theme.colorScheme = "black-on-white"
+}
+
+export function setWhiteOnBlack() {
+ theme.colorScheme = "white-on-black"
+}
+
+export function setBlueOnBlue() {
+ theme.colorScheme = "blue-on-blue"
+}
+
+export function setBrownOnYellow() {
+ theme.colorScheme = "brown-on-yellow"
+}
+
+export function setGreenOnBrown() {
+ theme.colorScheme = "green-on-brown"
+}
+
+export function setLineHeightOneAndHalf() {
+ theme.lineHeight = 1.5
+}
+
+export function setLineHeightTwo() {
+ theme.lineHeight = 2
+}
+
+export function setLineHeightTwoAndHalf() {
+ theme.lineHeight = 2.5
+}
+
+export function setLetterSpacingOne() {
+ theme.letterSpacing = 1
+}
+
+export function setLetterSpacingTwo() {
+ theme.letterSpacing = 2
+}
+
+export function setLetterSpacingFour() {
+ theme.letterSpacing = 4
+}
+
+function getColor(scheme: ColorSchemeVariant): [string, string] {
+ switch (theme.colorScheme) {
+ case "black-on-white":
+ return ["black", "white"]
+ case "white-on-black":
+ return ["white", "black"]
+ case "blue-on-blue":
+ return ["oklch(32% 24% 253deg)", "oklch(84% 21% 245deg)"]
+ case "brown-on-yellow":
+ return ["oklch(41% 3% 92deg)", "oklch(96% 9% 101deg)"]
+ case "green-on-brown":
+ return ["oklch(85% 47% 128deg)", "oklch(29% 10% 61deg)"]
+ default:
+ return ["black", "white"]
+ }
+}
+
+const unsubscribe = subscribe(theme, () => {
+ document.documentElement.style.setProperty("--font-size-default", `${theme.fontSize}pt`)
+
+ document.documentElement.style.setProperty("--title-font", theme.fontType)
+ document.documentElement.style.setProperty("--text-font", theme.fontType)
+
+ document.documentElement.style.setProperty("--article-line-height", `${theme.lineHeight}em`)
+ if (theme.letterSpacing === 1) {
+ document.documentElement.style.setProperty("--letter-spacing", "normal")
+ } else {
+ document.documentElement.style.setProperty("--letter-spacing", `${theme.letterSpacing}px`)
+ }
+
+ const [t, b] = getColor(theme.colorScheme)
+ document.documentElement.style.setProperty("--color-text", t)
+ document.documentElement.style.setProperty("--color-text-second", t)
+ document.documentElement.style.setProperty("--color-text-opposite", b)
+ document.documentElement.style.setProperty("--color-back-main", b)
+ document.documentElement.style.setProperty("--color-back", b)
+})
diff --git a/src/style/style.css b/src/style/style.css
index d112d8da..27791599 100644
--- a/src/style/style.css
+++ b/src/style/style.css
@@ -21,6 +21,8 @@
--font-size-h2: 3rem;
--font-size-h3: 1.5rem;
+ --letter-spacing: normal;
+
/* COLOR */
--color-text: hsl(0, 0%, 15%);
--color-text-second: hsl(240, 10%, 60%);
@@ -89,6 +91,7 @@ body {
background-color: var(--color-back-main);
font-family: var(--text-font);
+ letter-spacing: var(--letter-spacing);
}
/* TITLE */
@@ -168,21 +171,19 @@ h3 {
/* CONTRAST THEME */
.theme-contrast {
/* FONTS */
- --title-font: 'Roboto', Helvetica, sans-serif;
- --text-font: 'Roboto', Helvetica, sans-serif;
+ /*--title-font: "Roboto", Helvetica, sans-serif;*/
+ /*--text-font: "Roboto", Helvetica, sans-serif;*/
/* TEXT COLOR */
- --color-text: black;
+ /*--color-text: black;
--color-text-second: black;
--color-text-opposite: white;
-
--color-back-main: white;
--color-back: white;
--color-back-active: hsl(240, 10%, 20%);
- /* --color-back-opposite: hsl(240, 10%, 80%); */
--color-back-opposite: black;
--color-link: hsl(240, 10%, 40%);
- --color-link-opposite: hsl(240, 10%, 60%);
+ --color-link-opposite: hsl(240, 10%, 60%);*/
--color-hover: white;
--color-hover-back: black;
@@ -193,9 +194,9 @@ h3 {
--shadow-active: none;
/* FONTS */
- --font-size-default: 16pt;
- --font-size-accent: 24pt;
- --font-size-second: 14pt;
+ /*--font-size-default: 16pt;*/
+ /*--font-size-accent: 24pt;*/
+ /*--font-size-second: 14pt;*/
--font-size-h1: 5rem;
--font-size-h2: 3rem;
@@ -207,6 +208,19 @@ h3 {
--border: 5px solid var(--color-back-opposite);
}
+.theme-contrast.no-images img {
+ display: none;
+ /*opacity: 0.5;*/
+ /*position: relative;*/
+}
+
+/*.theme-contrast.no-images img:after {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ border: 1px solid black;
+}*/
+
/* CONTRAST + DARK THEME */
@media (prefers-color-scheme: dark) {
.theme-contrast {
diff --git a/src/ui/theme/Theme.tsx b/src/ui/theme/Theme.tsx
deleted file mode 100644
index 5cf5bd02..00000000
--- a/src/ui/theme/Theme.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useLocalStorage } from "react-use"
-import { ThemeContext } from "./ThemeContext"
-import { ThemeType } from "./types"
-
-export type ThemeProps = {
- children?: React.ReactNode
-}
-
-export const Theme: React.FC = ({ children }) => {
- const [theme, setTheme] = useLocalStorage("hudozka-theme", "default")
-
- return (
-
- {children}
-
- )
-}
diff --git a/src/ui/theme/ThemeContext.ts b/src/ui/theme/ThemeContext.ts
index 2dcb4d68..736b3f8d 100644
--- a/src/ui/theme/ThemeContext.ts
+++ b/src/ui/theme/ThemeContext.ts
@@ -1,4 +1,5 @@
import { createContext } from "react"
-import { SetTheme, ThemeType } from "./types"
+import { DEFAULT } from "./const"
+import { SetTheme, ThemeOptions } from "./types"
-export const ThemeContext = createContext<[ThemeType, SetTheme]>(["default", () => {}])
+export const ThemeContext = createContext<[ThemeOptions, SetTheme]>([DEFAULT, () => {}])
diff --git a/src/ui/theme/const.ts b/src/ui/theme/const.ts
new file mode 100644
index 00000000..0c949a2a
--- /dev/null
+++ b/src/ui/theme/const.ts
@@ -0,0 +1,5 @@
+import { ThemeOptions } from "./types"
+
+export const DEFAULT: ThemeOptions = {
+ theme: "default",
+}
diff --git a/src/ui/theme/types.ts b/src/ui/theme/types.ts
index 8baed57c..4eaf0946 100644
--- a/src/ui/theme/types.ts
+++ b/src/ui/theme/types.ts
@@ -1,2 +1,5 @@
-export type ThemeType = "default" | "contrast"
-export type SetTheme = (theme: ThemeType) => void
+export type ThemeOptions = {
+ theme: "default" | "contrast"
+ fontSize?: number
+}
+export type SetTheme = (theme: ThemeOptions["theme"]) => void
diff --git a/src/ui/theme/useTheme.ts b/src/ui/theme/useTheme.ts
index b3fb9232..fe91ee77 100644
--- a/src/ui/theme/useTheme.ts
+++ b/src/ui/theme/useTheme.ts
@@ -1,9 +1,9 @@
import { useContext } from "react"
import { ThemeContext } from "./ThemeContext"
-import { SetTheme, ThemeType } from "./types"
+import { SetTheme, ThemeOptions } from "./types"
export type UseThemeResult = {
- theme: ThemeType
+ theme: ThemeOptions["theme"]
setTheme: SetTheme
// toggleTheme:
}
@@ -11,5 +11,8 @@ export type UseThemeResult = {
export function useTheme(): UseThemeResult {
const [theme, setTheme] = useContext(ThemeContext)
- return { theme, setTheme }
+ return {
+ setTheme,
+ theme: theme.theme ?? "default",
+ }
}