oirodolfo
8/20/2018 - 6:01 PM

Programmatically create responsive styled components with react and styled-components

Programmatically create responsive styled components with react and styled-components

// this file is just here to change the name of the gist
import React from 'react'
import styled from 'styled-components'

const makeResponsiveComponent = (rulesets, tagName = 'div') =>
  styled(tagName)`${buildStyles(rulesets)}`

const buildStyles = rulesets =>
  rulesets.reduce(
    (cssString, { constraint, width, rules }) =>
      `${cssString} @media (${constraint}-width: ${width}) { ${rules} }`
    , '')

export const hideAt = breakpoints => {
  const rulesets = Object.entries(breakpoints).reduce(
    (rulesets, [constraint, width]) =>
      [...rulesets, {
        constraint,
        width,
        rules: `display: none;`
      }]
    , []
  )

  return makeResponsiveComponent(rulesets)
}

export const Breakpoint = ({ min, max, children }) => {
  const Component = hideAt({ min, max })
  return <Component>{children}</Component>
}

export default makeResponsiveComponent
import React from 'react'
import styled from 'styled-components'
import ResponsiveFonts from './responsive-fonts'
import {
  MediumAndUp,
  LargeAndUp,
  SmallAndDown,
  MediumAndDown,
  MediumOnly
} from './breakpoints.jsx'
import { Breakpoint } from './make-responsive-component'


const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
  text-align: center;
`

export default () =>
  <Wrapper>
    <ResponsiveFonts>
      <SmallAndDown>sm and down</SmallAndDown>
      <MediumAndUp>med and up</MediumAndUp>
      <MediumAndDown>med and down</MediumAndDown>
      <MediumOnly>medium only</MediumOnly>
      <LargeAndUp>lg and up</LargeAndUp>
      <Breakpoint max="1200px">only on huge width</Breakpoint>
    </ResponsiveFonts>
  </Wrapper>
import { hideAt } from './make-responsive-component'

export const SmallAndDown = hideAt({ min: '320px' })
export const MediumAndDown = hideAt({ min: '960px' })
export const MediumOnly = hideAt({ max: '640px', min: '960px' })
export const MediumAndUp = hideAt({ max: '640px' })
export const LargeAndUp = hideAt({ max: '960px' })
// functions to generate styled components with any arbitrary sets of style rules and corresponding breakpoints
import React from 'react'
import styled from 'styled-components'

const makeResponsiveComponent = (rulesets, tagName = 'div') =>
  styled(tagName)`${buildStyles(rulesets)}`

const buildStyles = rulesets =>
  rulesets.reduce(
    (cssString, { constraint, width, rules }) =>
      `${cssString} @media (${constraint}-width: ${width}) { ${rules} }`
    , '')

export const hideAt = breakpoints => {
  const rulesets = Object.entries(breakpoints).reduce(
    (rulesets, [constraint, width]) =>
      [...rulesets, {
        constraint,
        width,
        rules: `display: none;`
      }]
    , []
  )

  return makeResponsiveComponent(rulesets)
}

export const Breakpoint = ({ min, max, children }) => {
  const Component = hideAt({ min, max })
  return <Component>{children}</Component>
}

export default makeResponsiveComponent
// example usage
import makeResponsiveComponent from './make-responsive-component'

export default makeResponsiveComponent(
  [
    {
      constraint: 'min',
      width: '0px',
      rules: `
        font-size: 14px;
        color: rebeccapurple;
      `
    }, {
      constraint: 'min',
      width: '320px',
      rules: `
        font-size: 28px;
        color: cyan;
      `
    }, {
      constraint: 'min',
      width: '640px',
      rules: `
        font-size: 42px;
        color: green;
      `
    }, {
      constraint: 'min',
      width: '960px',
      rules: `
        font-size: 56px;
        color: red;
      `
    }
  ]
)