0

I'm trying to use themes in Rebass, and it suggested Theme UI for theming. After following the guide on the following, I cannot get setColorMode to work in my storybook.

  1. import useColorMode
import React from 'react'
import { ColorMode, ThemeProvider, useColorMode } from 'theme-ui'
const ThemeWrapper = (props) => {
  const [colorMode, setColorMode] = useColorMode() // error
  //...
}

I receive this as an error instead: [useColorMode] requires the ThemeProvider component

  1. import useThemeUI
import { ColorMode, ThemeProvider, useThemeUI } from 'theme-ui'
const ThemeWrapper = (props) => {
  const context = useThemeUI()
  const { setColorMode } = context
  //...
}

Later on, I have setColorMode is not a function

Examining this context using console.log, it contains the following:

{
  components: Object { p: {…}, b: {…}, i: {…}, … }
  emotionVersion: "10.0.27"
  theme: null
}

useColorMode is nowhere to be found.

What am I doing wrong?


My current code:

.storybook/config.js

import React, { useEffect } from 'react'
import addons from '@storybook/addons';
import { addDecorator, configure } from '@storybook/react';
import { ColorMode, ThemeProvider, useThemeUI } from 'theme-ui'
import theme from '../theme'

const channel = addons.getChannel();

const ThemeWrapper = (props) => {
  const context = useThemeUI()
  const { setColorMode } = context

  console.log(context)

  const setDarkMode = isDark => setColorMode(isDark ? 'dark' : 'default')

  useEffect(() => {
    channel.on('DARK_MODE', setDarkMode);
    return () => channel.removeListener('DARK_MODE', setDarkMode);
  }, [channel, setColorMode]);

  return (
    <ThemeProvider theme={theme}>
      <ColorMode/>
      {props.children}
    </ThemeProvider>
  );
}

addDecorator(renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>);

configure([
  require.context('../components', true, /\.stories\.(jsx?|mdx)$/),
  require.context('../stories', true, /\.stories\.(jsx?|mdx)$/)
], module);

Daniel Cheung
  • 4,779
  • 1
  • 30
  • 63

1 Answers1

3

I asked here: https://github.com/system-ui/theme-ui/issues/537 and I managed to correct my problematic code.

The error arises from the function useColorMode not being called inside a <ThemeProvider>.

I changed my config file to the following to mitigate the issue. And it fixed my problem.

import React, { useEffect } from 'react'
import addons from '@storybook/addons';
import { addDecorator, configure } from '@storybook/react';
import { ColorMode, ThemeProvider, useColorMode } from 'theme-ui'
import theme from '../theme'

const channel = addons.getChannel();

const ThemeChanger = () => {
  const [colorMode, setColorMode] = useColorMode();

  const setDarkMode = isDark => setColorMode(isDark ? 'dark' : 'default')

  useEffect(() => {
    channel.on('DARK_MODE', setDarkMode);
    return () => channel.removeListener('DARK_MODE', setDarkMode);
  }, [channel, setColorMode]);

  return <div/>
}

const ThemeWrapper = ({ children }) => {
  return (
    <ThemeProvider theme={theme}>
      <ThemeChanger/>
      <ColorMode/>
      {children}
    </ThemeProvider>
  );
}

addDecorator(renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>);

configure([
  require.context('../components', true, /\.stories\.(jsx?|mdx)$/),
  require.context('../stories', true, /\.stories\.(jsx?|mdx)$/)
], module);

Daniel Cheung
  • 4,779
  • 1
  • 30
  • 63
  • how do you actually change the theme in Storybook? Is it based on the user's `prefer-color-scheme` value? or is it something else? – Zander Jan 29 '20 at 14:08
  • @Zander I'm so sorry, I'll delete my previous comment. The plugin I used is this: https://github.com/hipstersmoothie/storybook-dark-mode. It has a "theme" button with rather open API. I just followed their tutorial, but swapped code when changing theme to Theme UI's code. – Daniel Cheung Jan 29 '20 at 18:39
  • 1
    Thanks, I thought it was a copy/paste mistake. I have actually found a nice solution using https://github.com/joshrasmussen34/storybook-addon-color-mode that allows for switching multiple color modes. Take a look if you're interested. – Zander Jan 30 '20 at 10:20