update dark and ligth theme

This commit is contained in:
2026-08-10 12:35:18 +05:30
parent f397e94418
commit 6cc3c9a0b7
28 changed files with 319 additions and 105 deletions

View File

@@ -1,7 +1,14 @@
import type {Metadata, Viewport} from 'next';
import {cookies} from 'next/headers';
import {Sora, Inter} from 'next/font/google';
import './globals.css';
import {getServerSession} from '@/features/auth/services/serverSession';
import {
htmlThemeAttr,
parseThemeMode,
THEME_MODE_COOKIE,
type ThemeMode,
} from '@/shared/theme/themeMode';
import {Providers} from './providers';
const sora = Sora({
@@ -39,10 +46,34 @@ export const metadata: Metadata = {
},
};
export const viewport: Viewport = {
colorScheme: 'dark',
themeColor: '#000000',
};
/**
* Resolved per request rather than exported as a constant, so the UA chrome
* (address bar, native scrollbars, the paint before CSS arrives) matches the
* mode this visitor actually chose. A hardcoded `colorScheme: 'dark'` here
* was one of the reasons picking Light did nothing visible.
*/
export async function generateViewport(): Promise<Viewport> {
const mode = await readThemeMode();
if (mode === 'light') {
return {colorScheme: 'light', themeColor: '#F7F7F8'};
}
if (mode === 'dark') {
return {colorScheme: 'dark', themeColor: '#000000'};
}
return {
colorScheme: 'light dark',
themeColor: [
{media: '(prefers-color-scheme: light)', color: '#F7F7F8'},
{media: '(prefers-color-scheme: dark)', color: '#000000'},
],
};
}
async function readThemeMode(): Promise<ThemeMode> {
const store = await cookies();
return parseThemeMode(store.get(THEME_MODE_COOKIE)?.value);
}
export default async function RootLayout({
children,
@@ -56,19 +87,27 @@ export default async function RootLayout({
* already answered in this very request.
*/
const session = await getServerSession();
const themeMode = await readThemeMode();
return (
// The theme attributes are server-rendered so the @scope rules in
// loyaly.css match on the very first byte — no flash from stock defaults.
//
// data-theme now comes from the cookie, and is ABSENT for 'system' so
// color-scheme stays `light dark` and light-dark() follows the OS. Astryx's
// <Theme> re-syncs this same attribute after hydration; it writes exactly
// what htmlThemeAttr() writes here, so the two never disagree.
<html
lang="en"
data-theme="dark"
data-theme={htmlThemeAttr(themeMode)}
data-astryx-theme="loyaly"
className={`${sora.variable} ${inter.variable}`}
suppressHydrationWarning
>
<body>
<Providers initialSession={session}>{children}</Providers>
<Providers initialSession={session} initialThemeMode={themeMode}>
{children}
</Providers>
</body>
</html>
);