- Replace next-themes (38 KiB) with a tiny custom ThemeProvider (~< 1 KiB) using localStorage + classList.toggle for theme management - Add FOUC-prevention inline script in layout.tsx to apply saved theme before React hydrates - Remove framer-motion from Header.tsx: nav entry now uses CSS slideDown keyframe, mobile menu uses CSS opacity/translate transitions - Remove framer-motion from ThemeToggle.tsx: use Tailwind hover/active scale - Remove framer-motion from legal-notice and privacy-policy pages - Update useTheme import in ThemeToggle to use custom ThemeProvider - Add slideDown keyframe to tailwind.config.ts - Update tests to mock custom ThemeProvider instead of next-themes Result: framer-motion moves from "First Load JS shared by all" to lazy chunks; next-themes chunk eliminated entirely; -38 KiB from initial bundle Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
// tailwind.config.ts
|
|
import type { Config } from "tailwindcss";
|
|
|
|
// tailwind.config.js
|
|
export default {
|
|
darkMode: "class", // Enables class-based dark mode
|
|
content: [
|
|
"./app/**/*.{js,ts,jsx,tsx}",
|
|
"./app/components/**/*.{js,ts,jsx,tsx}",
|
|
// Add other paths if necessary
|
|
],
|
|
theme: {
|
|
extend: {
|
|
keyframes: {
|
|
fadeIn: {
|
|
"0%": { opacity: "0", transform: "translateY(10px)" },
|
|
"100%": { opacity: "1", transform: "translateY(0)" },
|
|
},
|
|
slideDown: {
|
|
"0%": { opacity: "0", transform: "translateY(-20px)" },
|
|
"100%": { opacity: "1", transform: "translateY(0)" },
|
|
},
|
|
},
|
|
animation: {
|
|
"fade-in": "fadeIn 0.5s ease-out",
|
|
"slide-down": "slideDown 0.4s ease-out",
|
|
},
|
|
colors: {
|
|
background: "var(--background)",
|
|
foreground: "var(--foreground)",
|
|
card: {
|
|
DEFAULT: "var(--card)",
|
|
foreground: "var(--card-foreground)",
|
|
},
|
|
popover: {
|
|
DEFAULT: "var(--popover)",
|
|
foreground: "var(--popover-foreground)",
|
|
},
|
|
primary: {
|
|
DEFAULT: "var(--primary)",
|
|
foreground: "var(--primary-foreground)",
|
|
},
|
|
secondary: {
|
|
DEFAULT: "var(--secondary)",
|
|
foreground: "var(--secondary-foreground)",
|
|
},
|
|
muted: {
|
|
DEFAULT: "var(--muted)",
|
|
foreground: "var(--muted-foreground)",
|
|
},
|
|
accent: {
|
|
DEFAULT: "var(--accent)",
|
|
foreground: "var(--accent-foreground)",
|
|
},
|
|
destructive: {
|
|
DEFAULT: "var(--destructive)",
|
|
foreground: "var(--destructive-foreground)",
|
|
},
|
|
border: "var(--border)",
|
|
input: "var(--input)",
|
|
ring: "var(--ring)",
|
|
// Warm brown palette
|
|
cream: "#FAF8F3",
|
|
sand: "#EFEBE9",
|
|
brown: {
|
|
50: "#EFEBE9",
|
|
100: "#D7CCC8",
|
|
200: "#BCAAA4",
|
|
300: "#A1887F",
|
|
400: "#8D6E63",
|
|
500: "#795548",
|
|
600: "#6D4C41",
|
|
700: "#5D4037",
|
|
800: "#4E342E",
|
|
900: "#3E2723",
|
|
},
|
|
stone: {
|
|
50: "#FAFAF9",
|
|
100: "#F5F5F4",
|
|
200: "#E7E5E4",
|
|
300: "#D6D3D1",
|
|
400: "#A8A29E",
|
|
500: "#78716C",
|
|
600: "#57534E",
|
|
700: "#44403C",
|
|
800: "#292524",
|
|
900: "#1C1917",
|
|
},
|
|
liquid: {
|
|
mint: "#A7F3D0",
|
|
lavender: "#DDD6FE",
|
|
blue: "#BFDBFE",
|
|
rose: "#FECACA",
|
|
yellow: "#FDE68A",
|
|
peach: "#FED7AA",
|
|
pink: "#FBCFE8",
|
|
sky: "#BAE6FD",
|
|
lime: "#D9F99D",
|
|
coral: "#FCA5A5",
|
|
purple: "#E9D5FF",
|
|
teal: "#99F6E4",
|
|
amber: "#FDE047",
|
|
},
|
|
},
|
|
fontFamily: {
|
|
sans: ["var(--font-inter)", "sans-serif"],
|
|
serif: ["var(--font-playfair)", "Georgia", "serif"],
|
|
mono: ["var(--font-roboto-mono)", "Monaco", "Courier New", "monospace"],
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
} satisfies Config;
|