Component API

The core functionality of the Styletron Themer package is built into the <Styled> component.

Props

themeName

If you pass a themeName prop to <Styled>, your component will be given an entry in the theme. This allows component users to override the theme globally (see Theming).

If your component is private, you may not need to pass the name up to the theming system.

staticStyle

The staticStyle prop is a plain Styletron object. You can include nested objects for all of the standard Styletron features (such as hover, media queries, pseudo-elements, etc.).

You can also include a nested key called meta for dynamic style information. Nothing inside the component's meta is applied automatically; it is simply a place to store values for use in your dynamic style function. See the discussion in best practices.

const staticStyle = {
  color: '#333',
  outline: '1px dotted gray',
  ':hover': {textDecoration: 'underline'},

  meta: {
    fancyButton: {
      color: '#404',
      outline: 'none'
    }
  }
};

dynamicStyle

The dynamicStyle prop is an optional function. It takes a single argument, which is an object with several keys:

function dynamicStyle({props, componentTheme, globalMeta}) {
    // ...
}
  • props is what you'd expect: the props for this instance of your component. (Note that you can hack this object so that it contains values from state or context; see best practices.)
  • componentTheme is an object with the theme for your component. This not the same as the staticStyle object; by the time your dynamicStyle function is called, the user's custom theme has been applied as well.
  • globalMeta is an object that has the global theme meta. See theming for more details.

The function must return a new Styletron object, with your props-dependent styles merged in. If you have no changes to make, you can simply return componentTheme from your function. But -- and hopefully this is obvious -- you should not modify the componentTheme object.

Note that your function does not return a delta object (i.e., changes to the static style). It must return the full style object, including both static and dynamic styles. There are various tools to help with this: Object.assign, as well as Lodash's _.merge.

If your component only needs static styles, and does not adjust its style to props, you can omit the dynamicStyle prop. The nested SVG sample illustrates this.

Here is a typical dynamicStyle function:

// for reference, here is the default style of the component
export default {
  display: 'inline-block',
  cursor: 'pointer',
  ':hover': {backgroundColor: '#ffc'}

  meta: {       // see comments below
    disabled: {
      cursor: 'default',
      ':hover': {backgroundColor: '#ccc'}
    }
  }
};

export function dynamicStyle({props, componentTheme}) {
  let instanceStyles = {},
      {readOnly, disabled} = props;

  if (readOnly || disabled) {
    /*
      notice how the actual style (cursor:'default', etc) is not hard-coded in this
      function, but loaded from the meta. this allows the user to
      override the styles in their theme. see the article on best practices.

      also notice that this function does not directly reference the default styles
      object above. instead, we look at "componentTheme", which takes into account
      the user's theme and any properties it overrides
    */
    instanceStyles = componentTheme.meta.disabled;
  }

  /*
    the lodash merge tool is a perfect way handle the style overrides in this situation.
    Object.assign is only one level deep, which will fail on nested objects like ':hover'
  */
  return _.merge({},
    componentTheme,
    instanceStyles
  );
}

Other props

You should always (with caveats) pass your component's props up to <Styled>:

return (
  <Styled
   themeName = 'MyComponent'
   staticStyle = {staticStyle} 
   dynamicStyle = {dynamicStyle}
   {...this.props}    // <= notice this
  >
    {className => <div className={className} />}
  </Styled>
);

This serves several important purposes:

First, your dynamic style function needs to be invoked with the correct props for this instance. You need to give the Styled component access to those props so it can call your function properly.

Also, if your user passes inline styles or custom classes, they will be incorporated into the className parameter passed to your render callback. See Theme Cascade for details.

Lastly, you can manually pass props to the Styled component. Use this technique to have your styles adapt to state, for instance.

If neither case is relevant to your component, you can skip the props spread. But this is typically not a good habit to develop!

The render callback

The <Styled> component must be rendered with a callback function instead of child elements:

<Styled>
  {className => <div />}
</Styled>

The callback function is invoked with three parameters.

The first parameter is the className generated by the theming process. It incorporates all of the styles and classes for this instance of the component, and is a string of classes generated by Styletron.

The second parameter is props. This is an object with all of the props you passed into Styled, minus any props that it consumes (such as style, staticStyle). Full details in prop flow.

The third parameter is used only occasionally. It is an object with the following keys:

  • componentTheme -- This is the same set of base styles that is passed to your dynamicStyle() function. This is most useful as a way to access the values in the component meta inside your render. You can see this in action in the Nested SVG sample.
  • globalMeta -- This is also the same value passed to dynamicStyle()
  • classify -- This is a function which accepts a Styletron object and returns a set of classes. You can see it in use in the Nested SVG sample.

results matching ""

    No results matching ""