Theming

Each component brings its own mini-theme to the application. The static style for your component acts as its base theme:

const staticButtonStyle = {
  background:   '#aaa',
  color:        '#333',
  borderRadius: '4px',

  meta: { /* discussed below */ }
};

The ThemeProvider component merges all of your components' static styles into a single master theme object. You do not create this directly. Each component gets a key in the master theme object that corresponds to the themeName you pass to the <Styled> component.

(This is why single-use components do not need to be named, and themeable components need to have a meaningful, globally-unique themeName.)

// created automatically, behind the scenes, from all of your styled components.
// users can override all of the values in this object, as described below.
//
const masterTheme = {
  Button: {
    // the button theme is taken from the static styles from the Button component
    background:   '#aaa',
    color:        '#333',
    borderRadius: '4px',
    meta: {/* ... */}
  },
  Dropdown: { /* ... */ },
  Menu: { /* ... */ },

  meta: { /* this meta is global ... see below */ }
};

The process for overriding the theme is described below.

Global meta

The theme object also contains a key called meta which contains values not tied to a specific component. You can put anything you like in the meta -- styles, strings, numbers, nested objects -- any values that you need. You can think of this as a set of global variables: colors, timing constants, font sizes, etc.

We often refer to this as the "global" meta. Each component can also have its own meta, as described below and in best practices.

The global meta is useful in middleware. It is also passed to your dynamic styling function, so you can use its values as needed:

function dynamicStyle({props, componentTheme, globalMeta}) {
  return Object.assign(
    {}, 
    componentTheme,
    {transition: `opacity ${globalMeta.timing.animationSpeed}`}
  );
}

The bare Styletron Themer library doesn't put anything into the global meta. It is up to the library author to populate it with useful values, and the library user to override those values as needed. The process is described below.

Per-component meta

The component meta is a place to store values that are used in your dynamic styling function. For example, you can include alternate styles for components in different states (focused, disabled). You can include anything you like.

By putting values in the component meta. you make it available for users to override in their theme. If you find yourself hard-coding values in your dynamic styling function, or even in your render method, that's a clue that those values should probably be put into the component meta.

For example, if your button changes color when a disabled prop is set, you might add these keys to the component meta:

const staticButtonStyle = {
  background:   '#aaa',
  color:        '#333',
  borderRadius: '4px',

  meta: {
    // these values are used in the Button's dynamicStyles function. they are not
    // applied automatically! anything in the meta must be applied in code.
    //
    customDisabledState: {
      color:      '#fff',
      background: '#777'
    },
    customFocusState: {/* ... */}
  }
};

function dynamicStyle({props, componentTheme}) {
  return Object.assign({}, componentTheme,
    props.disabled && componentTheme.meta.customDisabledState
  );
}

By putting your disabled styles in the meta, rather than hard-coding them in your styling function, they are installed into the default theme, as described above. And this allows your component's users to override them:

// an end-user can override the values in the component meta
//
const myCustomTheme = {
  Button: {
    background: 'red',

    // the user's meta must match the structure of the button's own default meta.
    // all keys are merged; in this case, the user wants to retain the original
    // background color for disabled buttons, but have them drawn with pink text
    meta: {
      customDisabledState: {
        color: 'pink'
      }
    }
  }
};

Different types of users

Keep in mind that there are different users that are relevant for this discussion:

  • Component authors writing a library, and
  • End users writing applications with your components

These may well be the same person (or team), but they may not be.

We mention this here because the discussion immediately below (on the library meta) is relevant only for library authors, while the discussion that follows (on overriding the theme) is relevant only for end users.

Library meta (for library authors)

As a library author, you can add as much data to the global meta as you like.

Remember, the global theme is created for you from your components' base styles. To set up the global meta, however, you need to invoke the installLibraryMeta() function at startup:

import {installLibraryMeta} from 'styletron-themer';

installLibraryMeta({
  colors: {
    primary: 'blue',
    brandRed: '#ff0033'
  }
});

Library users can then override your values in their theme, as described below.

Overriding the theme (for library users)

The master theme is created by merging the default styles for each component (provided by the library author), with the global library meta (also provided by the library author).

The user-defined theme (which you pass to the ThemeProvider component) can override anything in either a component or in the global meta:

const myCustomTheme = {
  // override default button styles
  Button: {
    background:   'red',
    color:        'green',
    borderRadius: '0',

    meta: {
      // override the component's meta
    }
  },

  // override anything in the global meta
  meta: {
    colors: {
      primary:   'lime',
      brandRed:  '#ff0022',
      brandGold: '#e90'
    }
  }
};

The styles used by any single instance of a component can also be tweaked with inline styles and even an inline theme. Learn more in theme cascade and overriding styles.

results matching ""

    No results matching ""