This is a common component in React style guides like gestalt. It gives a general primitive component that you can pass a bunch of css props to it. What makes this version of box different then other implementations is the ability to extend the box without modifying the core code. Box is a single element component meaning that the box component is very flexible with its implementation.
You will need to install these packages since they are peerDependencies.
npm install @mujo/box --save
and if you do not have React or emotion.
npm install react emotion --save
The out of the box Box component, is very limited. It currently only supports a handful of flex properties. The expectation you will want to extend Box right away.
import { Box } from '@mujo/box'
export const MyComponent = () => (
<Box display="flex" flex={0} flexWrap="nowrap">
A Box with some flex
</Box>
)
Box has only a few props that the internal component cares about: Component, and css. These two props allow you to "on the fly" change out styles, and functionality of the component.
<Box Component="a" href="/foo" css={{ textDecoration: 'underline' }}>
Go to foo
</Box>
Component
can take a string for built in components in react-dom
or custom components. This functionality allows for things like usage of Box
with react-native
(see more in extending the box).
css
is a css object that contains any css properties that you would like to apply to component.
Box is implemented in a way to be able to easily make variants of Box using the withBox
higher order component. You can pass in a style guide into the withBox
function, and also a default component. This allows the Box component to be transformed into a primitive component that exposes props of your style guide.
import { withBox } from '@mujo/box'
const Box = withBox({
styleGuide: {
foo: {
bar: { color: 'red' },
baz: { color: 'blue' },
},
},
defaultComponent: 'span',
})
export const MyComponent = () => (
<>
<Box foo="bar">Some red text</Box>
<Box foo="baz">Some blue text</Box>
</>
)
Box is also written in Typescript so we are able to add those props in a ways that makes it pretty easy to see the type hinting for each prop.
const styleGuide = {
foo: {
bar: { color: 'red' },
baz: { color: 'blue' },
},
}
const Box = withBox<typeof styleGuide>({
styleGuide,
defaultComponent: 'div',
})
In this example here would be what the props of the component looks like.
interface BoxProps extends ExistingProps {
foo: 'bar' | 'baz'
}
// ExistingProps are HTMLElement props, Component prop, and css prop.
Box supports react native but only if you extend it to pass in react native primitives.
import { View } from 'react-native'
const Box = withBox({
styleGuide: {
foo: {
bar: { color: 'red' },
baz: { color: 'blue' },
},
},
defaultComponent: View,
})
A style guide should be rigid enough to support a teams need for consistency and also flexible enough that designs do not want to exit the system. For this reason the boxes style guide implementation is just JSON
with some CSS properties.
interface StyleGuide {
[propName: string]: {
[propValue: string]: CSSObject
}
}
Note: please do not type your style guide or it will break inference.
Your team has a couple colors you want to use. Box can make it easy for the team to apply those colors to a component.
const styleGuide = {
color: {
red: { color: '#ED6173' },
blue: { color: '#6761ED' },
},
backgroundColor: {
red: { backgroundColor: '#ED6173' },
blue: { backgroundColor: '#6761ED' },
},
}
const Box = withBox({
styleGuide,
defaultComponent: 'div',
})
<Box color="red" backgroundColor="blue">My text is #ED6173</Box>
We also expose a utility called makeStyles
to stream line this.
import { makeStyles } from '@mujo/box'
const colors = {
red: '#ED6173',
blue: '#6761ED',
}
const styleGuide = {
color: makeStyles('color', colors),
backgroundColor: makeStyles('backgroundColor', colors),
}
// its still type safe!
We will be supporting more styles in the future, and potentially even some themes. To be able to reuse some of the current built in styles you can just spread them into your custom styles.
import { flexStyles } from '@mujo/box'
const styleGuide = {
...myCustomStyles,
...flexStyles,
}