# System

The underlying architecture of UI Kit that powers the CSS in JS styling.

![System Graph](../../../../images/system-graph.png)

- [Style Props](#style-props)
- [CSS Prop](#css-prop)
- [Split Styles](#split-styles)
- [CXS](#cxs)
- [Related Libraries](#related-libraries)

## Style Props

Styles in UI Kit are predominantly driven by style props. In a simple example, we map props to styles that can interact with a defined theme:

```jsx
<Box color="pink">Hello Box</Box>
```

This has the benefit of colocating styles making it easier to add, change, or remove as needed.

## CSS Prop

While style props takes care of most use cases, we can also define Sass-like styles through the `css` prop:

```jsx
<Box css={{ ':hover': { color: 'pink' } }}>Hello Box</Box>
```

## Split Styles

We achieve this CSS-in-JS solution through a helper [splitStyles](split-styles.js) function that will split out style props and the `css` prop from other props and generate a `className` while passing all other props through:

```jsx
function Box(props) {
  const splitProps = splitStyles(props)
  return <div {...splitProps} />
}
```

<small>See the [Box](../Box/Box.tsx) component for an actual implementation.</small>

The `splitStyles` function will also process any `mediaQueries` and `variants` props that are defined. See [Responsive](https://ministrycentered.github.io/ui-kit/responsive) and [Variants](https://ministrycentered.github.io/ui-kit/variants) for more information and examples.

### Plugins

There are two types of plugins `Global` and `Local`. Plugins allow intercepting props designated for styles and mapping them to CSS. The architecture specifically comes from Glamor's [plugin system](https://github.com/threepointone/glamor/blob/master/docs/plugins.md) and has since been modified to be more agnostic and work with `Emotion`.

#### Global

Global plugins are defined in the [plugins](plugins) directory and currently do not support user-defined plugins, only what is available and exported from [plugins/index](plugins/index.js).

```js
function colorPlugin({ backgroundColor, ...styles }, theme) {
  if (backgroundColor) {
    styles.backgroundColor = theme.colors[backgroundColor]
  }
  return styles
}
```

#### Local

Local plugins are defined in the `splitStyles` function and allow for mapping specific component props to CSS:

```jsx
const plugin = {
  // determines what props splitStyles should intercept as styles
  styleProps: ['axis', 'alignment'],
  // remove style props here to map properly and return all styles
  getStyles({ alignment, axis, ...styles }) {
    return {
      flexDirection: axis === 'horizontal' ? 'row' : 'column',
      alignItems: alignment,
      ...styles,
    }
  },
}
function StackView(props) {
  const splitProps = splitStyles({ ...props, plugin })
  return <div {...splitProps} />
}
```

<small>See the [StackView](../StackView/StackView.tsx) component for an actual implementation.</small>

## CXS

A fork of the [CXS](https://github.com/cxs-css/cxs) library is available as an escape hatch if Emotion is performing poorly. This is specifically used to combat performance issues in intensive components like `DataTable`. This is done through a `useCss` hook exported from system:

```jsx
import { designSystem } from '@planning-center/ui-kit'
function Box({ color, ...props }) {
  const css = designSystem.useCss()
  return <div className={css({ color })} {...props} />
}
```

## Related Libraries

UI Kit is built on the shoulders of giants. These libraries were and continue to be influential to the success of UI Kit.

### Initial architecture inspired by:

[Glamor](https://github.com/threepointone/glamor) (forked [split styles](https://github.com/threepointone/glamor/blob/master/src/jsxstyle.js))

[JSX Style](https://github.com/jsxstyle/jsxstyle/) (style props)

[Rebass](https://rebassjs.org/) (primitive Box component)

### Similar solutions in the wild:

[Styled System](https://styled-system.com/)

[Theme UI](https://theme-ui.com/)

[Chakra UI](https://chakra-ui.com/)

[Material UI](https://material-ui.com/)
