theme toggling

This commit is contained in:
Sergey Yarkov 2022-07-27 22:38:43 +03:00
parent 5f76f318db
commit 75fa8117f6
34 changed files with 304 additions and 269 deletions

View File

@ -12,7 +12,7 @@
"scripts": {
"dev": "astro dev --host",
"start": "astro dev",
"build": "astro build",
"build": "astro check && tsc --noEmit && astro build",
"preview": "astro preview --host",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json}\"",
"lint": "eslint '**/*.{js,mjs,ts,tsx}'"

View File

@ -1,29 +0,0 @@
:root {
/* Fonts */
--font-color: var(--color-white);
--font-color-gray: var(--color-gray-100);
--font-color-grayer: var(--color-gray-200);
/* Border */
--border-color: var(--color-gray-700);
--border-color-hover: var(--color-gray-600);
/* Elements */
--background-body-color: var(--color-gray-900);
--background-header-color: var(--color-gray-900);
--background-inline-code: var(--color-gray-800);
--background-color-hover: var(--color-gray-800);
--background-btn-link: var(--color-gray-800);
--background-btn-link-active: var(--color-gray-700);
--background-inputs-color: var(--color-gray-800);
/* Icons */
--icon-primary: var(--color-white);
--icon-secondary: var(--color-gray-100);
--icon-filter: invert(100%);
}
.header svg,
.site-content svg {
filter: var(--icon-filter);
}

View File

@ -1,23 +0,0 @@
:root {
/* Fonts */
--font-color: var(--color-black);
--font-color-gray: var(--color-gray-500);
--font-color-grayer: var(--color-gray-700);
/* Border */
--border-color: var(--color-gray-100);
--border-color-hover: var(--color-gray-400);
/* Elements */
--background-body-color: var(--color-white);
--background-header-color: var(--color-white);
--background-inline-code: rgba(0, 0, 0, 0.05);
--background-color-hover: var(--color-gray-50);
--background-btn-link: var(--color-white);
--background-btn-link-active: var(--color-white);
--background-inputs-color: var(--color-white);
/* Icons */
--icon-primary: var(--color-white);
--icon-secondary: var(--color-gray-700);
}

View File

@ -1,8 +1,6 @@
import type { ArticleType } from '@root/types';
import './ArticleItem.scss';
import { Component } from 'solid-js';
import { DateFormatter } from '@utils/date';
import './ArticleItem.scss';
export type ArticleItemProps = {
data: ArticleType;

View File

@ -1,6 +1,4 @@
---
import type { ArticleType } from '@root/types';
import { DateFormatter } from '@root/utils';
import './ArticlePost.scss';

View File

@ -1,5 +1,4 @@
import type { Component } from 'solid-js';
import type { ArticleBlockType } from '@root/types';
import { createSignal, createEffect, For } from 'solid-js';
import { search, selectedTags } from '@stores/searchStore';

View File

@ -1,5 +1,6 @@
---
import { SITE_METADATA } from '@root/config';
import { DetectThemeScript } from '@root/scripts';
export interface Props {
title?: string | undefined;
@ -12,8 +13,8 @@ const { title = SITE_METADATA.title, description } = Astro.props as Props;
<link rel='preconnect' href='https://fonts.googleapis.com' />
<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 rel='stylesheet' href='assets/dark.css' media='(prefers-color-scheme: dark)' />
<link rel='stylesheet' href='assets/light.css' media='(prefers-color-scheme: light)' />
<!-- <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 name='viewport' content='width=device-width, initial-scale=1' />
@ -22,4 +23,7 @@ const { title = SITE_METADATA.title, description } = Astro.props as Props;
</title>
<meta name='title' content={title} />
<meta name='description' content={description || SITE_METADATA.description} />
<!-- This script will prevent FOUC -->
<DetectThemeScript />
<slot></slot>

View File

@ -11,14 +11,14 @@ const {
<div class='contacts-list'>
<a href={'mailto:' + email}
>Email
<Icon name='arrow-up-right' width='15' height='15' />
<Icon name='arrow-up-right' width='15' height='15' data-filter='none' />
</a>
<a href={githubUrl} target='_blank'
>Github
<Icon name='arrow-up-right' width='15' height='15' />
<Icon name='arrow-up-right' width='15' height='15' data-filter='none' />
</a>
<a href={telegramUrl} target='_blank'
>Telegram
<Icon name='arrow-up-right' width='15' height='15' />
<Icon name='arrow-up-right' width='15' height='15' data-filter='none' />
</a>
</div>

View File

@ -38,7 +38,7 @@ const { pathname } = Astro.canonicalURL;
<Icon name='telegram' width='18' height='18' />
</a>
</div>
<ThemeSwitcher />
<ThemeSwitcher client:load />
</nav>
<NavToggle client:visible />
</div>

View File

@ -7,7 +7,6 @@
padding-bottom: 15px;
user-select: none;
z-index: 9999;
& .container {
display: flex;
align-items: center;
@ -64,57 +63,11 @@
}
}
}
&__button {
// cursor: pointer;
// background: none;
// border: none;
// &:hover {
// border: none;
// opacity: var(--opacity-hover);
// }
// & span {
// pointer-events: none;
// display: block;
// position: absolute;
// height: 3px;
// width: 100%;
// background: var(--font-color);
// border-radius: 7px;
// opacity: 1;
// left: 0;
// }
// & span:nth-child(1) {
// top: 2px;
// transform-origin: left center;
// }
// & span:nth-child(2) {
// top: 9px;
// transform-origin: left center;
// }
// & span:nth-child(3) {
// top: 16px;
// transform-origin: left center;
// }
// &[aria-pressed='true'] {
// & span:nth-child(1) {
// transform: rotate(45deg);
// top: -1px;
// left: 5px;
// }
// & span:nth-child(2) {
// display: none;
// }
// & span:nth-child(3) {
// transform: rotate(-45deg);
// top: 20px;
// left: 5px;
// }
// }
}
}
@media screen and (max-width: 768px) {
.header {
padding: 10px 0;
&__nav {
display: none;
}
@ -122,6 +75,7 @@
body[data-is-mobile-open='true'] {
& .header {
padding: 15px 0;
background-color: var(--background-header-color);
position: fixed;
right: 0;

View File

@ -1,9 +1,7 @@
.nav-toggle {
display: flex;
padding: 0;
cursor: pointer;
// background: none;
border: none;
padding: 0;
&:hover {
border: none;
opacity: var(--opacity-hover);

View File

@ -4,19 +4,14 @@ import { createSignal, createEffect } from 'solid-js';
import './NavToggle.scss';
const MenuIcon: Component = () => (
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21 6V8H3V6H21ZM3 18H21V16H3V18ZM3 13H21V11H3V13Z" fill="black" />
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="24px" height="24px">
<path d="M 0 7.5 L 0 12.5 L 50 12.5 L 50 7.5 Z M 0 22.5 L 0 27.5 L 50 27.5 L 50 22.5 Z M 0 37.5 L 0 42.5 L 50 42.5 L 50 37.5 Z" />
</svg>
);
const CloseIcon: Component = () => (
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.0002 13.0605L17.4692 18.531L18.5312 17.4705L13.0607 12L18.5312 6.53099L17.4707 5.46899L12.0002 10.9395L6.5312 5.46899L5.4707 6.53099L10.9397 12L5.4707 17.469L6.5312 18.531L12.0002 13.0605Z"
fill="black"
/>
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="24px" height="24px">
<path d="M 9.15625 6.3125 L 6.3125 9.15625 L 22.15625 25 L 6.21875 40.96875 L 9.03125 43.78125 L 25 27.84375 L 40.9375 43.78125 L 43.78125 40.9375 L 27.84375 25 L 43.6875 9.15625 L 40.84375 6.3125 L 25 22.15625 Z" />
</svg>
);

View File

@ -1,6 +1,4 @@
---
import type { ProjectType } from '@root/types';
import './ProjectItem.scss';
import { Icon } from 'astro-icon';

View File

@ -1,6 +1,4 @@
---
import type { ArticleType } from '@root/types';
import './RecentArticles.scss';
import { ArticleItem } from '@components/ArticleItem';
import { sortArtcilesByDate } from '@utils/articles';

View File

@ -20,7 +20,7 @@
& span {
font-size: var(--font-size-lg);
font-weight: 500;
color: var(--font-color-grayer);
color: var(--font-color-gray);
min-width: 20px;
text-align: center;
}

View File

@ -54,7 +54,7 @@ const SearchInput: Component<SearchInputProps> = (props) => {
return (
<div class="search-input">
<svg width="25" height="24" viewBox="0 0 25 24" xmlns="http://www.w3.org/2000/svg">
<svg width="25" height="24" viewBox="0 0 25 24" xmlns="http://www.w3.org/2000/svg" data-filter="none">
<path d="M10.6026 3.60001C11.8798 3.59993 13.1316 3.94283 14.2172 4.5901C15.3028 5.23736 16.179 6.16331 16.7472 7.26368C17.3154 8.36405 17.5531 9.59517 17.4334 10.8184C17.3137 12.0417 16.8415 13.2085 16.0699 14.1876L21.2427 19.164C21.4085 19.3248 21.5053 19.5399 21.5135 19.7662C21.5218 19.9926 21.4411 20.2137 21.2874 20.3853C21.1337 20.5569 20.9184 20.6665 20.6845 20.6921C20.4505 20.7178 20.2151 20.6576 20.0253 20.5236L19.9205 20.436L14.7476 15.4596C13.8802 16.0922 12.8687 16.5172 11.7968 16.6994C10.7248 16.8815 9.62324 16.8157 8.58298 16.5074C7.54272 16.199 6.59366 15.6569 5.81422 14.9259C5.03478 14.1949 4.44733 13.296 4.10042 12.3034C3.7535 11.3108 3.65708 10.2531 3.81911 9.21757C3.98114 8.18204 4.39698 7.19847 5.03226 6.34812C5.66755 5.49778 6.50404 4.80506 7.47263 4.32721C8.44122 3.84936 9.51411 3.60009 10.6026 3.60001V3.60001ZM10.6026 5.40001C9.27934 5.40001 8.01025 5.90572 7.07454 6.80589C6.13884 7.70607 5.61316 8.92697 5.61316 10.2C5.61316 11.473 6.13884 12.6939 7.07454 13.5941C8.01025 14.4943 9.27934 15 10.6026 15C11.9259 15 13.195 14.4943 14.1307 13.5941C15.0664 12.6939 15.5921 11.473 15.5921 10.2C15.5921 8.92697 15.0664 7.70607 14.1307 6.80589C13.195 5.90572 11.9259 5.40001 10.6026 5.40001Z" />
</svg>
<input onInput={onSearch} value={search()} type="text" placeholder={props.placeholder || 'Search article by title or description...'} />

View File

@ -1,6 +1,4 @@
---
import type { SkillsType } from '@root/types';
import { Icon } from 'astro-icon';
import './SkillsBlock.scss';

View File

@ -1,8 +0,0 @@
---
import './ThemeSwitcher.scss';
import { Icon } from 'astro-icon';
---
<button class='theme-switcher'>
<Icon name='moon' width='21' height='21' />
</button>

View File

@ -6,8 +6,13 @@
cursor: pointer;
padding: 0;
margin: 0;
opacity: 0;
&:hover {
opacity: var(--opacity-hover);
border: none;
}
&.ready {
opacity: 1;
transition: all 0.1s linear 0s;
}
}

View File

@ -0,0 +1,62 @@
import type { Component, JSX } from 'solid-js';
import { SITE_SETTINGS } from '@root/config';
import { createSignal, onMount, Switch, Match } from 'solid-js';
import './ThemeSwitcher.scss';
const MoonIcon: Component = () => (
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M10.4998 10.3311C9.39883 9.22975 8.64906 7.82674 8.34521 6.29939C8.04136 4.77203 8.19707 3.18889 8.79266 1.75C7.09451 2.08429 5.53468 2.91752 4.31266 4.14313C0.895781 7.56 0.895781 13.1005 4.31266 16.5174C7.73041 19.9351 13.27 19.9342 16.6878 16.5174C17.9131 15.2955 18.7462 13.736 19.0809 12.0382C17.642 12.6337 16.0589 12.7894 14.5316 12.4855C13.0042 12.1817 11.6012 11.432 10.4998 10.3311Z"
fill="#010409"
/>
</svg>
);
const SunIcon: Component = () => (
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.12062 10.5C6.12062 12.9159 8.08587 14.8811 10.5017 14.8811C12.9176 14.8811 14.8829 12.9159 14.8829 10.5C14.8829 8.08413 12.9176 6.11888 10.5017 6.11888C8.08587 6.11888 6.12062 8.08413 6.12062 10.5ZM9.625 16.625H11.375V19.25H9.625V16.625ZM9.625 1.75H11.375V4.375H9.625V1.75ZM1.75 9.625H4.375V11.375H1.75V9.625ZM16.625 9.625H19.25V11.375H16.625V9.625ZM4.93238 17.3057L3.69513 16.0685L5.551 14.2126L6.78825 15.4499L4.93238 17.3057ZM14.2118 5.551L16.0685 3.69425L17.3057 4.9315L15.449 6.78825L14.2118 5.551ZM5.551 6.78912L3.69513 4.93238L4.93325 3.69513L6.78825 5.55187L5.551 6.78912ZM17.3057 16.0685L16.0685 17.3057L14.2118 15.449L15.449 14.2118L17.3057 16.0685Z"
fill="black"
/>
</svg>
);
const ThemeSwitcher: Component = () => {
const [theme, setTheme] = createSignal<ThemeModeType>(SITE_SETTINGS.defaultTheme);
const [isReady, setIsReady] = createSignal<boolean>(false);
const toggleTheme: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (e) => {
const newTheme = theme() === 'light' ? 'dark' : 'light';
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
document.documentElement.setAttribute('data-theme', newTheme);
};
onMount(() => {
setIsReady(true);
if (window.theme) {
setTheme(window.theme);
/* Update theme state on changing OS the,e */
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ({ matches: isDark }) => {
const theme = isDark ? 'dark' : 'light';
setTheme(theme);
});
}
});
return (
<button onClick={toggleTheme} class={isReady() ? 'theme-switcher ready' : 'theme-switcher'}>
<Switch
children={
<>
<Match when={theme() === 'light'} children={<MoonIcon />} />
<Match when={theme() === 'dark'} children={<SunIcon />} />
</>
}
/>
</button>
);
};
export default ThemeSwitcher;

View File

@ -1 +1 @@
export { default } from './ThemeSwitcher.astro';
export { default } from './ThemeSwitcher';

View File

@ -1,3 +1,7 @@
export const SITE_SETTINGS: SiteConfigType = {
defaultTheme: 'dark',
};
export const SITE_METADATA = {
title: 'Sergey Yarkov',
name: 'yarkov.tech',

View File

@ -1,6 +1,5 @@
---
import type { Props as BaseHeadProps } from '@root/components/BaseHead.astro';
import type { ArticleType } from '@root/types';
import BaseHead from '@components/BaseHead.astro';
import BaseLayout from '@components/BaseLayout';

View File

@ -1,9 +1,9 @@
---
import type { Props as BaseHeadProps } from '@components/BaseHead.astro';
import { SITE_METADATA } from '@root/config';
import BaseHead from '@components/BaseHead.astro';
import BaseLayout from '@components/BaseLayout';
import { SITE_METADATA } from '@root/config';
import PageHeading from '@components/PageHeading';
import '@styles/global.scss';

View File

@ -1,6 +1,4 @@
---
import type { ArticleType } from '@root/types';
import PageLayout from '@layouts/default.astro';
import ArticlesList from '@components/ArticlesList';
import { transformArticles, formatToArticleBlocks } from '@utils/articles';

View File

@ -1,6 +1,4 @@
---
import type { ArticleType } from '@root/types';
import * as utils from '@utils/index';
import PageLayout from '@layouts/default.astro';
import RecentArticles from '@components/RecentArticles';

View File

@ -0,0 +1,20 @@
<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
src/scripts/index.ts Normal file
View File

@ -0,0 +1 @@
export { default as DetectThemeScript } from './detect-theme.astro';

View File

@ -1,91 +1,4 @@
:root {
color-scheme: light dark;
/* Fonts */
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-family-base: 'Rubik', var(--font-fallback);
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-md: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.5rem;
--font-size-3xl: 1.875rem;
--font-size-4xl: 2.25rem;
--font-size-5xl: 3rem;
--font-size-6xl: 3.75rem;
--font-size-7xl: 4.5rem;
--font-size-8xl: 6rem;
--font-size-9xl: 8rem;
/* Line heights */
--line-height-normal: 'normal';
--line-height-none: 1;
--line-height-shorter: 1.25;
--line-height-short: 1.375;
--line-height-base: 1.5;
--line-height-tall: 1.625;
/* Colors */
--color-white: #ffffff;
--color-black: #010409;
--color-blue-50: #cae8ff;
--color-blue-100: #a5d6ff;
--color-blue-200: #79c0ff;
--color-blue-300: #58a6ff;
--color-blue-400: #388bfd;
--color-blue-500: #1f6feb;
--color-blue-600: #1158c7;
--color-blue-700: #0d419d;
--color-blue-800: #0c2d6b;
--color-blue-900: #051d4d;
--color-gray-50: #f0f6fc;
--color-gray-100: #c9d1d9;
--color-gray-200: #b1bac4;
--color-gray-300: #8b949e;
--color-gray-400: #6e7681;
--color-gray-500: #484f58;
--color-gray-600: #30363d;
--color-gray-700: #21262d;
--color-gray-800: #161b22;
--color-gray-900: #0d1117;
--color-orange-50: #ffdfb6;
--color-orange-100: #ffc680;
--color-orange-200: #ffa657;
--color-orange-300: #f0883e;
--color-orange-400: #db6d28;
--color-orange-500: #bd561d;
--color-orange-600: #9b4215;
--color-orange-700: #762d0a;
--color-orange-800: #5a1e02;
--color-orange-900: #3d1300;
--color-yellow-50: #f8e3a1;
--color-yellow-100: #f2cc60;
--color-yellow-200: #e3b341;
--color-yellow-300: #d29922;
--color-yellow-400: #bb8009;
--color-yellow-500: #9e6a03;
--color-yellow-600: #845306;
--color-yellow-700: #693e00;
--color-yellow-800: #4b2900;
--color-yellow-900: #341a00;
/* Border */
--border-radius-md: 3px;
--border-radius-lg: 5px;
/* Sizes */
--content-width: 760px;
--content-padding: 24px;
--outline-color: var(--color-blue-500);
--opacity-hover: 0.7;
}
@import './theme.scss';
::selection {
background: var(--color-yellow-100);
@ -115,13 +28,14 @@ html {
font-weight: normal;
font-kerning: normal;
font-family: var(--font-family-base);
background: var(--background-body-color);
}
body {
margin: 0;
padding: 0;
color: var(--font-color);
background-color: var(--background-body-color);
background: var(--background-body-color);
}
.container {
@ -197,13 +111,14 @@ textarea {
-webkit-appearance: none;
font-family: var(--font-family-base);
padding: 8px 15px;
border: 1px solid var(--border-color);
border: none;
border-radius: var(--border-radius-md);
background-color: var(--background-inputs-color);
font-size: var(--font-size-sm);
width: 100%;
outline-color: var(--outline-color);
resize: vertical;
border: 1px solid var(--border-color);
outline-color: var(--color-blue-500);
}
button {
@ -249,12 +164,12 @@ pre {
}
a {
color: var(--color-blue-500);
color: var(--color-blue-400);
font-weight: 500;
text-decoration: none;
&:hover {
text-decoration: underline;
color: var(--color-blue-500);
color: var(--color-blue-400);
}
}

140
src/styles/theme.scss Normal file
View File

@ -0,0 +1,140 @@
:root,
:root[data-theme='light'] {
color-scheme: light;
/* Fonts */
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-family-base: 'Rubik', var(--font-fallback);
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-md: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.5rem;
--font-size-3xl: 1.875rem;
--font-size-4xl: 2.25rem;
--font-size-5xl: 3rem;
--font-size-6xl: 3.75rem;
--font-size-7xl: 4.5rem;
--font-size-8xl: 6rem;
--font-size-9xl: 8rem;
/* Line heights */
--line-height-normal: 'normal';
--line-height-none: 1;
--line-height-shorter: 1.25;
--line-height-short: 1.375;
--line-height-base: 1.5;
--line-height-tall: 1.625;
/* Colors */
--color-white: #ffffff;
--color-black: #010409;
--color-blue-50: #cae8ff;
--color-blue-100: #a5d6ff;
--color-blue-200: #79c0ff;
--color-blue-300: #58a6ff;
--color-blue-400: #388bfd;
--color-blue-500: #1f6feb;
--color-blue-600: #1158c7;
--color-blue-700: #0d419d;
--color-blue-800: #0c2d6b;
--color-blue-900: #051d4d;
--color-gray-50: #f0f6fc;
--color-gray-100: #c9d1d9;
--color-gray-200: #b1bac4;
--color-gray-300: #8b949e;
--color-gray-400: #6e7681;
--color-gray-500: #484f58;
--color-gray-600: #30363d;
--color-gray-700: #21262d;
--color-gray-800: #161b22;
--color-gray-900: #0d1117;
--color-orange-50: #ffdfb6;
--color-orange-100: #ffc680;
--color-orange-200: #ffa657;
--color-orange-300: #f0883e;
--color-orange-400: #db6d28;
--color-orange-500: #bd561d;
--color-orange-600: #9b4215;
--color-orange-700: #762d0a;
--color-orange-800: #5a1e02;
--color-orange-900: #3d1300;
--color-yellow-50: #f8e3a1;
--color-yellow-100: #f2cc60;
--color-yellow-200: #e3b341;
--color-yellow-300: #d29922;
--color-yellow-400: #bb8009;
--color-yellow-500: #9e6a03;
--color-yellow-600: #845306;
--color-yellow-700: #693e00;
--color-yellow-800: #4b2900;
--color-yellow-900: #341a00;
/* Border */
--border-radius-md: 3px;
--border-radius-lg: 5px;
/* Sizes */
--content-width: 760px;
--content-padding: 24px;
--opacity-hover: 0.7;
/* Fonts */
--font-color: var(--color-black);
--font-color-gray: var(--color-gray-500);
--font-color-grayer: var(--color-gray-700);
/* Border */
--border-color: var(--color-gray-100);
--border-color-hover: var(--color-gray-400);
/* Elements */
--background-body-color: var(--color-white);
--background-header-color: var(--color-white);
--background-inline-code: rgba(0, 0, 0, 0.05);
--background-color-hover: var(--color-gray-50);
--background-btn-link: var(--color-white);
--background-btn-link-active: var(--color-white);
--background-inputs-color: var(--color-white);
/* Icons */
--icon-primary: var(--color-white);
--icon-secondary: var(--color-gray-700);
}
:root[data-theme='dark'] {
color-scheme: dark;
/* Fonts */
--font-color: var(--color-white);
--font-color-gray: var(--color-gray-100);
--font-color-grayer: var(--color-gray-200);
/* Border */
--border-color: var(--color-gray-700);
--border-color-hover: var(--color-gray-600);
/* Elements */
--background-body-color: var(--color-gray-900);
--background-header-color: var(--color-gray-900);
--background-inline-code: var(--color-gray-800);
--background-color-hover: var(--color-gray-800);
--background-btn-link: var(--color-gray-800);
--background-btn-link-active: var(--color-gray-700);
--background-inputs-color: var(--color-gray-800);
/* Icons */
--icon-primary: var(--color-white);
--icon-secondary: var(--color-gray-100);
--icon-filter: invert(100%);
& .header svg,
& .site-content svg:not([data-filter='none']) {
filter: var(--icon-filter);
}
}

View File

@ -1,25 +0,0 @@
export type ArticleType = {
title: string;
author: string;
tags: Array<string>;
published_at: string;
};
export type ProjectType = {
icon: string;
name: string;
year: string;
description: string;
sourceUrl?: string | undefined;
articleUrl?: string | undefined;
demoUrl?: string | undefined;
};
export type SkillsType = {
title: string;
list: Array<{ icon?: string | undefined; name: string }>;
};
export type ArticleBlockType = {
[year: number]: ArticleType[];
};

39
src/types/main.d.ts vendored Normal file
View File

@ -0,0 +1,39 @@
export {};
declare global {
interface Window {
theme?: ThemeModeType | undefined;
}
type ArticleType = {
title: string;
author: string;
tags: Array<string>;
published_at: string;
};
type ProjectType = {
icon: string;
name: string;
year: string;
description: string;
sourceUrl?: string | undefined;
articleUrl?: string | undefined;
demoUrl?: string | undefined;
};
type SkillsType = {
title: string;
list: Array<{ icon?: string | undefined; name: string }>;
};
type ArticleBlockType = {
[year: number]: ArticleType[];
};
type ThemeModeType = 'light' | 'dark';
type SiteConfigType = {
defaultTheme: ThemeModeType;
};
}

View File

@ -1,5 +1,3 @@
import type { ArticleType, ArticleBlockType } from '@root/types';
import { MarkdownInstance } from 'astro';
export const transformArticles = (articles: MarkdownInstance<ArticleType>[]): ArticleType[] =>

View File

@ -17,7 +17,8 @@
"@utils/*": ["./src/utils/*"],
"@stores/*": ["./src/stores/*"]
},
"outDir": "./dist"
"outDir": "./dist",
"typeRoots": ["./node_modules/@types", "./src/types"]
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts"]
}