<a href="https://github.com/cssinjs/styled-jss">
  <img alt="styled-jss" src="https://github.com/cssinjs/logo/blob/master/styled-jss-logo.png?raw=true" height="150px" />
</a>

# Styled Components on top of JSS

[![Travis branch](https://img.shields.io/travis/cssinjs/styled-jss/master.svg?style=flat)](https://travis-ci.org/cssinjs/styled-jss)
[![Coverage Status branch](https://img.shields.io/coveralls/cssinjs/styled-jss/master.svg?style=flat)](https://img.shields.io/coveralls/cssinjs/styled-jss/master.svg?branch=master)
[![npm version](https://img.shields.io/npm/v/styled-jss.svg?style=flat)](https://www.npmjs.com/package/styled-jss)
[![npm license](https://img.shields.io/npm/l/styled-jss.svg?style=flat)](https://www.npmjs.com/package/styled-jss)

Styled-JSS implements a styled-primitives interface on top of [JSS](https://github.com/cssinjs/jss). Its API is similar to styled-components but thanks to the JSS core, it supports all features and plugins JSS does. For e.g. you can use full [JSON Syntax](https://github.com/cssinjs/jss/blob/master/docs/json-api.md) inside.

Try it out on [playground](https://codesandbox.io/s/xl89zx8zz4).

## Default styled function

```js
import styled from 'styled-jss'

const Button = styled('button')({
  fontSize: 12,
  color: (props) => props.theme.textColor
})

// You can also use curried interface this way.
const div = styled('div')

const Container = div({
  padding: 20
})

// Composition.
const PrimaryButton = styled(Button)({
  color: 'red'
})

// Composition with unstyled React Components too.
const Button = styled(UnstyledButton)({
  color: 'blue'
})

// Component Selectors.
const ButtonContainer = styled(Container)({
  [`& ${PrimaryButton}`]: {
    color: 'green'
  }
})
```

## Theming

`styled-jss` has out of the box support for theme customization with the unified [theming](https://github.com/cssinjs/theming) package.

```js
import styled, {ThemeProvider} from 'styled-jss'

const Button = styled('button')(({margin, theme}) => ({
  margin,
  color: theme.color,
  backgroundColor: theme.backgroundColor,
}))

const themes = {
  light: {
    color: 'black',
    backgroundColor: 'yellow',
  },
}

const App = () => (
  <ThemeProvider theme={themes.light}>
    <Button margin={20}>This is themed Button</Button>
  </ThemeProvider>
)

export default App
```

## Composable styles

Example on the [CodeSandbox](https://codesandbox.io/s/y0162p38lv)

You can compose your style-objects and style-functions.

Let's say this is our **mods.js**:

```js
export const theme = ({ theme }) => ({
  color: theme.colors.primary,
  backgroundColor: theme.colors.secondary,
})

export const font = ({ bold }) => ({
  font: {
    weight: bold ? 'bold' : 'normal',
    family: 'Arial',
  },
})

export const size = ({ size = 'm' }) => ({
  s: {
    fontSize: 12,
    lineHeight: 1.2,
  },
  m: {
    fontSize: 16,
    lineHeight: 1.5
  }
})[size]

export const rounded = ({ rounded }) => rounded && { borderRadius: 5 }
```

Now we can mix them to our **Button** Component:

```js
import styled from 'styled-jss'
import {theme, font, size, rounded} from 'mods'

const Button = styled('button')(
  {
    border: 0,
    padding: [5, 10],
    display: 'inline-block',
  },
  theme,
  font,
  size,
  rounded,
)

export default Button
```

And Usage:

```js
import {ThemeProvider} from 'styled-jss'
import Button from './components/Button'

const theme = {
  dark: {
    colors: {
      primary: 'white',
      secondary: 'purple'
    }
  }
}

export default () => (
  <ThemeProvider theme={theme.dark}>
    <Button>normal button</Button>
    <Button bold>bold button</Button>
    <Button size="s">small button</Button>
    <Button rounded>rounded button</Button>
  </ThemeProvider>
)
```

## Base Style Sheet

Using base Style Sheet we can reuse classes in the render function and inside of a styled component.

```js
import { Styled, injectStyled } from 'styled-jss'

// Base styles, like a regular jss object.
const styled = Styled({
  root: {
    margin: 10,
    '& $baseButton': {
      fontSize: 16
    }
  },
  baseButton: {
    padding: 10,
    '& + &': {
      marginLeft: 10
    }
  }
})

const NormalButton = styled('button')({
  composes: '$baseButton',
  border: [1, 'solid', 'grey'],
  color: 'black'
})

// Composition - same way.
const PrimaryButton = styled(NormalButton)({
  color: 'red'
})

// One can use classes AND styled primitives.
const MyComponent = ({classes}) => (
  <div className={classes.root}>
    <NormalButton>normal button</NormalButton>
    <PrimaryButton>primary button</PrimaryButton>
  </div>
)

const MyStyledComponent = injectStyled(styled)(MyComponent)
```

## Custom JSS setup

Styled-JSS uses [jss-preset-default](https://github.com/cssinjs/jss-preset-default) by default. You can require `createStyled` function and provide your custom JSS instance.

```js
import { create as createJss } from 'jss'
import vendorPrefixer from 'jss-vendor-prefixer'
import createStyled from 'styled-jss/createStyled'

const jss = createJss()
jss.use(vendorPrefixer())

// Create a custom Styled function, that allows to set BaseStyles.
export const Styled = createStyled(jss)

// Create a custom styled function that allows to create styled components.
const styled = Styled()

export default styled
```

## Install

```sh
npm install --save styled-jss
```

Install peer dependencies `react` and `react-dom` in your project.

## License

MIT
