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 yourdynamicStyle()
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 todynamicStyle()
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.