Multiple themes

Easy. Just wrap different sections of the app inside multiple ThemeProvider components. Or -- see below -- apply a local theme to a single component instance.

Remember, every styled component in your app needs to have two components somewhere in its ancestry: a ThemeProvider and a Styletron provider.

This is how your end users might set up a two-theme system:

const mainTheme = {/* ... */},
      sidebarTheme = {/* ... */};

const app = (
  <StyletronProvider styletron={new Styletron()}>
    <ThemeProvider theme={sidebarTheme}>
      <Sidebar />
    </ThemeProvider>

    <ThemeProvider theme={mainTheme}>
      <ContentArea />
    </ThemeProvider>
  </StyletronProvider>
);

ThemeProviders are not expensive. Use them liberally. You can wrap a single component inside a ThemeProvider, if you need to override its design in ways that cannot be accomplished with an inline style prop. (Although local themes might be a better choice for that situation, as described below.)

Nested themes

Unlike other providers, the ThemeProvider component does not need to be unique. You can nest themes in order to adapt your designs to different parts of your app.

A nested theme inherits all of the designs from its parent.

const outerTheme = {
  Button: {
    color: 'red',
    background: 'white'
  }
};

const innerTheme = {
  Button: {
    color: 'blue'  // inherits background color from parent
  }
};

Values in the global meta are also inherited and overridable.

const outerTheme = {
  Button: { /* ... */},
  meta: {
    colors: {
      primary: 'green',
      secondary: 'pink'
    }
  }
};

const innerTheme = {
  Button: { /* ... */},
  meta: {
    colors: {
      primary: 'purple'     // inherits "secondary"
    }
  }
};

Using nested themes requires no fancy footwork:

const app = (
  <StyletronProvider styletron={new Styletron()}>
    <ThemeProvider theme={pageTheme}>
      <MainPage />

      <ThemeProvider theme={sidebarTheme}>
        <Sidebar />
      </ThemeProvider>
    </ThemeProvider>
  </StyletronProvider>
);

Bear in mind that an inner ThemeProvider will mask values installed in an outer ThemeProvider. In some situations, you may need to merge your themes.

const mainTheme = {/* ... */},
      headerTheme = _.merge({}, mainTheme, {/* ... */});

function App() {
  return (
    <ThemeProvider theme={mainTheme}>

      <ThemeProvider theme={headerTheme}>
        <Header />
      </ThemeProvider>    

      <ContentArea />
    </ThemeProvider>
  );
}

Local themes

If you need to theme a single instance of a component, you might find it easier (and semantically more accurate) to use a local theme. A local theme is only used for the component being rendered; subcomponents will use the existing theme from the ThemeProvider.

const localTheme = {
  // the local theme is for a single component, so you don't
  // scope values using the component name. you also can't
  // override the global meta

  color: 'blue',
  background: '#eee',

  // using a local theme allows you to override the component meta
  // (not the global meta).

  meta: { /* ... */ }
};

const b = <Button localTheme={localTheme}>Blue button</Button>;

results matching ""

    No results matching ""