### Install Remix Themes Source: https://github.com/abereghici/remix-themes/blob/main/README.md Install the remix-themes package using npm or yarn. ```bash npm install remix-themes # or yarn add remix-themes ``` -------------------------------- ### Setup ThemeProvider in Root Component Source: https://github.com/abereghici/remix-themes/blob/main/README.md Wrap your application with ThemeProvider and configure it with theme data from session storage and the theme action route. Use PreventFlashOnWrongTheme to avoid visual flashes on initial load. ```typescript // root.tsx import { ThemeProvider, useTheme, PreventFlashOnWrongTheme, } from "remix-themes"; import { themeSessionResolver } from "./sessions.server"; // Return the theme from the session storage using the loader export const loader: LoaderFunction = async ({ request }) => { const { getTheme } = await themeSessionResolver(request); return { theme: getTheme(), }; }; // Wrap your app with ThemeProvider. // `specifiedTheme` is the stored theme in the session storage. // `themeAction` is the action name that's used to change the theme in the session storage. export default function AppWithProviders() { const data = useLoaderData(); return ( ); } // Use the theme in your app. // If the theme is missing in session storage, PreventFlashOnWrongTheme will get // the browser theme before hydration and will prevent a flash in browser. // The client code runs conditionally, it won't be rendered if we have a theme in session storage. function App() { const data = useLoaderData(); const [theme] = useTheme(); return ( ); } ``` -------------------------------- ### ThemeProvider Component Setup Source: https://context7.com/abereghici/remix-themes/llms.txt Provides theme context, manages state, persists changes via an action route, and synchronizes state across tabs. Use PreventFlashOnWrongTheme to avoid theme flicker on initial load. ```tsx // app/root.tsx import { useLoaderData, type LoaderFunction } from "react-router"; import { ThemeProvider, useTheme, PreventFlashOnWrongTheme, Theme } from "remix-themes"; import { themeSessionResolver } from "./sessions.server"; // 1. Loader: read theme from cookie and pass to the client export const loader: LoaderFunction = async ({ request }) => { const { getTheme } = await themeSessionResolver(request); return { theme: getTheme() }; // Theme.LIGHT | Theme.DARK | null }; // 2. Inner component: consumes ThemeContext function App() { const data = useLoaderData(); const [theme] = useTheme(); return ( {/* Prevents flash when no server theme is available */} ); } // 3. Default export: wraps App in ThemeProvider export default function AppWithProviders() { const data = useLoaderData(); return ( ); } ``` -------------------------------- ### createThemeSessionResolver Source: https://github.com/abereghici/remix-themes/blob/main/README.md Creates a session resolver for managing themes. It returns an object with functions to get, set, and commit the theme to session storage. ```APIDOC ## createThemeSessionResolver ### Description Creates a session resolver for managing themes. This function takes a cookie session storage and returns an object containing functions to interact with the theme stored in the session. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Resolver Functions - **getTheme**: A function that returns the current theme from the session storage. - **setTheme**: A function that takes a theme name (string) and sets it in the session storage. - **commit**: A function that commits the session storage. It stores all data in the session and returns the `Set-Cookie` header to be used in the HTTP response. ``` -------------------------------- ### Create Theme Session Storage and Resolver Source: https://github.com/abereghici/remix-themes/blob/main/README.md Set up session storage and a theme session resolver in your Remix application. Ensure domain and secure parameters are configured correctly for production. ```typescript // sessions.server.tsx import { createThemeSessionResolver } from "remix-themes"; import { createCookieSessionStorage } from "react-router"; const sessionStorage = createCookieSessionStorage({ cookie: { name: "__remix-themes", // domain: 'remix.run', path: "/", httpOnly: true, sameSite: "lax", secrets: ["s3cr3t"], // secure: true, }, }); export const themeSessionResolver = createThemeSessionResolver(sessionStorage); ``` -------------------------------- ### Create Theme Action Route Source: https://github.com/abereghici/remix-themes/blob/main/README.md Define an action route to handle theme changes and store the user's preference in session storage. Ensure the action name matches the one provided to ThemeProvider. ```typescript import { createThemeAction } from "remix-themes"; import { themeSessionResolver } from "./sessions.server"; export const action = createThemeAction(themeSessionResolver); ``` -------------------------------- ### createThemeAction Utility Source: https://github.com/abereghici/remix-themes/blob/main/README.md Utility function to create an action handler for updating the theme in session storage. ```APIDOC ## createThemeAction ### Description Creates an action handler that processes theme change requests and updates session storage. ### Parameters - **themeSessionResolver** (function) - The theme session resolver instance. ### Returns - **action** (function) - An action function compatible with Remix route actions. ``` -------------------------------- ### ThemeProvider Source: https://context7.com/abereghici/remix-themes/llms.txt A React context provider that manages the application's theme state. It integrates with server-side data, handles theme updates via actions, and synchronizes theme changes across browser tabs. ```APIDOC ## ThemeProvider ### Description React context provider that manages theme state for the entire application. It reads the server-supplied theme from the loader, persists changes via the action route, syncs state across tabs with BroadcastChannel, and optionally suppresses CSS transitions during theme switches. ### Usage ```tsx // app/root.tsx import { useLoaderData, type LoaderFunction } from "react-router"; import { ThemeProvider, useTheme, PreventFlashOnWrongTheme, Theme } from "remix-themes"; import { themeSessionResolver } from "./sessions.server"; // 1. Loader: read theme from cookie and pass to the client export const loader: LoaderFunction = async ({ request }) => { const { getTheme } = await themeSessionResolver(request); return { theme: getTheme() }; // Theme.LIGHT | Theme.DARK | null }; // 2. Inner component: consumes ThemeContext function App() { const data = useLoaderData(); const [theme] = useTheme(); return ( {/* Prevents flash when no server theme is available */} ); } // 3. Default export: wraps App in ThemeProvider export default function AppWithProviders() { const data = useLoaderData(); return ( ); } ``` ``` -------------------------------- ### Create Server-Side Theme Session Resolver Source: https://context7.com/abereghici/remix-themes/llms.txt Sets up a session resolver using cookie session storage. This function is called on each request to manage theme values in cookies. ```typescript import { createThemeSessionResolver } from "remix-themes"; import { createCookieSessionStorage } from "react-router"; const sessionStorage = createCookieSessionStorage({ cookie: { name: "__remix-themes", path: "/", httpOnly: true, sameSite: "lax", secrets: ["s3cr3t"], // domain: "example.com", // set only in production // secure: true, // set only in production }, }); // themeSessionResolver: (request: Request) => Promise export const themeSessionResolver = createThemeSessionResolver(sessionStorage); // ThemeSession shape: // { // getTheme: () => Theme | null // setTheme: (theme: Theme) => void // commit: () => Promise // returns Set-Cookie header value // destroy: () => Promise // clears the session cookie // } ``` -------------------------------- ### Prevent Theme Flash on Load Source: https://context7.com/abereghici/remix-themes/llms.txt A component to be placed inside `` that eliminates the flash of the wrong theme on initial load. It injects a script to read system preferences and set the theme before the rest of the page renders, especially when `ssrTheme` is false. It also renders a `` tag. ```tsx // Placed inside , always within ThemeProvider import { PreventFlashOnWrongTheme } from "remix-themes"; // ssrTheme={true} → theme came from session; no inline script injected // ssrTheme={false} → no session theme; inline script sets correct class before hydration // nonce → optional CSP nonce for the inline script function AppHead({ hasServerTheme }: { hasServerTheme: boolean }) { return ( {/* Renders: Conditionally renders: */} ); } // The injected script (when ssrTheme=false) applies the system theme to: // document.documentElement.dataset.theme (if data-theme attribute already exists) // document.documentElement.classList (fallback — adds "light" or "dark" class) ``` -------------------------------- ### createThemeAction Source: https://context7.com/abereghici/remix-themes/llms.txt Wraps the session resolver into a React Router ActionFunction. This function handles POST requests to update the theme preference in the user's session cookie. ```APIDOC ## createThemeAction ### Description Wraps the session resolver into a React Router `ActionFunction`. The action reads a `{ theme }` JSON body from a POST request, validates it, and stores or destroys the theme cookie. Mount this as a dedicated route that `ThemeProvider` posts to when the user changes their theme. ### Usage ```ts // app/routes/action.set-theme.ts import { createThemeAction } from "remix-themes"; import { themeSessionResolver } from "../sessions.server"; // POST body: { theme: "light" | "dark" | null } // Response: { success: true } → 204 + Set-Cookie header // { success: false, message: "..." } → invalid theme value export const action = createThemeAction(themeSessionResolver); // Internal behaviour: // - theme === null / "" → destroys the session cookie (falls back to system) // - theme === "light" | "dark" → saves to cookie and commits session // - any other value → returns { success: false, message: "theme value of X is not a valid theme." } ``` ``` -------------------------------- ### createThemeSessionResolver Utility Source: https://github.com/abereghici/remix-themes/blob/main/README.md Utility function to create a theme session resolver, used for managing theme persistence in session storage. ```APIDOC ## createThemeSessionResolver ### Description Creates a resolver function to interact with session storage for theme persistence. ### Parameters - **sessionStorage** (object) - The session storage instance (e.g., from `createCookieSessionStorage`). ### Returns - **themeSessionResolver** (function) - A function that takes a request and returns an object with a `getTheme` method. ``` -------------------------------- ### useTheme Hook Source: https://github.com/abereghici/remix-themes/blob/main/README.md The useTheme hook provides access to the current theme and a function to update it. It also returns metadata about how the theme was defined (user or system). ```APIDOC ## useTheme ### Description A hook to access and manage the application's current theme. ### Returns - **theme** (string | null) - The name of the currently active theme. If null, the system theme is used. - **setTheme** (function) - A function to set the theme. Passing `null` will revert to the system theme. - **metadata** (object) - An object containing information about the theme's source. - **definedBy** (string) - Indicates if the theme was set by the `USER` or the `SYSTEM`. ``` -------------------------------- ### ThemeProvider Component Source: https://github.com/abereghici/remix-themes/blob/main/README.md The ThemeProvider component wraps your application to manage theme state. It accepts the specified theme from session storage, an action to change the theme, and an option to disable transitions. ```APIDOC ## ThemeProvider ### Description Provides theme context to the application and manages theme state. ### Props - **specifiedTheme** (string) - The theme currently set in session storage. - **themeAction** (string) - The endpoint or action name used to update the theme in session storage. - **disableTransitionOnThemeChange** (boolean) - Optional. If true, disables CSS transitions when the theme changes to prevent flashing. ``` -------------------------------- ### useTheme Hook Source: https://context7.com/abereghici/remix-themes/llms.txt The primary hook for reading and updating the active theme. It must be called inside a ThemeProvider and returns a tuple containing the current theme, a function to set the theme, and metadata about how the theme was defined. ```APIDOC ## useTheme ### Description Primary hook for reading and updating the active theme. Must be called inside a `ThemeProvider`. Returns a tuple of `[theme, setTheme, metadata]`. ### Usage ```tsx import { Theme, useTheme } from "remix-themes"; function MyComponent() { // theme: Theme.LIGHT | Theme.DARK | null // setTheme: (theme: Theme | null) => void // metadata: { definedBy: "USER" | "SYSTEM" } const [theme, setTheme, { definedBy }] = useTheme(); // ... component logic using theme, setTheme, and definedBy } ``` ### Parameters - `theme` (Theme | null): The current active theme. Can be `Theme.LIGHT`, `Theme.DARK`, or `null` to indicate system preference. - `setTheme` ((theme: Theme | null) => void): A function to update the theme. Passing `null` reverts to the system preference. - `metadata` ({ definedBy: "USER" | "SYSTEM" }): An object containing information about how the theme was defined. `definedBy` can be "USER" or "SYSTEM". ### Error Handling - Calling `useTheme` outside of a `ThemeProvider` will result in an error. ``` -------------------------------- ### Theme Enum and isTheme Guard Source: https://context7.com/abereghici/remix-themes/llms.txt Provides a `Theme` enum for defining theme values and an `isTheme` type-guard function to validate theme values. ```APIDOC ## Theme Enum and isTheme Guard ### Description `Theme` is a TypeScript enum with two members: `Theme.LIGHT` and `Theme.DARK`. `isTheme` is a type-guard function that validates unknown values against the defined `Theme` members, useful for rejecting invalid theme strings. ### Usage ```ts import { Theme, themes, isTheme } from "remix-themes"; // Enum values const lightTheme = Theme.LIGHT; // "light" const darkTheme = Theme.DARK; // "dark" // All valid themes as an array const allThemes = themes; // ["light", "dark"] // Type guard usage function handleThemeInput(input: unknown) { if (isTheme(input)) { // input is now typed as Theme console.log(`Valid theme: ${input}`); } else { console.error("Invalid theme input"); } } handleThemeInput("light"); // true handleThemeInput("dark"); // true handleThemeInput("yellow"); // false handleThemeInput(null); // false handleThemeInput(undefined); // false ``` ### Members - `Theme.LIGHT`: Represents the light theme. - `Theme.DARK`: Represents the dark theme. ### Functions - `themes`: An array containing all valid `Theme` enum values. - `isTheme(value: unknown): value is Theme`: A type-guard function that returns `true` if the provided `value` is a valid `Theme`, and `false` otherwise. ``` -------------------------------- ### Create Theme Action Function Source: https://context7.com/abereghici/remix-themes/llms.txt Wraps the session resolver into a React Router ActionFunction. This handles POST requests to update or destroy the theme cookie based on the JSON body. ```typescript // app/routes/action.set-theme.ts import { createThemeAction } from "remix-themes"; import { themeSessionResolver } from "../sessions.server"; // POST body: { theme: "light" | "dark" | null } // Response: { success: true } → 204 + Set-Cookie header // { success: false, message: "..." } → invalid theme value export const action = createThemeAction(themeSessionResolver); // Internal behaviour: // - theme === null / "" → destroys the session cookie (falls back to system) // - theme === "light" | "dark" → saves to cookie and commits session // - any other value → returns { success: false, message: "theme value of X is not a valid theme." } ``` -------------------------------- ### Use Theme Hook in Remix Source: https://context7.com/abereghici/remix-themes/llms.txt The primary hook for reading and updating the active theme within a ThemeProvider. It returns the current theme, a function to set the theme, and metadata about how the theme was defined (user or system). ```tsx import { Theme, useTheme } from "remix-themes"; export default function Index() { // theme: Theme.LIGHT | Theme.DARK | null // setTheme: (theme: Theme | null) => void // passing null reverts to the system preference // metadata: { definedBy: "USER" | "SYSTEM" } const [theme, setTheme, { definedBy }] = useTheme(); return (

