This example shows how it's possible to set a color theme mode (dark | light | system | ...) in a RedwoodSDK application using cookies.
It uses the Standard RedwoodSDK Starter template.
The example supports the following color themes: dark, light, and system. The system theme adapts to the user's system preference.
You can set the theme on the root page (/) or by editing the cookie manually.
The example adds a dark class name to the html element when the theme is set to dark or system with the systems preference set to dark mode. The light theme does not add any class name to the html element.
Yes, it was made with tailwindcss in mind. If you need more classes, data attributes or whatever, you can easily adapt the code to your needs.
worker (get theme from cookie)
⮑ <Document /> (set class on the html element, calculate the system theme before render)
⮑ <AppLayout /> (layout() server component reading the AppContext)
⮑ <AppProviders /> (client)
⮑ <ThemeProvider /> (client)
⮑ <ThemeProviderContext /> (client)
⮑ <Page />
- the
worker.tsxreads thethemecookie and adds athemeprop to the global context - the layout
AppLayoutreads thethemevariable and passes it to theAppProviderscomponent.
TheAppLayouthas to be a server component, otherwise it can't read the global context AppProvidershas to be a client component, otherwise theThemeProviderContextinside theThemeProviderwon't work.- the
ThemeProvidermanages the theme settings. It persists thethemein a cookie calling a server function (setThemeFn), updates theclassNameof thehtmlelement, and maintains a local state to keep track of the current theme without reloading the page. - the
useTheme()hook is used to access theThemeProviderContextsomewhere in the react three - the
ThemeTogglecomponent shows how to change the theme
To support a system theme, which adapts to the user's system preference, we need to ensure that the theme is set before the page is rendered. This prevents a flash of unstyled content (FOUC) when the page loads.
This is only achievable by adding a <script> to the Document component, which runs before react is hydrated.
If you don't want to use themes calculated dynamically in the client, you can ignore that part.
Clone this repository and install the dependencies:
pnpm install
pnpm devPoint your browser to the URL displayed in the terminal (e.g. http://localhost:5173/). You should see a "Hello World" message in your browser.