Capítulo 82 de 108
Remix implementa dark mode com a lib remix-themes, persistindo o tema em cookie de sessão server-side (via loader/action), o que evita flash de tema mesmo com SSR completo.
createCookieSessionStorage.specifiedTheme (do loader) e themeAction (rota de action que grava o cookie).ssrTheme={Boolean(data.theme)}.:root[class~="dark"]: precisa ser adicionado manualmente ao CSS do Tailwind para o seletor dark funcionar corretamente com a abordagem de classe do Remix..dark,
:root[class~="dark"] {
...;
}
dark funcionar via atributo de classe no <html>.const sessionStorage = createCookieSessionStorage({
cookie: { name: "theme", path: "/", httpOnly: true, sameSite: "lax", secrets: ["s3cr3t"] },
})
export const themeSessionResolver = createThemeSessionResolver(sessionStorage)
export async function loader({ request }: LoaderFunctionArgs) {
const { getTheme } = await themeSessionResolver(request)
return { theme: getTheme() }
}
export default function AppWithProviders() {
const data = useLoaderData<typeof loader>()
return (
<ThemeProvider specifiedTheme={data.theme} themeAction="/action/set-theme">
<App />
</ThemeProvider>
)
}
import { createThemeAction } from "remix-themes"
export const action = createThemeAction(themeSessionResolver)
ModeToggle./action/set-theme: o ThemeProvider referencia themeAction explicitamente; sem a rota correspondente, o toggle falha ao persistir.next-themes (client-driven com localStorage).tailwind.css manualmente para adicionar o seletor :root[class~="dark"].PreventFlashOnWrongTheme é o mecanismo Remix-específico para evitar flash, análogo ao script inline do Astro.useTheme() de remix-themes retorna tupla [theme, setTheme], e usa enum Theme.LIGHT/Theme.DARK em vez de strings soltas.