react-restyle
v2.0.0
Published
Simple composable styling for React components
Downloads
1
Maintainers
Readme
react-restyle
Simple composable styling for React components. Supports css-in-jss, css-modules, BEM or just plain old css.
Why?
react-restyle provide composable styling for react components by allowing className (and style) to target and restyle elements inside the component, including the ability to remove or alter existing styling (so no more !important issues). Best of all there is no need for complex and fragile nested selectors!
Making a component restylable is transparent (ie, backward-compatible) to any component consumer, so code changes to introduce restyling are minimal.
Install
npm install --save react-restyle
Usage
Quickstart
Define a restylable component with defaultStyles
using the withStyles
higher order component to automatically compose the styles (or the hook-like composeStyles
can also be used):
import * as React from "react";
import { withStyles} from "react-restyle";
const defaultStyles = {
classes: {
root: 'bg-red border padding-sm',
text: 'white caps'
}
}
const NameBadge = ({className,style, name}) => {
return (
<div
className={className.root /* or `className` also works for root elements */}
>
<span className={className.text}>{name}</span>
</div>
)
}
export default withStyles(NameBadge, defaultStyles)
Then simply restyle be expanding className to change the styling:
const App = () => {
return (
<NameBadge className={{root: 'bg-green padding-lg', text: 'white'}}/>
)
}
Passing a string to className still works fine, but will only change classes on the root component (ie, the fallback matches typical className usage):
const App = () => {
return (
<NameBadge className='bg-green, padding-lg'/>
)
}
Example
The following is a simple example of combining two restylable components, HeyButton
and NameBadge
that both have inbuilt styling that would be diffcult to change with selectors. Executable code is in example/
.
The raw components:
<HeyButton /> <NameBadge name='Jude'/>
Combining the components, they do not interface well. Overriding the styles using a plain className prop would be limited as
!important
is present on several properties, along with inline styles too:<HeyButton> <NameBadge name='Jude'/> </HeyButton>
Instead, as the components are restylable (and can very easily be made restylable if not, without notifying other component users) we can strip the un-needed styles by passing a targeted object for
className
andstyle
:<HeyButton className={{ root: undefined, hey: undefined, punctuation: undefined }}> <NameBadge name='Jude' className='' style={{'color': undefined }}/> </HeyButton>
Now we can style the object as required:
<HeyButton className={{ root: 'border margin-sm bg-blue white padding-sm sans inline-block', hey: 'capitalize', punctuation: 'bold', }}> <NameBadge name='Jude' className='' style={{'color': undefined, display: 'inline'}}/> </HeyButton>
API Reference
defaultStyles (Object)
: Definition object for base styles
withStyles
: Higher order component to automatically compose styles
composeStyles
: Hook-like explicit composition of styles
removeClass
: Simple utility to remove a className from a list of classes
defaultStyles
Defines the base styles for the component. By convention the outermost element is named root
but the key can be any named property.
const defaultStyles = {
rootKey: 'root', // optional name for the root reference
classes: { // mappings for element keys to css class names
root: 'bg-blue d-flex',
text: 'white',
},
styles: { // mappings for element keys to inline styles
isStyleMap: true, // required key for object identificaiton
root: {
display: 'inline-block',
},
text: {
textTransform: 'uppercase',
}
}
}
Altering defaultStyles
By convention the defaultStyles object is saved to the component so consumers of the component can fetch the defaults for reference.
As a component consumer, altering defaultStyles
itself will also change the default wherever the module is used.
withStyles
Higher order component the automatically composes styling passed to the restylable component.
Parameters
Component
The restyleable componentdefaultStyles
Base styles for the component
composeStyles
Explicity composes the className
and style
from props over the base defaultProps
.
Parameters
defaultStyles
Base styles for the componentprops: {className, style}
The received props to compose
Returns an object containing the composed props
, like so:
const {className, style} = composeStyles(HeyButton.defaultStyles, props)
composeStyles
Example
Note: By convention the defaultStyles object is added to the component to consumers of the component can fetch the defaults for reference or alter defaults. withStyles
will automatically add this, when manually composing styles the defaults need to be explicitly addded.
import * as React from "react";
import {composeStyles} from "react-restyle";
const defaultStyles = {
classes: {
root: 'bg-white border padding margin-sm inline-block',
hey: 'caps',
},
}
function HeyButton(props) {
const {className, style} = composeStyles(HeyButton.defaultStyles, props)
return (
<button className={className.root} style={style.root}>
<span className={className.hey} style={style.hey}>
hey
</span>
{props.children || '<SALUTATION>'}
</button>
)
}
HeyButton.defaultStyles = defaultStyles
export default HeyButton
removeClass
A utility to make altering existing classes on component cleaner:
Parameters
classes
The reference classesremove
String of space separated class names, or Array of classnames to remove fromclasses
Returns updated classes
Examples
removeClass('one two three four', 'one three') // returns 'two four'
const PlainComponent = () => {
// RedComponent has defaultStyles of {root: 'bg-red border d-flex'}
return (
<RedComponent className={{root: removeClass(SomeComponent.defaultStyles, 'bg-red')}}/>
)
}
License
MIT © Daniel Brownlees