# theme-system

> Theme system is a libary that combines the benefits of utility class libraries like [https://tailwindcss.com/](https://tailwindcss.com/) with the DX of css-in-js libraries like Styled Components or Emotion combined with styled-system.

Latest version **0.2.9** (published 2021-01-05) · MIT license · 0 weekly downloads

## Install

```sh
npm install theme-system
pnpm add theme-system
yarn add theme-system
bun add theme-system
```

## Health

**Score 45/100 (D)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 0.2.9 |
| Published | 2021-01-05 |
| First published | 2020-07-08 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=10 |
| Dependencies | 0 |
| Unpacked size | 171.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Corjen Moll |
| Maintainers | corjen |

## Links

- npm: https://www.npmjs.com/package/theme-system
- Repository: https://github.com/reversed-digital/theme-system
- Homepage: https://github.com/reversed-digital/theme-system#readme
- Issues: https://github.com/reversed-digital/theme-system/issues
- npm.io page: https://npm.io/package/theme-system

## Recent versions

- 0.2.9 (latest) — 2021-01-05
- 0.2.9-rc1 (next) — 2023-10-30
- 0.2.0-beta.2 (beta) — 2020-07-15
- 0.2.8 — 2020-09-30
- 0.2.7 — 2020-09-30
- 0.2.6 — 2020-09-28
- 0.2.5 — 2020-08-18
- 0.2.4 — 2020-08-10
- 0.2.3 — 2020-08-10
- 0.2.2 — 2020-08-10
- 0.2.1 — 2020-08-10
- 0.2.0 — 2020-08-10
- 0.2.0-beta.1 — 2020-07-15
- 0.2.0-beta.0 — 2020-07-09
- 0.1.1 — 2020-07-09
- … 1 more at https://npm.io/package/theme-system/versions

## README

# Theme System

Theme system is a libary that combines the benefits of utility class libraries like [https://tailwindcss.com/](https://tailwindcss.com/) with the DX of css-in-js libraries like Styled Components or Emotion combined with styled-system.

At [Reversed](https://www.thinkreversed.com) we make heavy use of both styled-components and styled-system. It offers a great DX but comes at a cost, since each `Box` component and `styled.div` call adds bytes to the JS bundle and these styles are inserted during runtime. We've looked for alternatives and found [Linaria](https://linaria.now.sh/) which looks great. It's mainly the same API as styled-components, but extracts styles to static css. On the other hand we've looked at [https://tailwindcss.com/](https://tailwindcss.com/), which is gaining a lot of attention and rightfully so.

We didn't want to lose our `Box` component though and wanted the freedom of our own design system. So we've build Theme System. Theme-System combines best of both worlds; it creates a fixed set of utility-clases for maximum reusability with the DX of styled-system props.

## How to install

Run `yarn add theme-system@latest`

## Get started

For a working example with next.js & linaria, please check the examples folder.

Create a theme system config file, for example `theme-system.ts`, inside this file, create the utility classes and parser using the `createThemeSystem` function. The `createThemeSystem` function accepts a single theme object and return an object with three properties.

Your theme object should look like this:

```typescript
type Theme = {
  breakpoints: { [key: string]: string | number }
  fontWeights: { [key: string]: string | number }
  fontFamilies: { [key: string]: string | number }
  space: { [key: string]: string | number }
  colors: { [key: string]: string | number }
}
```

Example:

```typescript
// theme-system.ts
const theme = {
  breakpoints: {
    md: '1024px',
  },
  fontWeights: {
    regular: '400',
  },
  fontSizes: {
    large: '3rem',
    regular: '1rem',
  },
  fontFamilies: {
    heading: 'serif',
    body: 'sans-serif',
  },
  space: {
    '0': 0,
    '1': '1rem',
    '2': '2rem',
  },
  colors: {
    primary: '#236FEA',
    info: '#258AE7',
    success: '#27C62D',
  },
}

export type Theme = typeof theme

export const { utilities, parse, parseAll } = createThemeSystem<Theme>(theme)
```

> Note the `export type Theme = typeof theme` line, this is needed to have typechecking on your theme object.

The `utilities` property is a string containing the css with the utility classes, you should add this once inside your global css.

The `parse` & `parseAll` functions are identical in implementation, but `parse` is strictly typed based on your theme.

## parse example

The parse function allows you to generate a string of classnames based on your theme which you can use anywhere in your code. Each property can be one of the values of that property in your theme (e.g. `color: 'primary'`) or an object with one of your breakpoint keys as the key, or `_` for the initial style. For example:

```jsx
<p
  className={parse({
    color: 'primary',
    fontSize: 'large',
    fontFamily: {
      _: 'body',
      md: 'heading',
    },
  })}
>
  Using parse
</p>
```

Renders this HTML:

```html
<p class="font-family-body md-font-family-heading font-size-large color-primary">Using parse</p>
```

The `parse` function is strictly typed, so passing in invalid properties will result in a typescript.

## parseAll example

The `parseAll` function allows you to pass in a props object without strict type checking. This allows you to build custom components with typechecking on their props and passing a complete props object to `parseAll`, generating the right class names. A Box component example:

```typescript
import React, { FC, HTMLAttributes } from 'react'
import { ThemeSystemProps, filterProps } from 'theme-system'
import { Theme, parseAll } from '../lib/theme-system'
import { cx } from 'linaria'

type Props = HTMLAttributes<HTMLDivElement> & ThemeSystemProps<Theme> & {}

const Box = React.forwardRef<HTMLDivElement, Props>(({ className, children, ...props }, ref) => {
  return (
    <div className={cx(className, parseAll(props))} ref={ref} {...filterProps(props)}>
      {children}
    </div>
  )
})

export default Box
```

In this example, the `filterProps` helper removes all theme system related props from the object, preventing your div having html attributes like `color` or `height` in the DOM.

Using the Box component, a component that looks like this:

```jsx
<Box color="primary" fontSize="large" fontFamily={{ _: 'body', md: 'heading' }}>
  Using a Box component
</Box>
```

Will render output like this:

```html
<div class="font-family-body md-font-family-heading font-size-large color-primary">Using parse</div>
```

## Additional class names

Both `parse` & `parseAll` support passing an additional classname or as the second argument. For example: `parse({color:primary}, 'additional-class')` will output `color-primary additional-class`.

## Class names in production

> Important: the classnames are hashed in production, don't use them directly.

## API

This needs a little more documentation work but these props are enabled:

### SpaceProps

| Prop |    Value    |
| ---- | :---------: |
| mt   | theme.space |
| mr   | theme.space |
| mb   | theme.space |
| ml   | theme.space |
| mx   | theme.space |
| my   | theme.space |
| m    | theme.space |
| pt   | theme.space |
| pr   | theme.space |
| pb   | theme.space |
| pl   | theme.space |
| px   | theme.space |
| py   | theme.space |
| p    | theme.space |

### DisplayProps

| Prop      |                                Value                                 |
| --------- | :------------------------------------------------------------------: |
| display   | 'inline', 'block', 'flex', 'grid', 'inline-block', 'none', 'initial' |
| width     |                      '100%' , 'auto' , 'screen'                      |
| minWidth  |                      '100%' , 'auto' , 'screen'                      |
| height    |                      '100%' , 'auto' , 'screen'                      |
| minHeight |                      '100%' , 'auto' , 'screen'                      |

### TypographyProps

| Prop       |           Value           |
| ---------- | :-----------------------: |
| fontFamily |    theme.fontFamilies     |
| fontWeight |     theme.fontWeights     |
| fontSize   |      theme.fontSizes      |
| color      |       theme.colors        |
| textAlign  | 'left', 'center', 'right' |

### BackgroundColorProps

| Prop |    Value     |
| ---- | :----------: |
| bg   | theme.colors |

### FlexProps

| Prop           |                                Value                                |
| -------------- | :-----------------------------------------------------------------: |
| alignItems     |                 'center', 'flex-start', 'flex-end'                  |
| justifyContent | 'center', 'flex-start', 'flex-end', 'space-between', 'space-around' |
| flexWrap       |                       'wrap' ,'wrap-reverse'                        |

## Future plans

- Allow variants
- See if we can use purgeCSS to remove unused utilities
- Investigate a babel-plugin to compile away the parse & parseAll calls

## Contributing

Note that this is expiremtal but ideas and pr's are welcome. Theme System is based on [TSDX](https://github.com/formik/tsdx), check that out if you'd like to contribute.

---
_Source: https://npm.io/package/theme-system · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
