Back to Guides

Themeing

Guidance around Preshapes themeing requirements and capabilities with CSS Custom properties and accompanying Components.

Custom Properties and the theme prop

Themeing is achieved by using CSS Custom Properties (CSS Variables), and are applied by adding the relevant HTML class to an element. All descendants elements will also start using that theme.
The Base component provides a theme prop that will apply the classes mentioned above. As mentioend in the composition guide, Base is the end of the chain for all other components so the theme prop is available on any other component too.

Global theme

Applications need a global theme, which is applied by adding a theme class to the html element.
<!DOCTYPE html>
<html class="Theme--day">
  <head>
  </head>
  <body>
  </body>
</html>

Theme Context Components

React Context Provider and Consumer components are available to get the current theme or change it.
Provider example...
import React, { Component } from 'react';
import { ThemeContext } from 'preshape';

export default class TopComponent extends Component {
  constructor() {
    super(props);
    this.state = {
      theme: 'day',
    };
  }

  render() {
    const { theme } = this.state;

    return (
      <ThemeContext.Provider
          onChangeTheme={ (theme) => this.setState({ theme }) }
          theme={ theme }>
        { children }
      </ThemeContext.Provider>
    );
  }
}
Consumer example...
import React, { Component } from 'react';
import { Button, Buttons, ThemeContext, Text } from 'preshape';

export default class LowerDown extends Component {
  render() {
    return (
      <ThemeContext.Consumer>
        { ({ onChangeTheme, theme }) => (
          <Fragment>
            <Text>Current theme is: { theme }</Text>
            <Buttons>
              <Button onCick={ () => onChangeTheme('day') }>Day</Button>
              <Button onCick={ () => onChangeTheme('night') }>Night</Button>
            </Buttons>
          </Fragment>
        ) }
      </ThemeContext.Consumer>
    );
  }
}
If using the Application component, there is no need to use the ThemeContext.Provider component, see below.

The Application component

The Application component provides handling for updating and setting the theme, at global leve.
import React, { Component } from 'react';
import { Application, ApplicationThemeControls  } from 'preshape';

export default class Root extends Component {
  constructor() {
    super(props);
    this.state = {
      theme: 'day',
    };
  }

  render() {
    const { theme } = this.state;

    return (
      <Application
          onChangeTheme={ (theme) => this.setState({ theme }) }
          theme={ theme }>
        <ApplicationThemeControls />
      </Application>
    );
  }
}