The first implementation of the style function expects the theme as its only argument. The theme defines a straightforward API:
class Theme {
get name () { /***/ }
get colors () { /***/ }
get palette () { /***/ }
get shapes () { /***/ }
get spacing () { /***/ }
get styles () { /***/ }
get timing () { /***/ }
get transitions () { /***/ }
get typo () { /***/ }
}
Based on the definitions found in the theme object, a style function can build its style object. But sometimes, this might not be enough. A component might want to style itself according to a property.
Styling with kind
In order to let the consumer of a component apply some predefined sub-styles,
Electrum supports the kind
property:
<Button kind='accept' ... />
The style function returns not only the base
style, but also a set of additional
CSS properties for accept
(here simply setting the font to bold):
export default function (theme) {
return {
base: {
display: 'inline-block',
cursor: 'pointer',
/***/
},
accept: {
fontWeight: 'bold',
}
};
};
Styling without dragons
After reading through Monica Dinculescu’s slides How to Style Elements without Dragons and watching her video multiple times, I finally decided to let the style function have access to more context, but not let the user of the component hijack the styles inside of the castle (that is, the component).
Rather than opening the styling mechanism to external style injection, it is preferable to let the style author decide what she allows to customize, and what not.
Style injection using style={{...}}
should therefore be avoided:
<Foo theme={theme} value='hello' kind='nice' styles={{fontWeight: 200}} />
Instead, if the component author of <Foo>
wants to let the user override
the font weight, then she should ask the user to do so explicitly:
<Foo theme={theme} value='hello' kind='nice' customFontWeight=200 />
This means that the style function also needs to get access to the props
of the component being rendered:
export default function (theme, props) {
return {
base: {
display: 'inline-block',
fontWeight: props.customFontWeight || theme.typo.fontWeight,
/***/
},
};
};
The result of the style function therefore needs to be computed again, not only when the theme changes, but also when any of the properties change…
Caching versus flexibilty
Most style functions won’t need to produce custom output based on the component’s properties. We should therefore cache the result of calling the style function if we detect that it only takes a dependency on the theme.
- The function theme ⇒ style should be cached and can be reused independently of the component instance, until the theme gets modified.
- The function theme, props ⇒ style should not be cached. It might
produce a different result for every component instance and will have to
be evaluated when
render()
gets called.
I don’t know if it is a good idea to open up all the props
to the style
function, or if we should rather filter them and only pass it a known
subset.