New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

theme-system

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

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
Source
npmnpm
Version
0.2.9
Version published
Maintainers
1
Created
Source

Theme System

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

At Reversed 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 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/, 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:

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:

// 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:

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

Renders this 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:

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:

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

Will render output like this:

<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

PropValue
mttheme.space
mrtheme.space
mbtheme.space
mltheme.space
mxtheme.space
mytheme.space
mtheme.space
pttheme.space
prtheme.space
pbtheme.space
pltheme.space
pxtheme.space
pytheme.space
ptheme.space

DisplayProps

PropValue
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

PropValue
fontFamilytheme.fontFamilies
fontWeighttheme.fontWeights
fontSizetheme.fontSizes
colortheme.colors
textAlign'left', 'center', 'right'

BackgroundColorProps

PropValue
bgtheme.colors

FlexProps

PropValue
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, check that out if you'd like to contribute.

FAQs

Package last updated on 05 Jan 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts