sullivan
Version:
Tools to quickly build interfaces in JS
325 lines (244 loc) • 9.13 kB
Markdown
Sullivan
===========
*Totally WIP: Here be dragons*
**What?**
Opinionated toolkit to quickly build visual interfaces in JS.
**Why?**
:white_check_mark: Because we're humans who make mistakes and need constraints around a predefined styleguide.
:white_check_mark: Because some css patterns are really annoying to rewrite all the time.
:white_check_mark: Because there are too many different ways to peel this potato (styling in JS) and sometimes we just want to write code.
:white_check_mark: Because we're lazy developers.
**How?**
Uses Aphrodite [https://github.com/Khan/aphrodite](https://github.com/Khan/aphrodite) under the hood to dynamically generate classnames and inject styles.
Prefixes everything so you don't have to think about it (thanks to Aphrodite);
Provides a library of functional css styles generated according to passed in styleguide values.
Abstracts around overly verbosed css syntaxes.
Includes a set of transform functions to inject dynamic styles.
Sullivan is built with React in mind but doesn't depend on it so can be used in other non-react project.
## Installation
Using [npm](https://www.npmjs.com/):
$ npm install sullivan
Then with a module bundler like [webpack](https://webpack.github.io/) that supports either CommonJS or ES2015 modules, use as you would anything else:
```js
// sully.js
// using an ES6 transpiler, like babel
import Sullivan from 'sullivan'
import {StyleSheet, css} from 'aphrodite'
import Styleguide from './styleguide' // BYOS - Bring Your Own Styleguide!
```
## Usage
Initialize the singleton somewhere in your project, Sullivan comes with opinional defaults but you should pass in your own map of values according to your project styleguide.
####**for a detailed example check out [The example project](https://github.com/adrianleb/sullivan/blob/master/example/index.js)**
```js
// ...
const sully = new Sullivan({
aphroditeStylesheet: StyleSheet,
styleguide: Styleguide
});
export default sully;
// Alternatively you can also export just set of things to work with using a convention your team agrees on.
const {utils: classes, rawUtils: raw, inline, mq, z, styleguide} = sully;
const {colors, sizes, textSizes} = styleguide;
export {
classes,
raw,
inline,
mq,
z,
colors,
sizes,
textSizes
}
```
Then inside your component:
```js
// component.js
import {classes, inline, raw, lineHeights} from './sully';
const FunkyComponent = () => {
return (
<div
className={css(
ss.wrap,
classes.flex.center,
classes.text.yellow,
classes.bg.cover
)}
style={
inline.bg.image("https://placekitten.com/200/300")
}>
Content will be flex centered and yellow with a pretty kitten covering the background!
</div>
);
};
const ss = StyleSheet.create({
wrap: {
...raw.bg.blue,
...raw.ma.large,
lineHeight: lineHeights.loose
}
});
```
### Using your own Styleguide
When bootstraping Sullivan you must pass in a styleguide configuration containing:
- `sizes`: for margins and paddings
- `colors`: for backgrounds, text colors, svg colors...
- `textSizes`: for text sizes (good ol' typography)
- `lineHeights`: for text sizes (good ol' typography)
- `z`: for depth mapping, (default to z[0-9])
[You can see an example styleguide here](https://github.com/adrianleb/sullivan/blob/master/example/styleguide.js)
A styleguide map is an object with a human readable keys (to be used across utils) and values, with the exception of z-index and reset styles handling
You're welcome to call your keys anything you want, just be careful not to make them clash (for example, calling a color 'medium' and a textSize 'medium' will break your text utils).
## API
### `sheet`
Alias for Aphrodite's `StyleSheet` object.
`sheet.create` will generate a new set of unique classnames ready for injection, based on a passed in object of styles.
### `class`
Alias for Aphrodite's `css` object.
Combines generated classnames (either from `StyleSheet.create` or from `sullivan.util`) left to right and injects styles into document `head`.
### `rawUtil`
Catalogue of small abstractions around common css patterns.
### `util`
Same as `rawUtils` but pre-transformed by Aphrodite's `Stylesheet.create` method and ready for injection using `class`
### `inline`
Functional utils returning an object with a transformed css declaration.
### `z`
the same object passed in (or the default) of z-indexes to be used in custom stylesheets.
##Utils
New utils are constantly being added, this is the current list:
- spacing
- pos
- disp
- bg
- svg
- text
- flex
- cursor
#### Spacing
**Requires sizes**
Mapping to margins and paddings according to passed in size values,
for ease of use they are not namespaced by `spacing` but shorthanded based on their function:
- `ma/pa`: Margin/Padding All (top, right, bottom, left)
- `mv/pv`: Margin/Padding Vertical (top, bottom)
- `mh/ph`: Margin/Padding Horizontal (right, left)
- `mt/pt`: Margin/Padding Top
- `mb/pb`: Margin/Padding Bottom
- `ml/pl`: Margin/Padding Left
- `mr/pr`: Margin/Padding Right
The values are based on what you pass through the `sizes` argument.
Example based on defaults:
`utils.mt.small // outputs a classname with {margin-top: 5px}`
#### Disp
**No requirements**
Mapping to css display values
- `inline` : {display: inline}
- `inlineBlock` : {display: inline-block}
- `block` : {display: block}
- `flex` : {display: flex}
- `none` : {display: none}
Example:
`util.disp.flex // outputs a classname with {display: flex}`
#### BG
**Requires colors**
Mapping to background-color values according to passed in colors, also a small set of quick patterns.
Example based on defaults:
`util.bg.black // outputs a classname with {background-color: '#000'}`
##### bg.cover
Outputs:
```css
{
background-size: 'cover',
background-position: 'center',
background-repeat: 'no-repeat'
}
```
#### SVG
**Requires colors**
Mapping to fill values according to passed in colors.
Example based on defaults:
`util.svg.black // outputs a classname with {fill: '#000'}`
#### Z
**Requires z**
Mapping to z-index values according to passed in z map.
Example based on defaults:
`util.z.z1 // outputs a classname with {z-index: '1'}`
z-index is a special case because beside the private API here provided you should also apply your own pattern on top with what makes sense to you:
```
sullivan.myZ = {
nav: sullivan.z.z5,
modal: sullivan.z9
// etc...
}
```
#### Text
**Requires textSizes and colors**
Mapping to color, size and weights values according to passed in maps and a set of utils
Example color based on defaults:
`util.text.black // outputs a classname with {color: '#000'}`
Example size based on defaults:
`util.text.small // outputs a classname with {font-size: '12px'}`
Example line-height based on defaults:
`util.text.loose // outputs a classname with {line-height: 1.2}`
Example weight:
`util.text.light // outputs a classname with {font-weight: '300'}`
##### text.truncate
Outputs:
```
{
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
```
#### Flex
Mapping around the flex syntax (which can be a bit verbosed), also a small set of quick patterns.
Properties:
- `align`: alignItems
- `alignSelf`: alignSelf
- `justify`: justifyContent
Values:
- `Start`: flex-start
- `End`: flex-end
- `Center`: center
- `Around`: space-around
- `Between`: space-between
With properties and values combined they summon earth's greatest champion (yes, this is a captain planet reference):
`util.flex.alignEnd // outputs a classname with {align-items: 'flex-end'}`
`util.flex.justifyAround // outputs a classname with {justify-content: 'space-around'}`
##### flex.center
Outputs:
```
{
display: 'flex',
align-items: 'center',
justify-content: 'center'
}
```
##### flex.column
Outputs:
```
{
display: 'flex',
flex-direction: 'column'
}
```
If you need to do anything else with flex, you're on your own.
## TODO
- Finish this readme file.
- Truncation text util.
- A helper to generate a "living styleguide" page based on passed in values and used utils.
- Some tests would be nice.
- A website would be cool.
# Contributing
Please do, this is built on top of other amazing open-source projects and belongs to the community.
- Ideas? suggest anything over an Issue or PR!
- Suggestions? Read above!
- bugs? Read above!
- this code smells and you can do better? Yes! You know what to do!
# Special Thanks
This project initially sparked from working on small to big scale React.js related projects and feeling the pains of using CSS in JS, special mention to [Kontor.com](http://kontor.com) for giving me room to introduce and mature some of these concepts, also [@colindresj] (https://github.com/colindresj) and [@dkozma](https://github.com/dkozma) for brainstorming ideas and giving suggestions.
# License (MIT)
Copyright (c) 2016 Adrian le Bas
Includes works from https://github.com/Khan/aphrodite, which is MIT licensed with the following copyright:
Copyright (c) 2016 Khan Academy
Which itself includes work from other libraries...