Skip to content
esr360 edited this page Feb 29, 2020 · 9 revisions

A theme is a JavaScript/JSON object that should contain things like:

  • Reusable colors
  • Reusable font-sizes, font-styles etc.
  • Style patterns (vertical-rhythm, positioning etc.)
Basic Example
/themes/myTheme.js
const theme = {
  colors {
    primary: 'red',
    secondary: 'blue'
  },
  sizes: {
    small: '9px',
    large: '18px'
  }
}
/modules/MyModule/styles.js
const styles = ({ state, context, theme }) => ({
  color: theme.colors.primary,
  ...
});

Passing Themes

There are several ways to utilise themes when using Lucid, depending on your setup and/or preference. You can utiliste all available methods simultaneously and the theme values will be merged together (in the priority of Mannual > Provider > Window).

Passing Manually

You can pass your theme to the theme prop of <Module>:

import { Module, Component } from '@onenexus/lucid';
import styles from './styles';
import theme from 'path/to/theme';

const MyModule = () => (
  <Module styles={styles} theme={theme}>
    ...
  </Module>
);

export default MyModule;

Using Theme Provider Component

You can wrap your Modules within a <Provider> Component, passing your theme to the theme prop:

import { Provider } from '@onenexus/lucid';
import theme from 'path/to/theme';
import MyModule from './modules/MyModule';

const App = () => (
  <Provider theme={theme}>
    <MyModule />
  </Provider>
);

Now any Modules within the Provider will have the theme exposed to their styles.

useTheme() Hook

When using the Provider Component to provide a theme, you can access the theme within your Module's JSX using the useTheme() Hook:

import { Module, useTheme } from '@onenexus/lucid';

const MyModule = (props) => {
  const theme = useTheme();

  // some logic with `theme`

  return (
    <Module {...props}>
      ...
    </Module>
  )
}
Evaluating Module Config

You can now evaluate the Module's configuration using the useConfig Hook so you can also access the Module's configuration from within the Module's JSX:

import { Module, useTheme, useConfig } from '@onenexus/lucid';

import config from './config';

const MyModule = (props) => {
  const theme = useTheme();
  const evaluatedConfig = useConfig(config, theme);

  // some logic with `evaluatedConfig`

  return (
    <Module {...props}>
      ...
    </Module>
  )
}

Using Window

By assigning your theme to window.theme, it will be picked up automatically by Lucid:

import theme from 'path/to/theme';
import MyModule from './modules/MyModule';

window.theme = theme;

const App = () => (
  <MyModule />
);

Configure Modules Via Theme

If your Modules have their own configuration, you can set this at the theme level (any theme level) by passing your configuration under the modules key:

You must pass a name prop when using <Module> to utilise this feature

const theme = {
  colors: {
    primary: 'red',
    secondary: 'blue'
  }
  modules: {
    'my-module': {
      // You can access the theme's properties by using a function
      // with a `theme` parameter, they will be evaluated before being
      // exposed to your styles (so no need to manually evaluate)
      someProp: (theme) => theme.colors.secondary,

      'my-component': {
        fontFamily: 'Comic Sans MS'
      }
    }
  }
}
import theme from 'path/to/theme';

const config = {
  someProp: 'purple'
}

const styles = ({ config }) => ({
  color: config.someProp // will be 'blue' (theme.colors.secondary)
});

const MyModule = () => (
  <Module name='my-module' styles={styles} config={config} theme={theme}>
    <Component name='my-component'>
      This Component will be 'Comic Sans MS'
    </Component>
    ...
  </Module>
);

Combined with the dynamic cosmetic properties feature, this allows you to create distinctly different versions of the same Module without changing the source code.

Accessing Theme From Within JSX

Using Render Function

You can access the theme within your Module's JSX by using a render function:

const MyModule = (props) => (
  <Module styles={styles} {...props}>
    {({ theme }) => {
      // some logic using `theme`...

      return props.children;
    }}
  </Module>
);

Note that using a render function with <Module> also exposes the Module's context object and config object