segmentio/ui-box

@media queries

junaid33 opened this issue ยท 6 comments

Hello,

Just wanted to say that ui-box is so convenient for CSS-in-JS. My question is can we do media queries using props? We are currently using other CSS-in-JS libraries and would like to just use ui-box if possible. Thank you!

Rowno commented

I've been trying to come up with a good API that's nice to use while still being performant but I haven't thought of one yet.

But since they're just regular React props, you can easily use something like react-media as a workaround.

import React from "react"
import Media from "react-media"
import Box from "ui-box"

const mobileStyles = {
  background: 'green'
}

const desktopStyles = {
  background: 'yellow'
}

class App extends React.Component {
  render() {
    return (
      <div>
        <Media query="(max-width: 599px)">
          {isMobile => (
            <Box
              color={isMobile ? 'red' : 'blue'}
              {...(isMobile ? mobileStyles : desktopStyles)}
            >
              Test
            </Box>
          )}
        </Media>
      </div>
    )
  }
}

I'm open to suggestions though.

There are two types of responsive design imo, on a property level, and component level.

  • Property level, you want a single property such as padding to change based on the viewport/parent
  • Component level, you want a component or structure to be different based on the viewport/parent

As for the Component level, I think in most cases you will need something like <MediaQuery> or even. As for property level I have some random thoughts below.

Array of values for predefined breakpoints

<MediaQueryProvider queries={['(max-width: 359px)', '(max-width: 599px)', '(max-width: 959px)']}>
   <Box padding={[8, 16, 32]} />
</MediaQueryProvider>

Array of values for predefined breakpoints

<MediaQueryProvider queries={['(max-width: 359px)', '(max-width: 599px)', '(max-width: 959px)']}>
   <Box padding={[8, 16, 32]} />
</MediaQueryProvider>

Properties could be functions taking a width

<Box color={width => width > 600 ? 'red' : 'blue} />

Return responsive props

<Box
  responsiveProps={width => {
    if (width < 360) return { padding: 8, margin: 8 }
    return { padding: 16, margin: 16 }
  }}
/>

Generate computed CSS custom properties (variables)

I am on the fence if this would actually work.

function createResponsiveValue(small, medium, large) {
  injectCSS(`
     @media (max-width: 359px) { --generated-var: ${small}; }
     @media (max-width: 599px) { --generated-var: ${medium}; }
     @media  (max-width: 959px) { --generated-var: ${large}; }
  `)
  return `var(--generated-var)`;
}

const R = createResponsiveValue;
<Box
  margin={R(8, 16, 32)}  
/>

@jeroenransijn The array props looks the best to me. I like the way facepaint handles this. They also handle pseudo-selectors in the same way which could be a bonus.

I want to like the function props but I'm not sure how that would be converted to a media query efficiently, which I believe is the goal here no? Perhaps this is also an opportunity to switch to emotion or styled-component or something? IDK If that would make these enhancements easier.

@jeroenransijn I would suggest also looking at what's been described here: https://usehooks.com/useMedia, which complements Array of values for predefined breakpoints

fs-c commented

Any news on this?

is there an interim recommendation or practice for media queries that plays well with evergreen?