Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

TEREN VELAN
TEREN VELAN

Posted on

     

Creating Variants of React Component

So recently i've been working on building react components with StorybookJS. For those who don't know what Storybook is ,Storybook is a JavaScript tool that allows developers to create organised UI systems making both the building process and documentation more efficient and easier to use.

With that said , i would like to share a common design pattern that i learned from building these components, and that is creating variants of a single component through the use of props.

*Do note that i'm using ChakraUI as my UI library

In this example we take a look at building a simple button component. Starting with the Button function

exportfunctionReactButton(props){let{children}=props;return(<Button>{children}</Button>);}
Enter fullscreen modeExit fullscreen mode

Following that , we add propTypes to establish our variants, you can definitely do without this step but it helps to ensure we're using the right data type

ReactButton.propTypes={variant:PropTypes.arrayOf(PropTypes.oneOf(["primary,secondary,outline,danger"])),};exportfunctionReactButton(props){let{children}=props;return(<Button>{children}</Button>);}
Enter fullscreen modeExit fullscreen mode

Now for the game changer, we make use of CSS to enable to the browser to display what we want want it to display. Using a switch statement we set the base styles for different variants

letbaseStyles={},invertStyles={},stretchedStyles={};switch(variant){case"primary":baseStyles={backgroundColor:"brand1.primary.400",color:"#fff",_hover:{backgroundColor:"brand1.primary.500",},};break;case"secondary":baseStyles={backgroundColor:"brand1.secondary.400",color:"#fff",_hover:{backgroundColor:"brand1.secondary.500",},};break;case"outline":baseStyles={backgroundColor:"transparent",color:"brand1.secondary.300",borderColor:"brand1.secondary.300",_hover:{color:"brand1.secondary.500",borderColor:"brand1.secondary.500",},};break;case"danger":baseStyles={backgroundColor:"brand1.danger.400",color:"#fff",_hover:{backgroundColor:"brand1.danger.500",},}break;
Enter fullscreen modeExit fullscreen mode

You will notice i created an empty object for inverted and stretched, keep reading on to see how we implement those.

With that we set our default variant to primary, and establish some props like invert and stretched and give them a boolean value

let{children,variant="primary",invert=false,stretched=false,}=props;
Enter fullscreen modeExit fullscreen mode

Now we can go ahead and add stylings for our props that we declared (invert and stretched).

switch(variant){case"primary":baseStyles={backgroundColor:"brand1.primary.400",color:"#fff",_hover:{backgroundColor:"brand1.primary.500",},};if(invert){invertStyles={backgroundColor:"brand1.primary.50",border:"0.25rem solid #ffe8ae",color:"#969696",_hover:{backgroundColor:"brand1.primary.100",},};}if(stretched){stretchedStyles={width:"100%",justifyContent:"space-between",};}break;case"secondary":baseStyles={backgroundColor:"brand1.secondary.400",color:"#fff",_hover:{backgroundColor:"brand1.secondary.500",},};if(invert){invertStyles={backgroundColor:"brand1.secondary.50",border:"0.25rem solid #c4c9ef",color:"#969696",_hover:{backgroundColor:"brand1.secondary.100",color:"#fff",},};}if(stretched){stretchedStyles={width:"100%",justifyContent:"space-between",};}break;case"outline":baseStyles={backgroundColor:"transparent",color:"brand1.secondary.300",borderColor:"brand1.secondary.300",_hover:{color:"brand1.secondary.500",borderColor:"brand1.secondary.500",},};if(invert){invertStyles={color:"#c9c9c9",borderColor:"#c9c9c9",_hover:{color:"#fff",borderColor:"#fff",},};}if(stretched){stretchedStyles={width:"100%",justifyContent:"space-between",};}break;case"danger":baseStyles={backgroundColor:"brand1.danger.400",color:"#fff",_hover:{backgroundColor:"brand1.danger.500",},};if(invert){invertStyles={backgroundColor:"brand1.danger.50",border:"0.25rem solid #feb6b9",color:"#969696",_hover:{backgroundColor:"brand1.danger.100",color:"#fff",},};}if(stretched){stretchedStyles={width:"100%",justifyContent:"space-between",};}break;
Enter fullscreen modeExit fullscreen mode

Now that we have our complete styles in place and in a conditional statement , let us look at how we can use this styles in our component.

By spreading our stylings into the component through the object spread operator. Take note on the order in which the styles are added.

return(<Button{...baseStyles}{...props}{...invertStyles}{...stretchedStyles}>{children}</Button>);}
Enter fullscreen modeExit fullscreen mode

Now about the order in which we have placed our props , baseStyles first followed by props then invertStyles and lastly stretchedStyles. The order is very important as the latter props on the list will take precedence over the styles of the earlier props on the list. Thats why we have baseStyles first , this give the developer the flexibility to deviate from the baseStyles.

To demonstrate, i will show 4 different buttons using the variant="danger" and the invert and stretched props

<Buttonvariant="danger">DangerButton</Button>
Enter fullscreen modeExit fullscreen mode

Screenshot 2021-09-26 at 11.51.50 PM

<Buttonvariant="danger"stretched>DangerButton</Button>
Enter fullscreen modeExit fullscreen mode

Screenshot 2021-09-26 at 11.52.48 PM

<Buttonvariant="danger"invert>DangerButton</Button>
Enter fullscreen modeExit fullscreen mode

Screenshot 2021-09-26 at 11.53.45 PM

<Buttonvariant="danger"invertstretched>DangerButton</Button>
Enter fullscreen modeExit fullscreen mode

Screenshot 2021-09-26 at 11.54.29 PM

Thats all folks , i hope this helps you as much as it has helped me. If theres any way i can improve on this i would really love to hear it. Drop a comment below.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Junior Developer , looking to learn and improve. Using this platform to document whatever i've learnt
  • Location
    Sunny Island of Singapore
  • Work
    Junior Software Developer at Getpaid
  • Joined

More fromTEREN VELAN

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp