feat(settings): 站点界面动画总开关与子开关

管理后台可关全站动画,并细调代码折叠、平滑滚动、装饰入场;统一 lib/motion,尊重系统减少动态效果。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 06:59:26 +08:00
parent c6df1b3b7e
commit 2b27703e6c
14 changed files with 511 additions and 46 deletions

View File

@@ -10,10 +10,12 @@ import AccountGuard from "@/components/AccountGuard";
import ThemeSync from "@/components/ThemeSync";
import RealtimeProvider from "@/components/RealtimeProvider";
import CodeFoldProvider from "@/components/markdown/CodeFoldProvider";
import MotionProvider from "@/components/MotionProvider";
import type { User } from "@/lib/api";
import { getMeCached, getPublicSettingsCached } from "@/lib/serverData";
import { TOKEN_COOKIE, authCookieHeader } from "@/lib/cookies";
import { accentStyleCSS } from "@/lib/theme";
import { motionConfigFromSettings } from "@/lib/motion";
// 构建期下载并自托管字体:同源加载 + 自动 preload + fallback 度量校正,
// 消除 F5 时 Google CDN 字体到达后整页"由粗变细"的 FOUT 闪动
@@ -73,6 +75,13 @@ export default async function RootLayout({
const settings = await getPublicSettingsCached();
const accent = settings.accent;
const accentCSS = accentStyleCSS(accent || "");
const motionCfg = motionConfigFromSettings(settings);
const motionHtmlClass = [
!motionCfg.ui_animations ? "j13-reduce-motion" : "",
motionCfg.ui_animations && !motionCfg.anim_chrome ? "j13-reduce-chrome" : "",
]
.filter(Boolean)
.join(" ");
let user: User | null = null;
let unread = 0;
@@ -89,7 +98,7 @@ export default async function RootLayout({
return (
<html
lang="zh-CN"
className={`${theme === "dark" ? "dark" : ""} ${jakarta.variable} ${notoSC.variable} ${jetbrainsMono.variable}`}
className={`${theme === "dark" ? "dark" : ""} ${motionHtmlClass} ${jakarta.variable} ${notoSC.variable} ${jetbrainsMono.variable}`.trim()}
>
<body className="min-h-screen flex flex-col">
{accentCSS ? (
@@ -116,12 +125,14 @@ export default async function RootLayout({
tabIndex={-1}
className="flex-1 w-full max-w-[1440px] mx-auto px-4 sm:px-6 py-7 sm:py-9 outline-none"
>
<CodeFoldProvider
initialEnabled={settings.code_block_auto_fold}
initialFoldLines={settings.code_block_fold_lines}
>
{children}
</CodeFoldProvider>
<MotionProvider initial={motionCfg}>
<CodeFoldProvider
initialEnabled={settings.code_block_auto_fold}
initialFoldLines={settings.code_block_fold_lines}
>
{children}
</CodeFoldProvider>
</MotionProvider>
</main>
<Footer siteName={settings.site_name} />
<Toaster />