mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 18:39:14 +03:00
moved theme-detector to public folder
This commit is contained in:
parent
75fa8117f6
commit
b0d7490ecb
@ -9,9 +9,9 @@ Personal website created with Astro.
|
|||||||
|
|
||||||
- [x] HTML layout
|
- [x] HTML layout
|
||||||
- [x] Adaptive & Responsive layout
|
- [x] Adaptive & Responsive layout
|
||||||
- [ ] Dark/Light Theme
|
- [x] Search articles by title or description
|
||||||
|
- [x] Dark/Light Theme
|
||||||
- [ ] Multilang web-site
|
- [ ] Multilang web-site
|
||||||
- [ ] Search articles by title or description
|
|
||||||
- [ ] Form handling via Netlify Forms
|
- [ ] Form handling via Netlify Forms
|
||||||
- [ ] SEO optimized
|
- [ ] SEO optimized
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev --host",
|
"dev": "astro dev --host",
|
||||||
"start": "astro dev",
|
"start": "astro dev",
|
||||||
"build": "astro check && tsc --noEmit && astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview --host",
|
"preview": "astro preview --host",
|
||||||
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json}\"",
|
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json}\"",
|
||||||
"lint": "eslint '**/*.{js,mjs,ts,tsx}'"
|
"lint": "eslint '**/*.{js,mjs,ts,tsx}'"
|
||||||
|
|||||||
23
public/assets/js/detect-theme.js
Normal file
23
public/assets/js/detect-theme.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* This script is used to determine the theme of the site.
|
||||||
|
* The theme value is taken from localstorage, otherwise from the operating system.
|
||||||
|
* It is very important to include this script before loading the CSS
|
||||||
|
* and body markup to prevent FOUC (Flash of unstyled content).
|
||||||
|
*/
|
||||||
|
|
||||||
|
const getTheme = () => {
|
||||||
|
const local = localStorage.getItem('theme');
|
||||||
|
if (local && (local === 'dark' || local === 'light')) return local;
|
||||||
|
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
return isDark ? 'dark' : 'light';
|
||||||
|
};
|
||||||
|
|
||||||
|
window.theme = getTheme();
|
||||||
|
document.documentElement.setAttribute('data-theme', window.theme);
|
||||||
|
|
||||||
|
/* Sync with OS theme */
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ({ matches: isDark }) => {
|
||||||
|
window.theme = isDark ? 'dark' : 'light';
|
||||||
|
localStorage.setItem('theme', window.theme);
|
||||||
|
document.documentElement.setAttribute('data-theme', window.theme);
|
||||||
|
});
|
||||||
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { SITE_METADATA } from '@root/config';
|
import { SITE_METADATA } from '@root/config';
|
||||||
import { DetectThemeScript } from '@root/scripts';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title?: string | undefined;
|
title?: string | undefined;
|
||||||
@ -13,8 +12,6 @@ const { title = SITE_METADATA.title, description } = Astro.props as Props;
|
|||||||
<link rel='preconnect' href='https://fonts.googleapis.com' />
|
<link rel='preconnect' href='https://fonts.googleapis.com' />
|
||||||
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin />
|
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin />
|
||||||
<link href='https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap' rel='stylesheet' />
|
<link href='https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap' rel='stylesheet' />
|
||||||
<!-- <link rel='stylesheet' href='assets/dark.css' media='(prefers-color-scheme: dark)' /> -->
|
|
||||||
<!-- <link rel='stylesheet' href='assets/light.css' media='(prefers-color-scheme: light)' /> -->
|
|
||||||
|
|
||||||
<meta charset='utf-8' />
|
<meta charset='utf-8' />
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||||
@ -23,7 +20,7 @@ const { title = SITE_METADATA.title, description } = Astro.props as Props;
|
|||||||
</title>
|
</title>
|
||||||
<meta name='title' content={title} />
|
<meta name='title' content={title} />
|
||||||
<meta name='description' content={description || SITE_METADATA.description} />
|
<meta name='description' content={description || SITE_METADATA.description} />
|
||||||
|
<script is:inline src='assets/js/detect-theme.js'>
|
||||||
|
|
||||||
<!-- This script will prevent FOUC -->
|
</script>
|
||||||
<DetectThemeScript />
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const { pathname } = Astro.canonicalURL;
|
|||||||
<Icon name='telegram' width='18' height='18' />
|
<Icon name='telegram' width='18' height='18' />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<ThemeSwitcher client:load />
|
<ThemeSwitcher client:visible />
|
||||||
</nav>
|
</nav>
|
||||||
<NavToggle client:visible />
|
<NavToggle client:visible />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,7 +26,9 @@ const ThemeSwitcher: Component = () => {
|
|||||||
const [theme, setTheme] = createSignal<ThemeModeType>(SITE_SETTINGS.defaultTheme);
|
const [theme, setTheme] = createSignal<ThemeModeType>(SITE_SETTINGS.defaultTheme);
|
||||||
const [isReady, setIsReady] = createSignal<boolean>(false);
|
const [isReady, setIsReady] = createSignal<boolean>(false);
|
||||||
|
|
||||||
const toggleTheme: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (e) => {
|
const toggleTheme: JSX.EventHandler<HTMLButtonElement, MouseEvent> = () => {
|
||||||
|
if (!window.theme) return;
|
||||||
|
|
||||||
const newTheme = theme() === 'light' ? 'dark' : 'light';
|
const newTheme = theme() === 'light' ? 'dark' : 'light';
|
||||||
setTheme(newTheme);
|
setTheme(newTheme);
|
||||||
localStorage.setItem('theme', newTheme);
|
localStorage.setItem('theme', newTheme);
|
||||||
@ -46,7 +48,7 @@ const ThemeSwitcher: Component = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button onClick={toggleTheme} class={isReady() ? 'theme-switcher ready' : 'theme-switcher'}>
|
<button onClick={toggleTheme} class={isReady() ? 'theme-switcher ready' : 'theme-switcher'} aria-label={theme()}>
|
||||||
<Switch
|
<Switch
|
||||||
children={
|
children={
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -18,8 +18,8 @@ const { lang = 'ru', content } = Astro.props as Props;
|
|||||||
<html lang={lang}>
|
<html lang={lang}>
|
||||||
<head>
|
<head>
|
||||||
<BaseHead title={content.title}>
|
<BaseHead title={content.title}>
|
||||||
<link rel='stylesheet' href='assets/prism-one-dark.min.css' media='(prefers-color-scheme: dark)' />
|
<link rel='stylesheet' href='assets/css/prism-one-dark.min.css' media='(prefers-color-scheme: dark)' />
|
||||||
<link rel='stylesheet' href='assets/prism-one-light.min.css' media='(prefers-color-scheme: light)' />
|
<link rel='stylesheet' href='assets/css/prism-one-light.min.css' media='(prefers-color-scheme: light)' />
|
||||||
</BaseHead>
|
</BaseHead>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
<script is:inline>
|
|
||||||
const THEME_STORAGE_KEY = 'theme';
|
|
||||||
|
|
||||||
const getTheme = () => {
|
|
||||||
const local = localStorage.getItem(THEME_STORAGE_KEY);
|
|
||||||
if (local && (local === 'dark' || local === 'light')) return local;
|
|
||||||
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
||||||
return isDark ? 'dark' : 'light';
|
|
||||||
};
|
|
||||||
|
|
||||||
window.theme = getTheme();
|
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
|
||||||
|
|
||||||
/* Sync with OS theme */
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ({ matches: isDark }) => {
|
|
||||||
window.theme = isDark ? 'dark' : 'light';
|
|
||||||
localStorage.setItem(THEME_STORAGE_KEY, theme);
|
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export { default as DetectThemeScript } from './detect-theme.astro';
|
|
||||||
4
src/types/main.d.ts
vendored
4
src/types/main.d.ts
vendored
@ -32,8 +32,4 @@ declare global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type ThemeModeType = 'light' | 'dark';
|
type ThemeModeType = 'light' | 'dark';
|
||||||
|
|
||||||
type SiteConfigType = {
|
|
||||||
defaultTheme: ThemeModeType;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user