Files
neta/app/layout.tsx
T

74 lines
2.2 KiB
TypeScript

import type { Metadata, Viewport } from "next";
import type { CSSProperties } from "react";
import { cookies } from "next/headers";
import "./globals.css";
import { cn } from "@/lib/utils";
import {
COLOR_MODE_COOKIE,
isColorMode,
} from "@/lib/color-mode";
import { Toaster } from "poyraz-ui/molecules";
import { getPublicBranding } from "@/server/branding/runtime";
const colorModeScript = `(() => {
const root = document.documentElement;
const media = window.matchMedia("(prefers-color-scheme: dark)");
const apply = () => root.classList.toggle("dark", root.dataset.colorMode === "dark" || (root.dataset.colorMode === "system" && media.matches));
apply();
media.addEventListener("change", apply);
})();`;
export function generateMetadata(): Metadata {
const branding = getPublicBranding();
const faviconUrl = branding.iconUrl ?? "/logo/iconLogo.png";
return {
title: { default: branding.applicationName, template: `%s · ${branding.applicationName}` },
description: "Self-hosted freelancer operating dashboard",
manifest: "/manifest.webmanifest",
icons: {
icon: [{ url: faviconUrl, type: "image/png" }],
shortcut: [{ url: faviconUrl, type: "image/png" }],
apple: [{ url: faviconUrl, type: "image/png" }],
},
appleWebApp: {
capable: true,
statusBarStyle: "default",
title: branding.shortName,
},
};
}
export function generateViewport(): Viewport {
return { themeColor: getPublicBranding().primaryColor };
}
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const branding = getPublicBranding();
const cookieColorMode = (await cookies()).get(COLOR_MODE_COOKIE)?.value;
const colorMode = isColorMode(cookieColorMode)
? cookieColorMode
: branding.defaultColorMode;
return (
<html
lang="tr"
className={cn("font-sans", colorMode === "dark" && "dark")}
data-color-mode={colorMode}
style={branding.cssVariables as CSSProperties}
suppressHydrationWarning
>
<head>
<script dangerouslySetInnerHTML={{ __html: colorModeScript }} />
</head>
<body>
{children}
<Toaster closeButton richColors position="top-right" />
</body>
</html>
);
}