Skip to content

Instantly share code, notes, and snippets.

@kof
Last active March 22, 2017 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kof/3277ee04d2100bab3e6c6c33656edce7 to your computer and use it in GitHub Desktop.
Save kof/3277ee04d2100bab3e6c6c33656edce7 to your computer and use it in GitHub Desktop.
Styled Primitive Components with JSS
import injectSheet, {jss} from 'react-jss'
export function createStyled(options) {
const sheet = jss.createStyleSheet(null, options)
return function styled(tag, style) {
const {className} = sheet.addRule(Math.random(), style)
const StyledComponent = props => createElement(tag, {className, ...props})
return injectSheet(sheet)(StyledComponent)
}
}
export const styled = createStyled()
import {styled} from 'react-jss-components'
const RedButton = styled('button', {
color: 'red'
})
<RedButton>Click me</RedButton>
@kof
Copy link
Author

kof commented Oct 22, 2016

Good point by @nathanmarks:
For SSR we need to detect when a new request comes in. We can achieve that by wrapping the entire application into a JssProvider and either setting something on a context that tells our component that new request was created or provider creates a new jss instance and we just use it within the styled() fn.

@sergeysova
Copy link

Work example:

import React, { PropTypes } from 'react'
import cn from 'classnames'

const domElements = ['a', 'button', 'div', 'span', 'h1'] // etc



export default function createStyledJss(injectSheet) {
  const styledJss = (tag, name, styles) => {
    const themedStyles = { [name]: styles() }
    const sheetInjector = injectSheet(themedStyles)

    const component = ({ sheet, classes, className, ...props }) => (
      React.createElement(tag, { ...props, className: cn(classes[name], className) })
    )
    const styledComponent = sheetInjector(component)
    styledComponent.displayName = name

    return styledComponent
  }

  domElements.forEach(tag => {
    styledJss[tag] = styledJss.bind(null, tag)
  })

  return styledJss
}

Usage:

// app/styled.js

import { create as createJss } from 'jss'
import { create as createInjectSheet } from 'react-jss'
import presetDefault from 'jss-preset-default'
import createStyledJss from 'jss-styled'

export const jss = createJss()

jss.setup(presetDefault())

export const injectSheet = createInjectSheet(jss)
export default createStyledJss(injectSheet)


// app/components/button.js

import React from 'react'
import styled from '../styled'

const Button = styled.button('Button', () => ({
  backgroundColor: 'black',
  padding: 20,
  color: 'white',
}))

export default Button

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment