mirror of
https://github.com/afoim/fuwari.git
synced 2026-01-31 00:53:19 +08:00
feat(主题): 添加强制暗色模式支持并优化图片加载效果
- 在主题配置中新增forceDarkMode选项强制使用暗色模式 - 根据配置隐藏主题切换器和暗色模式切换组件 - 为图片组件添加加载动画和悬停效果 - 在页脚添加暗色模式IP检测iframe - 格式化package.json文件
This commit is contained in:
136
package.json
136
package.json
@@ -1,70 +1,70 @@
|
||||
{
|
||||
"name": "fuwari",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build && pagefind --site dist",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"type-check": "tsc --noEmit --isolatedDeclarations",
|
||||
"new-post": "node scripts/new-post.js",
|
||||
"format": "biome format --write ./src",
|
||||
"lint": "biome check --write ./src",
|
||||
"preinstall": "npx only-allow pnpm"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.3.1",
|
||||
"@astrojs/svelte": "7.0.12",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.2.5",
|
||||
"@fontsource/roboto": "^5.2.5",
|
||||
"@iconify-json/fa6-brands": "^1.2.5",
|
||||
"@iconify-json/fa6-regular": "^1.2.3",
|
||||
"@iconify-json/fa6-solid": "^1.2.3",
|
||||
"@iconify-json/material-symbols": "^1.2.20",
|
||||
"@iconify/svelte": "^4.2.0",
|
||||
"@swup/astro": "^1.6.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"astro": "5.7.9",
|
||||
"astro-icon": "^1.1.5",
|
||||
"hastscript": "^9.0.1",
|
||||
"katex": "^0.16.22",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"overlayscrollbars": "^2.11.1",
|
||||
"pagefind": "^1.3.0",
|
||||
"photoswipe": "^5.4.4",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-components": "^0.3.0",
|
||||
"rehype-katex": "^7.0.1",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"remark-directive": "^3.0.1",
|
||||
"remark-directive-rehype": "^0.4.2",
|
||||
"remark-github-admonitions-to-directives": "^1.0.5",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-sectionize": "^2.1.0",
|
||||
"sanitize-html": "^2.16.0",
|
||||
"sharp": "^0.34.1",
|
||||
"stylus": "^0.64.0",
|
||||
"svelte": "^5.28.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.8.3",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/ts-plugin": "^1.10.4",
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@rollup/plugin-yaml": "^4.1.2",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/sanitize-html": "^2.15.0",
|
||||
"postcss-import": "^16.1.0",
|
||||
"postcss-nesting": "^13.0.1"
|
||||
},
|
||||
"packageManager": "pnpm@9.14.4"
|
||||
"name": "fuwari",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build && pagefind --site dist",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"type-check": "tsc --noEmit --isolatedDeclarations",
|
||||
"new-post": "node scripts/new-post.js",
|
||||
"format": "biome format --write ./src",
|
||||
"lint": "biome check --write ./src",
|
||||
"preinstall": "npx only-allow pnpm"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.3.1",
|
||||
"@astrojs/svelte": "7.0.12",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.2.5",
|
||||
"@fontsource/roboto": "^5.2.5",
|
||||
"@iconify-json/fa6-brands": "^1.2.5",
|
||||
"@iconify-json/fa6-regular": "^1.2.3",
|
||||
"@iconify-json/fa6-solid": "^1.2.3",
|
||||
"@iconify-json/material-symbols": "^1.2.20",
|
||||
"@iconify/svelte": "^4.2.0",
|
||||
"@swup/astro": "^1.6.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"astro": "5.7.9",
|
||||
"astro-icon": "^1.1.5",
|
||||
"hastscript": "^9.0.1",
|
||||
"katex": "^0.16.22",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"overlayscrollbars": "^2.11.1",
|
||||
"pagefind": "^1.3.0",
|
||||
"photoswipe": "^5.4.4",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-components": "^0.3.0",
|
||||
"rehype-katex": "^7.0.1",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"remark-directive": "^3.0.1",
|
||||
"remark-directive-rehype": "^0.4.2",
|
||||
"remark-github-admonitions-to-directives": "^1.0.5",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-sectionize": "^2.1.0",
|
||||
"sanitize-html": "^2.16.0",
|
||||
"sharp": "^0.34.1",
|
||||
"stylus": "^0.64.0",
|
||||
"svelte": "^5.28.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.8.3",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/ts-plugin": "^1.10.4",
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@rollup/plugin-yaml": "^4.1.2",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/sanitize-html": "^2.15.0",
|
||||
"postcss-import": "^16.1.0",
|
||||
"postcss-nesting": "^13.0.1"
|
||||
},
|
||||
"packageManager": "pnpm@9.14.4"
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ const currentYear = new Date().getFullYear();
|
||||
<div class="transition border-t border-black/10 dark:border-white/15 my-10 border-dashed mx-32"></div>
|
||||
<!--<div class="transition bg-[oklch(92%_0.01_var(--hue))] dark:bg-black rounded-2xl py-8 mt-4 mb-8 flex flex-col items-center justify-center px-6">-->
|
||||
<div class="transition border-dashed border-[oklch(85%_0.01_var(--hue))] dark:border-white/15 rounded-2xl mb-12 flex flex-col items-center justify-center px-6">
|
||||
<iframe src="https://ip.skk.moe/simple-dark" style="width: 100%; border: 0"></iframe>
|
||||
<div class="transition text-50 text-sm text-center">
|
||||
<!-- Project Badges -->
|
||||
<div class="flex flex-wrap justify-center gap-2 mb-3">
|
||||
|
||||
@@ -50,7 +50,9 @@ let links: NavBarLink[] = navBarConfig.links.map(
|
||||
<Icon name="material-symbols:palette-outline" class="text-[1.25rem]"></Icon>
|
||||
</button>
|
||||
)}
|
||||
<LightDarkSwitch client:only="svelte"></LightDarkSwitch>
|
||||
{!siteConfig.themeColor.forceDarkMode && (
|
||||
<LightDarkSwitch client:only="svelte"></LightDarkSwitch>
|
||||
)}
|
||||
<button aria-label="Menu" name="Nav Menu" class="btn-plain scale-animation rounded-lg w-11 h-11 active:scale-90 md:!hidden" id="nav-menu-switch">
|
||||
<Icon name="material-symbols:menu-rounded" class="text-[1.25rem]"></Icon>
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@ interface Props {
|
||||
}
|
||||
import { Image } from "astro:assets";
|
||||
import { url } from "../../utils/url-utils";
|
||||
import { imageFallbackConfig } from "../../config";
|
||||
import { imageFallbackConfig, siteConfig } from "../../config";
|
||||
|
||||
const { id, src, alt, position = "center", basePath = "/" } = Astro.props;
|
||||
const className = Astro.props.class;
|
||||
@@ -46,13 +46,43 @@ if (isLocal) {
|
||||
const imageClass = "w-full h-full object-cover";
|
||||
const imageStyle = `object-position: ${position}`;
|
||||
---
|
||||
<div id={id} class:list={[className, 'overflow-hidden relative']}>
|
||||
<div id={id} class:list={[className, 'overflow-hidden relative image-wrapper']} style={`--theme-hue: ${siteConfig.themeColor.hue}`}>
|
||||
<!-- 加载条 -->
|
||||
<div class="loading-bar absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-32 h-1 bg-gray-200 dark:bg-gray-700 z-10 rounded-full overflow-hidden">
|
||||
<div class="loading-progress h-full w-8 bg-[oklch(0.70_0.14_var(--theme-hue))] animate-loading-progress rounded-full"></div>
|
||||
</div>
|
||||
|
||||
<!-- 图片内容 -->
|
||||
<div class="transition absolute inset-0 dark:bg-black/10 bg-opacity-50 pointer-events-none"></div>
|
||||
{isLocal && img && <Image src={img} alt={alt || ""} class={imageClass} style={imageStyle}/>}
|
||||
{isLocal && img && <Image src={img} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>}
|
||||
{!isLocal && (
|
||||
imageFallbackConfig.enable && src.includes(imageFallbackConfig.originalDomain) ?
|
||||
<img src={isPublic ? url(src) : src} alt={alt || ""} class={imageClass} style={imageStyle} onerror={`this.onerror=null; this.src='${(isPublic ? url(src) : src).replace(imageFallbackConfig.originalDomain, imageFallbackConfig.fallbackDomain)}';`}/> :
|
||||
<img src={isPublic ? url(src) : src} alt={alt || ""} class={imageClass} style={imageStyle}/>
|
||||
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';" onerror={`this.onerror=null; this.src='${(isPublic ? url(src) : src).replace(imageFallbackConfig.originalDomain, imageFallbackConfig.fallbackDomain)}';`}/> :
|
||||
<img src={isPublic ? url(src) : src} alt={alt || ""} class={`${imageClass} image-content opacity-0 transition-opacity duration-500`} style={imageStyle} onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-bar').style.opacity='0';"/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.loading-bar {
|
||||
transition: opacity 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes loading-progress {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(400%);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-loading-progress {
|
||||
animation: loading-progress 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.image-wrapper:hover .image-content {
|
||||
transform: scale(1.05);
|
||||
transition: transform 0.3s ease-out, opacity 0.5s ease-out;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export const siteConfig: SiteConfig = {
|
||||
themeColor: {
|
||||
hue: 360, // Default hue for the theme color, from 0 to 360. e.g. red: 0, teal: 200, cyan: 250, pink: 345
|
||||
fixed: true, // Hide the theme color picker for visitors
|
||||
forceDarkMode: true, // Force dark mode and hide theme switcher
|
||||
},
|
||||
banner: {
|
||||
enable: false,
|
||||
|
||||
@@ -110,22 +110,28 @@ const bannerOffset =
|
||||
))}
|
||||
|
||||
<!-- Set the theme before the page is rendered to avoid a flash -->
|
||||
<script is:inline define:vars={{DEFAULT_THEME, LIGHT_MODE, DARK_MODE, AUTO_MODE, BANNER_HEIGHT_EXTEND, PAGE_WIDTH, configHue}}>
|
||||
// Load the theme from local storage
|
||||
const theme = localStorage.getItem('theme') || DEFAULT_THEME;
|
||||
switch (theme) {
|
||||
case LIGHT_MODE:
|
||||
document.documentElement.classList.remove('dark');
|
||||
break
|
||||
case DARK_MODE:
|
||||
document.documentElement.classList.add('dark');
|
||||
break
|
||||
case AUTO_MODE:
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
<script is:inline define:vars={{DEFAULT_THEME, LIGHT_MODE, DARK_MODE, AUTO_MODE, BANNER_HEIGHT_EXTEND, PAGE_WIDTH, configHue, forceDarkMode: siteConfig.themeColor.forceDarkMode}}>
|
||||
// Force dark mode if configured
|
||||
if (forceDarkMode) {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('theme', DARK_MODE);
|
||||
} else {
|
||||
// Load the theme from local storage
|
||||
const theme = localStorage.getItem('theme') || DEFAULT_THEME;
|
||||
switch (theme) {
|
||||
case LIGHT_MODE:
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
break
|
||||
case DARK_MODE:
|
||||
document.documentElement.classList.add('dark');
|
||||
break
|
||||
case AUTO_MODE:
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the hue from local storage
|
||||
|
||||
@@ -9,6 +9,7 @@ export type SiteConfig = {
|
||||
themeColor: {
|
||||
hue: number;
|
||||
fixed: boolean;
|
||||
forceDarkMode?: boolean;
|
||||
};
|
||||
banner: {
|
||||
enable: boolean;
|
||||
|
||||
Reference in New Issue
Block a user