Pass props only once from JS to CSS-in-JS

305 Views Asked by At

I'm working on a reusable sidebar, with React & CSS-in-JS with the @emotion/react library

I have a ReactComponent that returns something like this:

 return (
    <s.SidebarContainer 
        backgroundImage={backgroundImage} 
        isOpen={isOpen}>
        <s.TogglerContainer 
            onClick={() => setIsOpen(!isOpen)} 
            isOpen={isOpen}>
        </s.TogglerContainer>
        <s.SidebarHeader 
        font={fonts.header}
        >
            {header}
        </s.SidebarHeader>
        <s.MenuContainer>{menuItemsJSX}</s.MenuContainer>
    </s.SidebarContainer>
)

As you can see, I attach the props to each style component. And this is my style.js:

import styled from '@emotion/styled';


export const SidebarContainer = styled.div`
width: ${p => p.isOpen ? '18%' : '5%'} ;
background-image: 
linear-gradient(
    315deg,
    rgba(252,82,150,0.8) 0%,
    rgba(246,112, 98, 0.8) 74%),
    url(${p => p.backgroundImage}
);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
color: white;
position: relative; // Toggler
transition: .2s ease-in all;

@media (max-width: 576.97px){ 
    width: ${p => p.isOpen ? '80%' : '15%'} ;
}

@media (min-width: 577px) and (max-width: 992px){ 
    width: ${p => p.isOpen ? '30%' : '7%'} ;
}
`


export const SidebarHeader = styled.h3`
text-align: center;
height:10%;
margin-top: .5em;
letter-spacing: .1em;
font-size: 1em;
font-family: ${p => p.font};
overflow: hidden;
padding: 0em .3em;
`

export const TogglerContainer = styled.div`
    position: relative;
    
    &:after{
        ${p => p.isOpen ? `content:'<';`
                        : `content:'>';`}
        text-align:center;
        position:absolute;
        background-color: #E58C8A;
        background-image: linear-gradient(315deg, #E58C8A 0%, #EEC0C6 74%);
        right:0;
        transform: translateX(12px);
        width: 24px;
        height: 24px;
        margin-top:2em;
        border-radius: 50%;
        color:rgb(19,15,64);
        box-shadow: 4px 2px 2px rgba(0,0,0,0.3);
        transition:  .2s ease-in box-shadow;
    }
    &:hover{
        &:after{
            box-shadow: 5px 3px 3px rgba(0,0,0,0.3);
            transition:  .2s ease-in all;
        }
    }

    `

I just put a part of code to avoid fill your display. My question is:

There's some way to send the props to .style.js file only once (through file instead through component), and then in .style.js file recive it and use it globally?

For example, i want had something like this,

  <s.SidebarContainer 
    backgroundImage={backgroundImage} >
    <s.TogglerContainer 
        onClick={() => setIsOpen(!isOpen)}>

(see what i removed isOpen={isOpen} )

1

There are 1 best solutions below

0
On

You must provide the prop to each styled component that depends on the prop.

Each styled component is a react component, and emotion will re-render the component when the props change, allowing you to adjust the styles based on props. It would not be possible to pass the isOpen state to only one styled component and share that state with the rest of the styled components because each component must receive the isOpen state via its own props.