### 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.