1.74.0 • Published 5 years ago

systemthing v1.74.0

Weekly downloads
7
License
MIT
Repository
github
Last release
5 years ago

A System Thing

Responsive, theme-based style props for building design systems in React JavaScript

Build Status Version size MIT License

npm i systemthing

This repository is a fork of the styled-system.

As with styled-system, this fork presents a collection of css-style yielding functions that support the development of responsive and theme-based design systems in JavaScript.

Unlike styled-system, this implementation is geared to also work with virtual dom libraries other than React.

Features

This fork provides the same core functionality found in the orignal styled-system libary,

plus:

minus:

  • Social proof, i. e. not used in Rebass et al.

Table of Contents

Notable differences

While this implementation tries to stay as close as possible to styled-system's original API, the following changes were made:

non-contextual theming

Style yielding functions can be called with a custom theme by passing a theme-object as a second argument.

import { space, fontSize, color } from 'systemthing'

const theme = {
 breakpoints: [ '32em', '48em', '64em' ],
 space: [ 0, 6, 12, 18, 24 ],
 fontSizes: [ 12, 16, 18, 24, 36, 72 ],
 radii: [ 2, 4 ],
 colors: {
   blue: '#07c',
   green: '#1c0',
   gray: ['#ccc', '#555']
 }
}
                       
// aliases
theme.space.big = 64
theme.fontSizes.big = 128

const blue = color({ color: 'blue' }, theme) // yields { color: '07c' }
const big = fontSize({ fontSize: 'big' }, theme) // yields { fontSize: '128px' }
const butAlso = space({ padding: 'big', theme }) // yields { padding: '64px' }

Passing a theme as 2nd argument bypasses React context and allows this implementation to work in concert with any virtual DOM based view layer.

It is still possible however to also use theme as a prop on the first argument. Prop based themes take precedence. styled-system's original theming mechanism remains intact.

No prop abbreviations

Mapping of popular style prop abbreviations to corresponding css properties (e. g. mt to marginTop) is delegated downstream. The only exceptions are mx, my, px and py within the space function. For there are no css equivalents to these props.

Default values

It is possible to directly instrument style yielding functions with default values as a fallback in case no corresponding style props are present at call time.

import { space } from 'systemthing'

const spaceWithDefaults = space.withDefaults({ padding: '1em' })

const spaced = spaceWithDefaults({ foo: 'bar' }) // { padding: '1em' }

Responsive default styles may be useful for defining components that do not require expensive style re-computations down the line.

Prop bundling

To minimize the number of downstream function calls, style props are bundled into a single function where possible.

import { flexbox } from 'systemthing'

const flexing = flexbox({
  display: 'flex',
  justifyContent: 'center',
  flexDirection: 'row-reverse'
})

The following prop bundles are available:

1. backgrounds

bundled props: background, backgroundImage, backgroundPosition, backgroundRepeat, backgroundSize

2. borders

bundled props: border, borderTop, borderRight, borderBottom, borderLeft

3. color

bundled props: color, backgroundColor

4. direction

bundled props: top, right, bottom, left

5. flexbox

bundled props: display, alignContent, alignSelf, justifyContent, justifyItems, justifySelf, flex, flexBasis, flexDirection, flexWrap, order

6. gridLayout

bundled props: gridArea, gridAutoColumns, gridAutoFlo', gridAutoRows, gridRow, gridRowGap, gridTemplateAreas, gridTemplateColumns, gridTemplateRows

7. gridGaps

bundled props: gridColumnGap, gridGap, gridRow, gridRowGap,

8. space

bundled props: margin, marginTop, marginRight, marginBottom, marginLeft, mx, my, padding, paddingTop, paddingRight, paddingBottom, paddingLeft, px, py

No PropTypes

Facebook's prop-types has been removed. Instead type declaration is delegated downstream. Users of this fork have to be prepared to properly type out components themselves, if necessary. This fork ships without external dependencies.

Width fit & fill

The width style yielding function accepts two additional prop values:

  • { width: 'fit' } - Make an element shrink wrap its content with flex-basis.
  • { width: 'fill' } - Make an element fill the remaining space. Distribute space evenly on multiple elements.

low level changes

get

The get utility function accepts excactly two arguments obj :: Object and path :: Array. get's path argument is not being destructured.

Hence, instead of writing:

// wrong
let bingo = get({ path: { in: { obj: 'Bingo' } } }, 'path', 'in', 'obj')

you'd have to write:

// correct
let bingo = get({ path: { in: { obj: 'Bingo' } } }, [ 'path', 'in', 'obj' ])

Secondly, dot notation in path strings is not supported out of the box. The following statement will fail to produce the desired result:

// wont work
let bingo = get({ path: { in: { obj: 'Bingo' } } }, [ 'path.in.obj' ])

Note: Refactoring the get function apparently resulted in significant performance improvements for some style functions.

num

The num utility is renamed to isNum.

px

The px transformation utility is renamed to addPx.

cloneFunc

The cloneFunc utility has been removed together with the prop-types dependency.

merge

The merge utility is renamed to mergeStyles.

compose

The compose utility is renamed to composeStyleFns. (may be removed entirely, as it is only used in a benchmarking script right now)

style

The style utility function is renamed to createStyleFn. The original function was refactored to also process arrays when passed as prop and cssProptery arguments. This enables the prop bundling functionality described above.

import { util } from 'systemthing'

const custom = util.createStyleFn({
  prop: [ 'display', 'overflow', 'opacity' ]
})

const result = custom({ display: 'none', overflow: 'hidden' })

mixed

The mixed utility has been removed entirely.

Usage

This implementation maintains most of styled-system's original API.

Here is an idiomatic usage example:

// Usage in tandem with compatible css-in-js lib is recommended
// Example uses bss, but systemthing works with most other css-in-js libraries as well
import b from 'bss'
import { color, fontSize, util } from 'systemthing'

// custom theme
const theme = {
 breakpoints: [ '32em', '48em', '64em' ],
 space: [ 0, 6, 12, 18, 24 ],
 fontSizes: [ 12, 16, 18, 24, 36, 72 ],
 colors: {
   blue: '#07c',
   green: '#1c0',
   grays: [ '#ccc', '#555', '#ddd' ]
 }
}

// define style props
const props = {
  // responsive background-color (theme.colors)
  backgroundColor: [ 'blue', 'green', 'grays.1', 'grays.2' ],
  // responsive font-size of 24px, 36px or 72px (theme.fontSizes)
  fontSize: [ 3, 4, 5 ],
  // theme passed as prop
  theme
}

// pass style props into the style functions and merge their return values
const result = util.mergeStyles(color(props), fontSize(props))

// result is a responsively themed css style object that
// can then be processed downstream by many css-in-js libraries
const classy = b(result).class

document.body.classList.add(classy)
document.body.appendChild(
  document.createTextNode(
    'Responsively themed! (resize the window!)'))

A live version of this script is available on flems.

Usage within the React ecosystem

Usage in combination with React and React-focused css-in-js libraries such as styled-components or emotion should work as advertised in styled-stystem's documentation (not tested, YMMV).

// Example uses react and styled-components, but systemthing works with most other vdom and css-in-js libraries as well
import React from 'react'
import ReactDOM from 'react-dom' // virtual DOM libary
import styled from 'styled-components' // css-in-js layer / component factory
import { space, width, fontSize, color } from 'systemthing'

// custom theme
const theme = {
 breakpoints: [ '32em', '48em', '64em' ],
 space: [ 0, 6, 12, 18, 24 ],
 fontSizes: [ 12, 16, 18, 24, 36, 72 ],
 colors: {
   blue: '#07c',
   green: '#1c0',
   grays: ['#ccc', '#555']
 }
}

// Add style yielding functions to your component
const Box = styled.div`
  ${space}
  ${width}
  ${fontSize}
  ${color}`

ReactDOM.render(  
  <Box
    // width: 50%
    width={1 / 2}
    // responsive font-size of 24px, 36px or 72px (theme.fontSizes)
    fontSize={[ 3, 4, 5 ]}
    // margin: 12px (theme.space[2])
    margin={2}
    // padding: 18px (theme.space[3])
    padding={3}
    // color: #ccc (theme.colors.grays[0])
    color='grays.0'
    // responsive background-color (theme.colors)
    backgroundColor={[ 'blue', 'green', 'grays.0', 'grays.1' ]}
    // theme passed as prop
    theme={theme}>Hello React!</Box>
, document.body)

A live version of the script is available on flems..

Usage with other vdom libaries

This fork definitely also works well in concert with the more exotic bss and stylething utilities, as well as vdom libaries other than React.

// Example illustrates usage with mithril, bss and stylething 
import m from 'mithril' // virtual DOM libary
import b from 'bss' // css-in-js layer
import { createStyler } from 'stylething' // component factory
import { space, width, fontSize, color } from 'systemthing'

// custom theme
const theme = {
 breakpoints: [ '32em', '48em', '64em' ],
 space: [ 0, 6, 12, 18, 24 ],
 fontSizes: [ 12, 16, 18, 24, 36, 72 ],
 colors: {
   blue: '#07c',
   green: '#1c0',
   grays: [ '#ccc', '#555', '#ddd' ]
 }
}

// instrument stylething's component factory with the vdom lib and bss css-in-js package
// note custom theme passed as a config option
const styled = createStyler(m, b, { mode: 'mithril', output: 'class', theme })

// Add a custom class name and style yielding functions to your component
const Box = styled('.Box', space, width, fontSize, color)

m.mount(document.body, {
 view: () =>
  m(Box, {
    // widthL 50%
    width: 1 / 2,
    // responsive font-size of 24px, 36px or 72px (theme.fontSizes)
    fontSize: [ 3, 4, 5 ],
    // margin: 12px (theme.space[2])
    margin: 2,
    // padding: 18px (theme.space[3])
    padding: 3,
    // color: #ccc (theme.colors.grays[0])
    color: 'grays.0',
    // responsive background-color (theme.colors)
    backgroundColor: [ 'blue', 'green', 'grays.1', 'grays.2' ]
  }, 'Hello Mithril!')
})

A live version of this script is available on flems.

Docs

TODO

Related

MIT License