Last active
June 19, 2017 22:54
-
-
Save souporserious/a352fe9c4ae18518f1d38099201d673a to your computer and use it in GitHub Desktop.
Compute design system styles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import deepExtend from 'deep-extend' | |
import colorStyles from './color-styles' | |
import fluidSize from './fluid-size' | |
import { fontBase, lineHeight, spacing, verticalRhythm } from '../design-system' | |
function valuesDefined(...values) { | |
return values.some(value => typeof value !== 'undefined') | |
} | |
function parseSides(...sides) { | |
return sides.reduce((acc, side) => { | |
if (typeof side === 'string') { | |
return side | |
} | |
if (side !== null && typeof side !== 'undefined') { | |
return side * spacing | |
} | |
return acc | |
}) | |
} | |
function parseValues(...values) { | |
return values.reduce((acc, value) => { | |
return value !== null && typeof value !== 'undefined' ? value : acc | |
}) | |
} | |
// TODO: | |
// we should be able to add to an array or something and deep merge at the end | |
// probably split out into smaller functions | |
function computeDesignSystem({ | |
// size | |
width, | |
height, | |
// spacing | |
top, | |
right, | |
bottom, | |
left, | |
padding, | |
paddingHorizontal, | |
paddingVertical, | |
paddingTop, | |
paddingRight, | |
paddingBottom, | |
paddingLeft, | |
margin, | |
marginHorizontal, | |
marginVertical, | |
marginTop, | |
marginRight, | |
marginBottom, | |
marginLeft, | |
// border | |
borderWidth, | |
borderTopWidth, | |
borderRightWidth, | |
borderBottomWidth, | |
borderLeftWidth, | |
dividerHorizontalWidth, | |
dividerVerticalWidth, | |
// color | |
fill, | |
stroke, | |
borderColor, | |
borderTopColor, | |
borderRightColor, | |
borderBottomColor, | |
borderLeftColor, | |
dividerHorizontalColor, | |
dividerVerticalColor, | |
backgroundColor, | |
color, | |
// radius | |
radius, | |
radiusTop, | |
radiusRight, | |
radiusBottom, | |
radiusLeft, | |
// type | |
fontSize, | |
uppercase, | |
// misc | |
shadow, | |
opacity, | |
...props | |
}) { | |
///////////////////////////////////////////////// | |
// SPACE | |
///////////////////////////////////////////////// | |
let styles = { | |
paddingTop: parseSides(padding, paddingVertical, paddingTop), | |
paddingRight: parseSides(padding, paddingHorizontal, paddingRight), | |
paddingBottom: parseSides(padding, paddingVertical, paddingBottom), | |
paddingLeft: parseSides(padding, paddingHorizontal, paddingLeft), | |
marginTop: parseSides(margin, marginVertical, marginTop), | |
marginRight: parseSides(margin, marginHorizontal, marginRight), | |
marginBottom: parseSides(margin, marginVertical, marginBottom), | |
marginLeft: parseSides(margin, marginHorizontal, marginLeft), | |
} | |
///////////////////////////////////////////////// | |
// POSITION | |
////////////////////////////////// | |
if (top) { | |
styles.top = parseSides(top) | |
} | |
if (right) { | |
styles.right = parseSides(right) | |
} | |
if (bottom) { | |
styles.bottom = parseSides(bottom) | |
} | |
if (left) { | |
styles.left = parseSides(left) | |
} | |
///////////////////////////////////////////////// | |
// SIZE | |
///////////////////////////////////////////////// | |
if (width) { | |
if (width <= 1) { | |
styles.width = width * 100 + '%' | |
} else { | |
styles.width = typeof width === 'string' ? width : width * spacing | |
} | |
} | |
if (height) { | |
styles.height = typeof height === 'string' ? height : height * spacing | |
} | |
///////////////////////////////////////////////// | |
// COLOR | |
///////////////////////////////////////////////// | |
const colorProps = { | |
fill, | |
stroke, | |
borderColor, | |
borderTopColor, | |
borderRightColor, | |
borderBottomColor, | |
borderLeftColor, | |
backgroundColor, | |
color, | |
} | |
Object.keys(colorProps).forEach(key => { | |
const colorProp = colorProps[key] | |
if (colorProp) { | |
deepExtend(styles, colorStyles(colorProp, { key })) | |
} | |
}) | |
///////////////////////////////////////////////// | |
// FONT SIZE | |
///////////////////////////////////////////////// | |
if (typeof fontSize !== 'undefined') { | |
if (isNaN(fontSize)) { | |
styles.fontSize = fontSize | |
} else { | |
const vr = verticalRhythm(fontSize) | |
styles.fontSize = vr.fontSize | |
styles.lineHeight = vr.lineHeight | |
} | |
} | |
if (uppercase) { | |
styles.textTransform = 'uppercase' | |
styles.letterSpacing = '0.025em' | |
} | |
///////////////////////////////////////////////// | |
// RADIUS | |
///////////////////////////////////////////////// | |
if (radius) { | |
if (radius === 'circle') { | |
styles.borderRadius = '100%' | |
} else { | |
styles.borderTopLeftRadius = radius | |
styles.borderTopRightRadius = radius | |
styles.borderBottomRightRadius = radius | |
styles.borderBottomLeftRadius = radius | |
} | |
} | |
if (radiusTop) { | |
styles.borderTopLeftRadius = radiusTop | |
styles.borderTopRightRadius = radiusTop | |
} | |
if (radiusRight) { | |
styles.borderTopRightRadius = radiusRight | |
styles.borderBottomRightRadius = radiusRight | |
} | |
if (radiusBottom) { | |
styles.borderBottomRightRadius = radiusBottom | |
styles.borderBottomLeftRadius = radiusBottom | |
} | |
if (radiusLeft) { | |
styles.borderTopLeftRadius = radiusLeft | |
styles.borderBottomLeftRadius = radiusLeft | |
} | |
///////////////////////////////////////////////// | |
// BORDER | |
///////////////////////////////////////////////// | |
styles.borderTopWidth = parseValues(borderWidth, borderTopWidth) | |
styles.borderRightWidth = parseValues(borderWidth, borderRightWidth) | |
styles.borderBottomWidth = parseValues(borderWidth, borderBottomWidth) | |
styles.borderLeftWidth = parseValues(borderWidth, borderLeftWidth) | |
if (dividerHorizontalColor) { | |
const size = dividerHorizontalWidth || 1 | |
const color = dividerHorizontalColor | |
styles['& > * + *'] = { | |
marginLeft: `-${size}px !important`, | |
borderLeftStyle: 'solid !important', | |
borderLeftWidth: `${size}px !important`, | |
borderLeftColor: `${color} !important`, | |
} | |
} | |
if (dividerVerticalColor) { | |
const prevDividerStyles = styles['& > * + *'] || {} | |
const size = dividerVerticalWidth || 1 | |
const color = dividerVerticalColor | |
styles['& > * + *'] = { | |
...prevDividerStyles, | |
marginTop: `-${size}px !important`, | |
borderTopStyle: 'solid !important', | |
borderTopWidth: `${size}px !important`, | |
borderTopColor: `${color} !important`, | |
} | |
} | |
if (shadow === true) { | |
styles.boxShadow = '0px 0px 4px 2px rgba(220,220,220,0.5)' | |
} | |
if (typeof opacity !== 'undefined') { | |
styles.opacity = opacity | |
} | |
// attempt to fix vertical rhythm | |
if (styles.paddingTop > 0 && styles.borderTopWidth > 0) { | |
styles.paddingTop -= styles.borderTopWidth | |
} | |
if (styles.paddingBottom > 0 && styles.borderBottomWidth > 0) { | |
styles.paddingBottom -= styles.borderBottomWidth | |
} | |
return { | |
styles, | |
props, | |
} | |
} | |
const styleReset = { | |
appearance: 'none', | |
font: 'inherit', | |
fontFamily: | |
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', | |
lineHeight: '24px', | |
textAlign: 'inherit', | |
textDecoration: 'none', | |
listStyle: 'none', | |
position: 'relative', | |
boxSizing: 'border-box', | |
minHeight: 0, | |
minWidth: 0, | |
margin: 0, | |
padding: 0, | |
outline: 0, | |
borderStyle: 'solid', | |
borderWidth: 0, | |
borderColor: 'transparent', | |
backgroundColor: 'transparent', | |
color: 'inherit', | |
// use focus-ring polyfill to provide keyboard only outlines | |
// https://github.com/WICG/focus-ring | |
'&.focus-ring:after': { | |
content: '""', | |
position: 'absolute', | |
top: -3, | |
right: -3, | |
bottom: -3, | |
left: -3, | |
border: '3px solid #007eff', | |
zIndex: 9999, | |
}, | |
} | |
export { computeDesignSystem as default, styleReset } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment