Files
wehub-resource-sync 070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

47 lines
2.2 KiB
TypeScript

import type { Metadata, Viewport } from 'next';
import type { ReactNode } from 'react';
import { I18nProvider } from '../src/i18n';
import { AnalyticsProvider } from '../src/analytics/provider';
import '@excalidraw/excalidraw/index.css';
import '../src/index.css';
import '../src/styles/home/index.css';
export const metadata: Metadata = {
title: 'Open Design',
icons: {
icon: '/app-icon.png',
apple: '/app-icon.png',
},
};
export const viewport: Viewport = {
themeColor: '#F4EFE6',
};
/**
* Inline script that runs before React hydrates to apply the saved theme
* preference without a flash of unstyled content. It reads the same
* localStorage key used by `state/config.ts` and sets `data-theme` on
* `<html>` immediately — before any CSS or React paint.
* Keep the accent variable mix ratios in sync with `accentVars()` in
* `src/state/appearance.ts`; this script cannot import application modules.
*/
const themeInitScript = `(function(){try{var c=JSON.parse(localStorage.getItem('open-design:config')||'{}');var t=c.theme;if(t==='light'||t==='dark')document.documentElement.setAttribute('data-theme',t);var a=typeof c.accentColor==='string'&&/^#[0-9a-fA-F]{6}$/.test(c.accentColor.trim())?c.accentColor.trim().toLowerCase():'#c96442';var s=document.documentElement.style;s.setProperty('--accent',a);s.setProperty('--accent-strong','color-mix(in srgb, '+a+' 86%, var(--text-strong))');s.setProperty('--accent-soft','color-mix(in srgb, '+a+' 22%, var(--bg-panel))');s.setProperty('--accent-tint','color-mix(in srgb, '+a+' 12%, var(--bg-panel))');s.setProperty('--accent-hover','color-mix(in srgb, '+a+' 90%, var(--text-strong))');}catch(e){}})();`;
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang='en' suppressHydrationWarning>
{/* eslint-disable-next-line @next/next/no-sync-scripts */}
<head>
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: intentional theme-init inline script to prevent FOUC */}
<script dangerouslySetInnerHTML={{ __html: themeInitScript }} />
</head>
<body suppressHydrationWarning>
<I18nProvider>
<AnalyticsProvider>{children}</AnalyticsProvider>
</I18nProvider>
</body>
</html>
);
}