Files
beenvoice-web/src/app/layout.tsx
T
soconnor 75ce36cf9c Update Next.js to v15.5.6 and upgrade dependencies
Bump Next.js from 15.4.5 to 15.5.6 and update related dependencies.

Also upgrade other packages to latest compatible versions including: -
Radix UI components (all minor version updates) - Tiptap editor (3.0.7 →
3.11.0) - React and React DOM (19.1.1 → 19.2.0) - TanStack Query (5.84.0
→ 5.90.10) - TypeScript and ESLint ecosystem - Tailwind CSS (4.1.11 →
4.1.17) - Various other patch and minor updates

Additionally add theme support with next-themes and multiple color
schemes (light, dark, sunset, forest).
2025-11-25 01:54:23 -05:00

58 lines
2.8 KiB
TypeScript

import "~/styles/globals.css";
import { Analytics } from "@vercel/analytics/next";
import { type Metadata } from "next";
import { Geist_Mono } from "next/font/google";
import { TRPCReactProvider } from "~/trpc/react";
import { Toaster } from "~/components/ui/sonner";
import { AnimationPreferencesProvider } from "~/components/providers/animation-preferences-provider";
import { ThemeProvider } from "~/components/providers/theme-provider";
export const metadata: Metadata = {
title: "beenvoice - Invoicing Made Simple",
description:
"Simple and efficient invoicing for freelancers and small businesses",
icons: [{ rel: "icon", url: "/favicon.ico" }],
};
const geistMono = Geist_Mono({
subsets: ["latin"],
variable: "--font-geist-mono",
display: "swap",
});
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html suppressHydrationWarning lang="en" className={geistMono.variable}>
<head>
{/* Inline early animation preference script to avoid FOUC */}
<script
dangerouslySetInnerHTML={{
__html: `(function(){try{var STORAGE_KEY='bv.animation.prefs';var raw=localStorage.getItem(STORAGE_KEY);var prefersReduced=false;var speed=1;if(raw){try{var parsed=JSON.parse(raw);if(typeof parsed.prefersReducedMotion==='boolean'){prefersReduced=parsed.prefersReducedMotion;}else{prefersReduced=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;}if(typeof parsed.animationSpeedMultiplier==='number'){speed=parsed.animationSpeedMultiplier;if(isNaN(speed)||speed<0.25||speed>4)speed=1;}}catch(e){}}else{prefersReduced=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;}var root=document.documentElement;if(prefersReduced)root.classList.add('user-reduce-motion');function apply(fast,normal,slow){root.style.setProperty('--animation-speed-fast',fast+'s');root.style.setProperty('--animation-speed-normal',normal+'s');root.style.setProperty('--animation-speed-slow',slow+'s');}if(prefersReduced){apply(0.01,0.01,0.01);}else{var fast=(0.15/speed).toFixed(4);var normal=(0.30/speed).toFixed(4);var slow=(0.50/speed).toFixed(4);apply(fast,normal,slow);}}catch(_e){}})();`,
}}
/>
</head>
<Analytics />
<body className="bg-background text-foreground relative min-h-screen overflow-x-hidden font-sans antialiased">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<TRPCReactProvider>
<AnimationPreferencesProvider>
{children}
</AnimationPreferencesProvider>
<Toaster />
</TRPCReactProvider>
</ThemeProvider>
</body>
</html>
);
}