I am trying to create responsive props for styled components as follows. To start with, we have a component (let's say a button):
<Button primary large>Click Me</Button>
This button will get a background-color of primary and a large size (as determined by a theme file).
I now want to create a responsive version of this button. This is how I would like that to work:
<Button
primary
large
mobile={{size: 'small', style: 'secondary'}}
tablet={size: 'small'}}
widescreen={{style: 'accent'}}
>
Click Me
</Button>
I now have my same button, but with the styles and sizes varied for different screen sizes.
Now, I have gotten this to work -- but it involves a lot of duplicate code. This is an example of what it looks like:
const Button = styled('button')(
({
mobile,
tablet,
tabletOnly,
desktop,
widescreen
}) => css`
${mobile &&
css`
@media screen and (max-width: ${theme.breakpoints.mobile.max}) {
background-color: ${colors[mobile.style] || mobile.style};
border: ${colors[mobile.style] || mobile.style};
border-radius: ${radii[mobile.radius] || mobile.radius};
color: ${mobile.style && rc(colors[mobile.style] || mobile.style)};
}
`}
${tablet &&
css`
@media screen and (min-width: ${theme.breakpoints.tablet.min}), print {
background-color: ${colors[tablet.style] || tablet.style};
border: ${colors[tablet.style] || tablet.style};
border-radius: ${radii[tablet.radius] || tablet.radius};
color: ${tablet.style && rc(colors[tablet.style] || tablet.style)};
}
`}
${tabletOnly &&
css`
@media screen and (min-width: ${theme.breakpoints.mobile.min}) and (max-width: ${theme.breakpoints.tablet.max}) {
background-color: ${colors[tabletOnly.style] || tabletOnly.style};
border: ${colors[tabletOnly.style] || tabletOnly.style};
border-radius: ${radii[tabletOnly.radius] || tabletOnly.radius};
color: ${tabletOnly.style &&
rc(colors[tabletOnly.style] || tabletOnly.style)};
}
`}
`
What I am looking for is a way to simplify this code. Basically, I want to only write the CSS styles ONCE and then generate the different props and media queries based off of a query object that something like this:
const mediaQueries = {
mobile: {
min: '0px',
max: '768px'
},
tablet: {
print: true,
min: '769px',
max: '1023px'
},
desktop: {
min: '1024px',
max: '1215px'
},
widescreen: {
min: '1216px',
max: '1407px'
},
fullhd: {
min: '1408px',
max: null
}
}
I imagine I should be able to create a function that loops through through the mediaQueries
object and inserts the appropriate css for each iteration. However, I can't seem to figure out how to do this.
Any ideas on how to do this?
Also, thanks in advance for any help you can offer.