📜 ⬆️ ⬇️

Efficient component creation with a styled system

For styling react components, our team uses styled-components .

About styled-components, there are already articles on Habré, so we will not dwell on this in detail.

Acquaintance with Styled components
Better, faster, more powerful: styled-components v4
')
Having written many components, we found that in almost every component we copy duplicate properties.

For example, in many components we wrote this:

padding-top: ${props => props.paddingTop || '0'}; padding-bottom: ${props => props.paddingBottom || '0'}; padding-right: ${props => props.paddingRight || '0'}; padding-left: ${props => props.paddingLeft || '0'}; 

Styled system


Copying duplicate properties started to annoy, and we rendered repeated pieces of code into separate reusable functions. But I thought that maybe someone had already implemented this before us and probably more beautiful and universal. I started to google and found a styled system .

Styled-System provides a set of style functions. Each style function provides its own set of properties that stylize elements based on the values ​​defined in the application theme. The styled system has a rich API with features for most CSS properties.

An example of using a styled system based on styled-components

 import { space, width, fontSize, color } from 'styled-system'; import styled, { ThemeProvider } from 'styled-components'; import theme from './theme'; const Box = styled.div` ${space} ${width} ${fontSize} ${color} `; render( <ThemeProvider theme={theme}> <Box p={3} bg="whites.10" color="orange"> This is a Box </Box> </ThemeProvider>, ); 

Main advantages



Connection threads


Above, I gave an example of code that uses ThemeProvider. We transfer our theme to the provider, and the styled system addresses it through props.

An example of our topic

 export const theme = { /**   */ fontSizes: [ 12, 14, 16, 18, 24, 32, 36, 72, 96 ], /**    */ space: [ // margin and padding 0, 4, 8, 16, 32, 64, 128, 256 ], /**   */ colors: { UIClientError: '#ff6c00', UIServerError: '#ff0000', UITriggerRed: '#fe3d00', UITriggerBlue: '#00a9f6', UIModalFooterLightBlueGray: '#f3f9ff', UIModalTitleDefault: colorToRgba('#5e6670', 0.4), UICheckboxIconCopy: colorToRgba('#909cac', 0.2) }, /**   */ buttonSizes: { xs: ` height: 16px; padding: 0 16px; font-size: 10px; `, sm: ` height: 24px; padding: 0 24px; font-size: 13px; `, md: ` height: 34px; padding: 0 34px; font-size: 14px; letter-spacing: 0.4px; `, lg: ` height: 56px; padding: 0 56px; font-size: 20px; `, default: ` height: 24px; padding: 0 30px; font-size: 13px; `, }, /**   */ buttonColors: { green: ` background-color: #a2d628; color: ${colorToRgba('#a2d628', 0.5)}; `, blue: ` background-color: #507bfc; color: ${colorToRgba('#507bfc', 0.5)}; `, lightBlue: ` background-color: #10aee7; color: ${colorToRgba('#10aee7', 0.5)}; `, default: ` background-color: #cccccc; color: ${colorToRgba('#cccccc', 0.5)}; ` } } 

The styled system will attempt to find the value in the theme object based on the passed component properties. Deep nesting of properties is supported, if the transferred value is not found in the subject, then the value is interpreted as is.

For example, we passed the component color = "red". The theme object has no color.red value, but the red value will be translated into css as red. Thus, after transpiling in the inspector, we will see

 color: red; 


Other examples of using theme values.
 // font-size: 24px (theme.fontSizes[4]) <Box fontSize={4} /> // margin: 16px (theme.space[3]) <Box m={3} /> // color: #ff6c00 (theme.colors.UIClientError) <Box color="UIClientError" /> // background color (theme.colors.UITriggerBlue) <Box bg="UITriggerBlue" /> // width: 50% <Box width={1/2} /> 

Responsive styles


To quickly describe responsive properties, just pass an array of values.

 <Box width={[ 1, // 100% below the smallest breakpoint 1/2, // 50% from the next breakpoint and up 1/4 // 25% from the next breakpoint and up ]} /> // responsive font size <Box fontSize={[ 1, 2, 3, 4 ]} /> // responsive margin <Box m={[ 1, 2, 3, 4 ]} /> // responsive padding <Box p={[ 1, 2, 3, 4 ]} /> 

Variants


The styled system allows us to define reusable objects in our theme that contain color sets, text styles, and so on. For example, in our topic presented above, we
use the options of sizes and colors of buttons.

  /**   */ buttonSizes: { xs: ` height: 16px; padding: 0 16px; font-size: 10px; `, sm: ` height: 24px; padding: 0 24px; font-size: 13px; `, default: ` height: 24px; padding: 0 30px; font-size: 13px; `, }, /**   */ buttonColors: { green: ` background-color: #a2d628; color: ${colorToRgba('#a2d628', 0.5)}; `, blue: ` background-color: #507bfc; color: ${colorToRgba('#507bfc', 0.5)}; `, lightBlue: ` background-color: #10aee7; color: ${colorToRgba('#10aee7', 0.5)}; `, default: ` background-color: #cccccc; color: ${colorToRgba('#cccccc', 0.5)}; ` } 

Implementation option:

 /**    */ export const buttonSize = variant({ /**   */ prop: 'size', /**  */ key: 'buttonSizes' }); /**    */ export const buttonColor = variant({ /**   */ prop: 'colors', /**  */ key: 'buttonColors' }); 


Button component
 /**   */ export const Button = styled(Box.withComponent('button'))` ${buttonSize} ${buttonColor} `; Button.propTypes = { ...buttonSize.propTypes, ...buttonColor.propTypes, } 

Example of using the medium size button in blue

 <Button size="md" colors="blue" /> 

A more detailed description and documentation of the styled system at the office. page in github

UPD: while writing an article, the styled system has got its own page with documentation and examples https://styled-system.com/ .

Source: https://habr.com/ru/post/441790/


All Articles