"use client" import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from "react" import { useTheme } from "next-themes" import { applyGlassMaterialFix } from "@/components/ui/glass-material-fix" // Define material types export type MaterialType = { id: string name: string description: string isGlass?: boolean opacity?: number blurAmount?: string cssClass: string lightClass?: string darkClass?: string } // Define the context type type MaterialContextType = { materials: MaterialType[] selectedMaterial: MaterialType | null setSelectedMaterial: (material: MaterialType) => void getMaterialClass: (material: MaterialType) => string currentTheme?: string } // Define available materials const materials: MaterialType[] = [ { id: "flat", name: "Flat", description: "Solid color with no transparency", isGlass: false, cssClass: "flat-material", lightClass: "bg-card", darkClass: "bg-card", }, { id: "glass", name: "Glass", description: "Translucent material with blur effect", isGlass: true, opacity: 0.2, blurAmount: "36px", cssClass: "glass-material", lightClass: "bg-card/20 backdrop-blur-[36px]", darkClass: "bg-card/20 backdrop-blur-[36px]", }, ] // Create the context const MaterialContext = createContext(undefined) export function MaterialProvider({ children }: { children: ReactNode }) { const { theme } = useTheme() const [selectedMaterial, setSelectedMaterial] = useState(materials[0]) const [mounted, setMounted] = useState(false) // Set mounted state after hydration useEffect(() => { setMounted(true) }, []) // Apply material to the document useEffect(() => { if (!mounted || !selectedMaterial) return const root = document.documentElement console.debug(`[Material Context] Setting material: ${selectedMaterial.id}`) // Set data attributes for CSS to use root.setAttribute("data-material", selectedMaterial.id) if (selectedMaterial.isGlass) { // Set CSS variables directly on :root for better inheritance root.style.setProperty("--glass-opacity", selectedMaterial.opacity?.toString() || "0.7") root.style.setProperty("--glass-blur", selectedMaterial.blurAmount || "36px") console.debug( `[Material Context] Set glass properties - opacity: ${selectedMaterial.opacity}, blur: ${selectedMaterial.blurAmount}`, ) // Apply glass material fixes const cleanup = applyGlassMaterialFix() return cleanup } else { // Remove glass-specific properties root.style.removeProperty("--glass-opacity") root.style.removeProperty("--glass-blur") console.debug(`[Material Context] Removed glass properties`) // Remove glass material fixes if they exist if (document.getElementById("glass-material-fix")) { document.getElementById("glass-material-fix")?.remove() } } // Set CSS variables for background colors const isDark = theme === "dark" // Set the background-primary variable directly // This ensures it's always available regardless of material root.style.setProperty("--background-primary", isDark ? "#0a0a0a" : "#ffffff") console.debug(`[Material Context] Set background-primary: ${isDark ? "#0a0a0a" : "#ffffff"}`) // Apply background-primary to style guide sections directly setTimeout(() => { document.querySelectorAll(".style-guide-section").forEach((section) => { ;(section as HTMLElement).style.setProperty("background-color", "var(--background-primary)", "important") }) }, 0) }, [selectedMaterial, mounted, theme]) // Function to get the appropriate CSS class based on theme and material const getMaterialClass = useCallback( (material: MaterialType): string => { if (!material) return "" return theme === "dark" ? material.darkClass || "" : material.lightClass || "" }, [theme], ) // Prevent hydration mismatch const contextValue = mounted ? { materials, selectedMaterial, setSelectedMaterial, getMaterialClass, currentTheme: theme, } : { materials, selectedMaterial: null, setSelectedMaterial: () => {}, getMaterialClass: () => "", currentTheme: undefined, } return {children} } export function useMaterial() { const context = useContext(MaterialContext) if (context === undefined) { throw new Error("useMaterial must be used within a MaterialProvider") } return context }