useLayout
The useLayout hook returns layout and visual environment information. These values may change dynamically during the session (e.g., on resize or theme toggle).
Basic usage
Section titled “Basic usage”import { useLayout } from "@usefractal/frac/web";
function ThemedView() { const { theme, maxHeight, safeArea } = useLayout();
return ( <div style={{ backgroundColor: theme === "dark" ? "#1a1a1a" : "#ffffff", maxHeight, paddingTop: safeArea.insets.top, }} > <p>Current theme: {theme}</p> </div> );}Returns
Section titled “Returns”type LayoutState = { theme: "light" | "dark"; maxHeight: number | undefined; safeArea: SafeArea;};The current color theme of the host application ("light" or "dark").
maxHeight
Section titled “maxHeight”The maximum height available for the view in pixels.
safeArea
Section titled “safeArea”Safe area insets for devices with notches, rounded corners, or other display cutouts.
type SafeArea = { insets: { top: number; right: number; bottom: number; left: number; };};Examples
Section titled “Examples”Conditional Styling
Section titled “Conditional Styling”import { useLayout } from "@usefractal/frac/web";
function ThemedCard() { const { theme } = useLayout(); const isDark = theme === "dark";
return ( <div style={{ backgroundColor: isDark ? "#1a1a1a" : "#ffffff", color: isDark ? "#ffffff" : "#000000", padding: "16px", borderRadius: "8px", border: `1px solid ${isDark ? "#333" : "#e0e0e0"}`, }} > <h3>Themed Card</h3> <p>This card adapts to the current theme.</p> </div> );}CSS Class-Based Theming
Section titled “CSS Class-Based Theming”import { useLayout } from "@usefractal/frac/web";
function View() { const { theme } = useLayout();
return ( <div className={`view ${theme === "dark" ? "dark" : "light"}`}> <header className="view-header"> <h2>My View</h2> </header> <main className="view-content"> <p>Content goes here</p> </main> </div> );}.view { padding: 16px; border-radius: 8px;}
.view.light { background-color: #ffffff; color: #1a1a1a;}
.view.dark { background-color: #1a1a1a; color: #f5f5f5;}
.view.light .view-header { border-bottom: 1px solid #e0e0e0;}
.view.dark .view-header { border-bottom: 1px solid #333;}CSS Variables Theme Provider
Section titled “CSS Variables Theme Provider”import { useLayout } from "@usefractal/frac/web";import { useEffect } from "react";
const lightTheme = { "--bg-primary": "#ffffff", "--bg-secondary": "#f5f5f5", "--text-primary": "#1a1a1a", "--text-secondary": "#666666", "--border-color": "#e0e0e0", "--accent-color": "#0066cc",};
const darkTheme = { "--bg-primary": "#1a1a1a", "--bg-secondary": "#2d2d2d", "--text-primary": "#f5f5f5", "--text-secondary": "#a0a0a0", "--border-color": "#404040", "--accent-color": "#4da6ff",};
function ThemeProvider({ children }: { children: React.ReactNode }) { const { theme } = useLayout(); const variables = theme === "dark" ? darkTheme : lightTheme;
useEffect(() => { const root = document.documentElement; Object.entries(variables).forEach(([key, value]) => { root.style.setProperty(key, value); }); }, [theme, variables]);
return <>{children}</>;}Theme-Aware Chart
Section titled “Theme-Aware Chart”import { useLayout } from "@usefractal/frac/web";
type DataPoint = { label: string; value: number;};
function BarChart({ data }: { data: DataPoint[] }) { const { theme } = useLayout(); const isDark = theme === "dark";
const colors = { bar: isDark ? "#4da6ff" : "#0066cc", barHover: isDark ? "#80c1ff" : "#0052a3", grid: isDark ? "#333" : "#e0e0e0", text: isDark ? "#a0a0a0" : "#666666", };
const maxValue = Math.max(...data.map((d) => d.value));
return ( <div className="bar-chart"> {data.map((item) => ( <div key={item.label} className="bar-container"> <div className="bar" style={{ width: `${(item.value / maxValue) * 100}%`, backgroundColor: colors.bar, }} /> <span style={{ color: colors.text }}>{item.label}</span> </div> ))} </div> );}Safe Area Handling
Section titled “Safe Area Handling”import { useLayout } from "@usefractal/frac/web";
function FullScreenView({ children }: { children: React.ReactNode }) { const { safeArea, maxHeight } = useLayout();
return ( <div style={{ maxHeight, paddingTop: safeArea.insets.top, paddingRight: safeArea.insets.right, paddingBottom: safeArea.insets.bottom, paddingLeft: safeArea.insets.left, }} > {children} </div> );}Theme-Sensitive Images
Section titled “Theme-Sensitive Images”import { useLayout } from "@usefractal/frac/web";
function Logo() { const { theme } = useLayout();
return ( <img src={theme === "dark" ? "/logo-light.svg" : "/logo-dark.svg"} alt="Logo" className="logo" /> );}