TL;DR;

We’re waiting for user preference headers. That will allow us to render the root theme with the correct resolved value in the provider and let all other themes resolve correctly in JSX.

User preference media features client hints headers

https://github.com/WICG/user-preference-media-features-headers

Full description

System color mode can currently be resolved only on the client through media queries in css and matchMedia in JS. That means that system color mode fully works on client-side.

For SSR – there are multiple challenges:

CSS variables. If themes are assigned based on selectors (data-rs-theme, data-rs-color-mode), we can inline a short synchronous script in the head tag that will update the root theme attribute. That solves most of the cases but leaves the problem of scoped themes and scoped dark mode on the table, where we need to figure out how to handle their inheritance. It adds additional complexity, but can be solved if system color mode is passed to the root provider with a system value explicitly.

Dark mode toggle. Can be solved by adding a “system” option to the toggle for cases that want to support system level theming, but won’t work for dark / light switches that want to only support system theme as default

JSX content. Since JSX is rendered on the client after the hydration, we can’t change JSX content based on the theme (e.g. 3rd party banners / images) without the content flash.

Related GH issues:

https://github.com/reshaped/community/issues/108