Current theme: {theme ?? "system"} (set by: {definedBy})

); } // Error: useTheme must be called inside // renderHook(() => useTheme()); // throws "useTheme must be used within a ThemeProvider" ``` -------------------------------- ### createThemeSessionResolver Source: https://context7.com/abereghici/remix-themes/llms.txt Creates a server-side session resolver that manages theme preferences stored in a cookie. This function is essential for reading and writing theme data on the server. ```APIDOC ## createThemeSessionResolver ### Description Creates a server-side session resolver bound to a cookie session storage. The returned resolver function is called on each request to read or write the theme value stored in the cookie. ### Usage ```ts // app/sessions.server.ts import { createThemeSessionResolver } from "remix-themes"; import { createCookieSessionStorage } from "react-router"; const sessionStorage = createCookieSessionStorage({ cookie: { name: "__remix-themes", path: "/", httpOnly: true, sameSite: "lax", secrets: ["s3cr3t"], // domain: "example.com", // set only in production // secure: true, // set only in production }, }); // themeSessionResolver: (request: Request) => Promise export const themeSessionResolver = createThemeSessionResolver(sessionStorage); // ThemeSession shape: // { // getTheme: () => Theme | null // setTheme: (theme: Theme) => void // commit: () => Promise // returns Set-Cookie header value // destroy: () => Promise // clears the session cookie // } ``` ``` -------------------------------- ### Theme Enum and Type Guard Source: https://context7.com/abereghici/remix-themes/llms.txt Defines the `Theme` enum with `LIGHT` and `DARK` members, provides an array of all valid themes, and includes an `isTheme` type guard to validate unknown values. This is useful for server-side logic to ensure theme strings are valid. ```ts import { Theme, themes, isTheme } from "remix-themes"; // Enum values Theme.LIGHT // "light" Theme.DARK // "dark" // All valid themes as an array themes // ["light", "dark"] // Type guard — returns true only for valid Theme values isTheme("light") // true isTheme("dark") // true isTheme("yellow") // false isTheme(null) // false isTheme(undefined) // false // Use in custom server logic function handleTheme(raw: unknown) { if (!isTheme(raw)) { throw new Response("Invalid theme", { status: 400 }); } // raw is now typed as Theme return raw; } ``` -------------------------------- ### PreventFlashOnWrongTheme Source: https://github.com/abereghici/remix-themes/blob/main/README.md A component that prevents theme flash on the server by ensuring the theme is correctly set before hydration. ```APIDOC ## PreventFlashOnWrongTheme ### Description This component ensures that the theme is correctly set on the server before client-side hydration to prevent visual flashes caused by incorrect theme rendering. It applies the theme to the `html` element using either a `data-theme` attribute or a `class` attribute. ### Props - **ssrTheme**: A boolean value indicating whether a theme is present in the session storage on the server. If `true`, the component will attempt to apply the theme. If `false` or `null`, it might default or not apply a theme. ### Usage This component should be used in your server-rendered components to manage theme consistency. ``` -------------------------------- ### PreventFlashOnWrongTheme Component Source: https://github.com/abereghici/remix-themes/blob/main/README.md Component to prevent the flash of incorrect theme content on initial load, especially when the theme is not yet determined from session storage. ```APIDOC ## PreventFlashOnWrongTheme ### Description Ensures that the correct theme is applied on initial load without a visual flash. It checks the browser's preferred color scheme if no theme is found in session storage. ### Props - **ssrTheme** (boolean) - Indicates whether a theme was provided during server-side rendering. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.