I have a StyledButton
, and I use it like this:
const StyledButton = styled.div<{
hoverStyle?: CSSProperties
}>`
color: black;
background: blue;
// What can I do here to apply the hoverStyle?
`
<StyledButton
hoverStyle={{
backgroundColor: 'red',
color: 'white',
}}
>
My button
</StyledButton>
Are there any ways to do that?
Usually we provide individual values in extra styling props, but it is still definitely possible to provide a set of CSS rules (a CSSObject).
First you need to use an interpolation function to adapt the style based on runtime props:
const StyledButton = styled.div<{
hoverStyle?: CSSProperties
}>`
color: black;
background: blue;
// What can I do here to apply the hoverStyle?
${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
`
Here I used an inlineRules
function to convert the CSSObject into a list of rules:
function inlineRules(rulesObj: CSSProperties) {
return Object.entries(rulesObj).map(([property, value]) => `${property}: ${value};`).join('');
}
Then, based on the "hoverStyle" name of your styling prop, it sounds like these rules should be applied only on :hover
, rather than being directly merged with the root styles of your <div>
. In that case, you need to place them in a nested block, for which you can use the &
ampersand keyword to refer to the self style:
&
a single ampersand refers to all instances of the component; it is used for applying broad overrides
&:hover {
${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
}
Live demo on CodeSandbox: https://codesandbox.io/s/sleepy-brook-h515v7?file=/src/App.tsx
Note: CSS rules in styled-components actually use the normal "kebab-case" notation, whereas CSSProperties
are defined in camelCase ("background-color" v.s. "backgroundColor" in your example). In the above demo, I used a template literal conversion type to convert them into kebab-case, based on TypeScript add kebab case types form actual camel case keys