Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/josuerhea/remix-themes

Dark and light mode with SSR for Remix.run
https://github.com/josuerhea/remix-themes

dark-mode remix remix-run theme-ui themes

Last synced: about 1 month ago
JSON representation

Dark and light mode with SSR for Remix.run

Awesome Lists containing this project

README

        

## Remix themes

Dark and light mode with SSR

### Installation

```bash
pnpm i @josuerhea/remix-themes
#or
npm i @josuerhea/remix-themes
```

### Usage

Firt create `app/theme.server.ts` to setup the session storage
```ts
// app/theme.server.ts

import { createCookieSessionStorage } from "@remix-run/node";
import { Theme, isTheme } from "@josuerhea/remix-themes";

const themeStorage = createCookieSessionStorage({
cookie: {
name: "your-theme-name",
secure: true,
sameSite: "lax",
path: "/",
httpOnly: true,
secrets: ["your-secret"],
},
});

async function getThemeSession(request: Request) {
const session = await themeStorage.getSession(request.headers.get("Cookie"));
return {
getTheme: () => {
const themeValue = session.get("theme");
return isTheme(themeValue) ? themeValue : Theme.DARK;
},
setTheme: (theme: Theme) => session.set("theme", theme),
commit: () =>
// no theme for you on my 100th birthday! 😂
themeStorage.commitSession(session, { expires: new Date("2088-10-18") }),
};
}

export { getThemeSession };
```

Update the `app/root.tsx` file. You'll ned a extra component that look like this.

```tsx
// app/root.tsx
import type { LinksFunction, LoaderArgs, SerializeFrom } from "@remix-run/node";
import { NonFlashOfWrongThemeEls, ThemeProvider, useTheme } from "@josuerhea/remix-themes";
import { getThemeSession } from "~/theme.server";
import stylesheet from "~/tailwind.css";
import { useLoaderData } from "@remix-run/react";

export const links: LinksFunction = () => [
{ rel: "stylesheet", href: stylesheet },
];

export async function loader({ request }: LoaderArgs) {
const theme = await getThemeSession(request);

return { theme: theme.getTheme() };
}

type LoaderData = SerializeFrom;

export function App() {
const data = useLoaderData();
const [theme] = useTheme();

return (


{/* ... */}

{/* ... */}


{/* .... */}


);
}

export default function AppWithProviders() {
const data = useLoaderData();

return (



);
}
```

Create a new route in `app/routes/action.set-theme.tsx` that will contain the actions that saves the session storage.

```tsx
// app/routes/action.set-theme.tsx

import { json, type ActionFunction, redirect } from "@remix-run/node";
import { isTheme } from "@josuerhea/remix-themes";
import { getThemeSession } from "~/theme.server";

export const action: ActionFunction = async ({ request }) => {
const themeSession = await getThemeSession(request);
const requestText = await request.text();
const form = new URLSearchParams(requestText);
const theme = form.get("theme");
if (!isTheme(theme)) {
return json({
success: false,
message: `theme value of ${theme} is not a valid theme.`,
});
}

themeSession.setTheme(theme);
return json(
{ success: true },
{
headers: { "Set-Cookie": await themeSession.commit() },
},
);
};

export const loader = () => redirect("/", { status: 404 });
```

### useTheme
Now you can use the hook to see your current theme or change the theme.

```tsx
// app/routes/_index.tsx
import { Theme, Themed, useTheme } from "@josuerhea/remix-themes";

export default function Page() {
const [theme, setTheme] = useTheme();

return (



Active theme: {theme ?? ""}


setTheme(e.target.value as Theme)}
>
Dark
Light


);
}
```