Simple, flexible, reactive mobx theme detector and switcher

mobx-theme

Simple, flexible, reactive mobx theme detector and switcher.

Features

  • Uses prefers-color-scheme to detect initial theme
  • Saves selected theme to local storage for the next page load.
  • Updates theme between tabs (this is a feature of mobx-localstorage)
  • Updates theme when preferred color scheme changes (this is a feature of mobx-matchmedia)
  • You can add more themes in addition to 'light' and 'dark'

Example

This example uses Webpack style-loader with lazyStyleTag. You can see the complete folder in the demo dir.

import { Theme } from 'mobx-theme'
import light from './light.lazy.css'
import dark from './dark.lazy.css'
import { autorunCleanup } from 'mobx-autorun-cleanup'
import { render } from 'react-dom'
import { observer } from 'mobx-react-lite'

const themes = { dark, light }

const theme = new Theme()

autorunCleanup(() => {
  const currentTheme = theme.theme
  themes[currentTheme].use()
  console.log('Loaded theme', currentTheme)
  return () => {
    themes[currentTheme].unuse()
    console.log('Unloaded theme', currentTheme)
  }
})

const Component = observer(() => (
  <select
    value={theme.selectedTheme ?? 'system'}
    onChange={({ target: { value } }) => {
      theme.selectedTheme = value === 'system' ? undefined : value
    }}
  >
    <option value='dark'>Dark</option>
    <option value='light'>Light</option>
    <option value='system'>System</option>
  </select>
))

render(<Component />, document.getElementById('app'))