Blueprint

System Factory

The system factory serves as an object of system-enabled JSX elements, and also a function that can be used to enable custom component receive system style props.


import { system } from '@hover/blueprint'

System JSX Elements

Create base html elements with theme-aware style props using system.<element> notation. For example, if you want a plain html button with ability to pass system styles, you can write <system.button />.

live

<system.button
px='300'
py='200'
bg='darkAlpha.200'
rounded='300'
_hover={{ bg: 'darkAlpha.300' }}
>
Click me
</system.button>

This reduces the need to create custom component wrappers and name them. This syntax is available for common html elements. See the reference for the full list of elements supported.


<system.h1 fontSize='lg'> Heading </system.h1>

System factory function

This is a function that converts non-system components or jsx element to system-enabled components so you can pass style props to them.

Consider a package called react-input-autoresize, let's use the system factory function to make possible to pass style props.

The function will infer the prop types from the wrapped component and also add system style props.


import { system } from '@hover/blueprint'
import Textarea from 'react-input-autoresize'
const AutoResizeInput = system(Textarea)
function Example() {
return <AutoResizeInput bg='danger.200' textStyle="body500" />
}

Note

Considering that the system uses emotion under the hood, ensure the non-system component accepts className as props for this to work correctly.

Attaching styles

In some instances, you might need to attach specific styles to the component wrapped in the system factory


const AutoResizeInput = system(AutoResizeInput, {
baseStyle: {
bg: 'papayawhip',
color: 'danger.600',
},
})

You can also use the system factory on jsx elements as well.


const Card = system('div', {
baseStyle: {
shadow: 'distance100',
rounded: '500',
bg: 'neutral.0',
},
})

Allowing custom props to be forwarded

By default, the system factory only filters system-related style props from getting to the DOM. For more fine-grained control of how and what prop should be forwarded, pass the shouldForwardProp option.

Here's a simple example that allows all props (including style props) to pass through except the sample prop.


const Div = system('div', {
shouldForwardProp: (prop) => !['sample'].includes(prop),
})

Another example that combines the default shouldForwardProp from Blueprint with custom logic.


import { system, shouldForwardProp } from '@hover/blueprint'
const Div = system('div', {
shouldForwardProp: (prop) => {
// don't forward Chakra's props
const isSystemProp = !shouldForwardProp(prop)
if (isSystemProp) return false
// else, only forward `sample` prop
return ['sample'].includes(prop)
},
})

To filter non-HTML attributes, you can leverage @emotion/is-prop-valid package.


import isValidHTMLProp from '@emotion/is-prop-valid'
import { system, shouldForwardProp } from '@hover/blueprint'
const Div = system('div', {
shouldForwardProp: (prop) => {
// don't forward Chakra's props
const isSystemProp = !shouldForwardProp(prop)
if (isSystemProp) return false
// forward valid HTML props
const isValidProp = isValidHTMLProp(prop)
if (isValidProp) return true
// else, only forward `sample` prop
return ['sample'].includes(prop)
},
})