styled-components-theme-builder v1.0.39
styled-components-theme-builder
Need to build a UI KIT for your project?
Only expose certain props to make sure other developers don't go outside the style guide.
Have a consistent UI KIT you can use across multiple projects within your organisation.
Theme builder uses a centralised state on which a number of elements are generated.
All elements follow common attributes that all follow a responsive vertical rhythm.
Usage
Installation
npm install styled-components-theme-builder --save
Setup
import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components';
import { ThemeBuilder } from 'styled-components-theme-builder';
// Only using Theme Builder
class App extends Component {
render() {
return (
<ThemeBuilder theme={this.props.theme}>{this.props.children}</ThemeBuilder>
);
}
}
// Using your own Styled-Components AND Theme Builder
class App extends Component {
render() {
return (
<ThemeProvider theme={this.props.theme}>
<ThemeBuilder theme={this.props.theme}>{this.props.children}</ThemeBuilder>
</ThemeProvider>
);
}
}
Exposing a button, for example, in your own UI kit
utils.js
const mergePropsWithAvailableProps = (availableProps, givenProps) => {
let props = { };
Object.keys(availableProps).forEach(key => {
if (typeof givenProps[key] !== 'undefined') {
if (availableProps[key] !== null) {
props[availableProps[key]] = givenProps[key];
} else {
props[key] = givenProps[key];
}
}
})
return props;
}
module.exports = {
mergePropsWithAvailableProps
}
props.js
const Common = {
margin: null,
padding: null,
block: null,
};
const Background = {
primary: 'backgroundPrimary',
warning: 'backgroundWarning',
danger: 'backgroundDanger',
success: 'backgroundSuccess',
};
module.exports = {
Common,
Background,
}
events.js
const Events = {
mouse: {
onClick: null,
onContextMenu: null,
onDoubleClick: null,
onDrag: null,
onDragEnd: null,
onDragEnter: null,
onDragExit: null,
onDragLeave: null,
onDragOver: null,
onDragStart: null,
onDrop: null,
onMouseDown: null,
onMouseEnter: null,
onMouseLeave: null,
onMouseMove: null,
onMouseOut: null,
onMouseOver: null,
onMouseUp: null,
},
touch: {
onTouchCancel: null,
onTouchEnd: null,
onTouchMove: null,
onTouchStart: null,
},
};
module.exports = {
Events,
}
available.js
import { Common, Background } from './props';
import { Events } from './events';
const button = Object.assign({}, Common, Background, Events.mouse, Events.touch);
module.exports = {
button,
}
button.js
import React, { Component } from 'react';
import { buildElement } from 'styled-components-theme-builder';
import { mergePropsWithAvailableProps } from '../../utils';
import { button as AvailableProps } from '../available';
const ButtonElement = buildElement('button');
class Button extends Component {
render() {
return (
<ButtonElement {...mergePropsWithAvailableProps(AvailableProps, this.props)}>{this.props.children}</ButtonElement>
);
}
}
export default Button;
index.js
// usage
import { Button } from 'your/ui/kit';
...
<Button primary margin={[0, 1, 1, 0]} onClick={() => console.log('clicked')}>Continue</Button>
Element Props (WIP)
All Elements
prop | value |
---|---|
margin | 1, 1, 1, 1 |
padding | 1, 1, 1, 1 |
center | true/false |
Buttons
prop | value |
---|---|
color{colorName} | true/false |
background{colorName} | true/false |
Block Elements
prop | value |
---|---|
background{colorName} | true/false |
border{borderName} | true/false |
Text (h1 -> h6, li, small, p)
prop | value |
---|---|
bold | true/false |
uppercase | true/false |
color{colorName} | true/false |
Theme State
Container width
{
containerMaxWidth: 1280, // container max width (will center once greater 1280)
}
Spacing
{
spacing: 16, // default spacing (px based unit)
}
Typography
Typography is based on vertical rhythm (vertical rhythm).
{
typography: {
fontSizeAdjust: 0.95, // helper to adjust overall font size
base: {
fontSize: 12,
lineHeight: 1.5,
},
h1: {
fontSize: 28,
lineHeight: 1.2,
marginBottom: 32,
paddingTop: 0,
},
h2: {
fontSize: 24,
lineHeight: 1.25,
marginBottom: 12,
paddingTop: 6,
},
h3: {
fontSize: 21,
lineHeight: 1.25,
marginBottom: 6,
paddingTop: 12,
},
h4: {
fontSize: 18,
lineHeight: 1.33333,
marginBottom: 8,
paddingTop: 12,
},
h5: {
fontSize: 16,
lineHeight: 1.5,
marginBottom: 9,
paddingTop: 12,
},
h6: {
fontSize: 14,
lineHeight: 1.5,
marginBottom: 3,
paddingTop: 9,
},
p: {
fontSize: 12,
marginBottom: 12,
paddingTop: 0,
},
small: {
fontSize: 10,
marginBottom: 0,
paddingTop: 0,
},
button: {
fontSize: 12,
},
}
}
All font sizes are responsive and use (responsive vertical rhythm), a basic algorithm, but you control by using the below params (minViewportWidth and maxViewportWidth).
Current algorithm used:
fontSize = (fontSizeAdjust * (16 + (min(max(minViewportWidth, windowWidth), maxViewportWidth) / 100))
Theme builder will update the html tag with the font size upon window resize.
Controlling how the font will adjust on window resize:
{
typography: {
minViewportWidth: 480, // stop reducing font at 480px
maxViewportWidth: 1000, // stop increasing font at 1000px
}
}
Specify your fonts
{
typography: {
fonts: {
heading: '\'Open Sans\', sans-serif;',
body: '\'Source Sans Pro\', sans-serif;',
},
fontWeights: {
heading: {
normal: 400,
bold: 700,
},
body: {
normal: 400,
bold: 700,
},
},
base: {
font: 'body',
},
h1: {
font: 'heading',
},
h2: {
font: 'heading',
},
h3: {
font: 'heading',
},
h4: {
font: 'heading',
},
h5: {
font: 'heading',
},
h6: {
font: 'heading',
},
p: {
// automatically uses same font as base if not specified
},
button: {
// automatically uses same font as base if not specified
},
small: {
// automatically uses same font as base if not specified
},
},
}
Final typography state together:
typography: {
fonts: {
heading: '\'Open Sans\', sans-serif;',
body: '\'Source Sans Pro\', sans-serif;',
},
fontWeights: {
heading: {
normal: 400,
bold: 700,
},
body: {
normal: 400,
bold: 700,
},
},
minViewportWidth: 480,
maxViewportWidth: 1000,
fontSizeAdjust: 0.95,
base: {
font: 'body',
fontSize: 12,
lineHeight: 1.5,
},
h1: {
font: 'heading',
fontSize: 28,
lineHeight: 1.2,
marginBottom: 32,
paddingTop: 0,
},
h2: {
font: 'heading',
fontSize: 24,
lineHeight: 1.25,
marginBottom: 12,
paddingTop: 6,
},
h3: {
font: 'heading',
fontSize: 21,
lineHeight: 1.25,
marginBottom: 6,
paddingTop: 12,
},
h4: {
font: 'heading',
fontSize: 18,
lineHeight: 1.33333,
marginBottom: 8,
paddingTop: 12,
},
h5: {
font: 'heading',
fontSize: 16,
lineHeight: 1.5,
marginBottom: 9,
paddingTop: 12,
},
h6: {
font: 'heading',
fontSize: 14,
lineHeight: 1.5,
marginBottom: 3,
paddingTop: 9,
},
p: {
fontSize: 12,
marginBottom: 12,
paddingTop: 0,
},
small: {
fontSize: 10,
marginBottom: 0,
paddingTop: 0,
},
button: {
fontSize: 12,
},
},
Colors:
State
colors: {
base: '#081e2c',
primary: '#2c97de',
secondary: '#f2c500',
success: '#1fce6d',
danger: '#e94b35',
...
},
Usage
<Element colorPrimary>Text</Element>
Borders:
State
borders: {
bottom: {
width: [ 0, 0, 1, 0 ],
type: 'solid',
color: 'base',
},
...
},
Usage
<Element borderBottom>Text</Element>
Button default colors
typography: {
button: {
fontSize: 12,
defaultColor: 'white',
defaultBackground: 'base',
hoverOpacity: 0.85,
activeOpacity: 0.7,
},
},
Typography default color
typography: {
base: {
color: 'base',
},
},
Final State Example
theme: {
containerMaxWidth: 1280,
spacing: 16,
typography: {
fonts: {
heading: '\'Open Sans\', sans-serif;',
body: '\'Source Sans Pro\', sans-serif;',
},
fontWeights: {
heading: {
normal: 400,
bold: 700,
},
body: {
normal: 400,
bold: 700,
},
},
minViewportWidth: 480,
maxViewportWidth: 1000,
fontSizeAdjust: 0.95,
base: {
font: 'body',
fontSize: 12,
lineHeight: 1.5,
color: 'base',
},
h1: {
font: 'heading',
fontSize: 28,
lineHeight: 1.2,
marginBottom: 32,
paddingTop: 0,
},
h2: {
font: 'heading',
fontSize: 24,
lineHeight: 1.25,
marginBottom: 12,
paddingTop: 6,
},
h3: {
font: 'heading',
fontSize: 21,
lineHeight: 1.25,
marginBottom: 6,
paddingTop: 12,
},
h4: {
font: 'heading',
fontSize: 18,
lineHeight: 1.33333,
marginBottom: 8,
paddingTop: 12,
},
h5: {
font: 'heading',
fontSize: 16,
lineHeight: 1.5,
marginBottom: 9,
paddingTop: 12,
},
h6: {
font: 'heading',
fontSize: 14,
lineHeight: 1.5,
marginBottom: 3,
paddingTop: 9,
},
p: {
fontSize: 12,
marginBottom: 12,
paddingTop: 0,
},
small: {
fontSize: 10,
marginBottom: 0,
paddingTop: 0,
},
button: {
fontSize: 12,
defaultColor: 'white',
defaultBackground: 'base',
hoverOpacity: 0.85,
activeOpacity: 0.7,
},
},
colors: {
white: '#ffffff',
base: '#081e2c',
primary: '#2c97de',
secondary: '#f2c500',
success: '#1fce6d',
danger: '#e94b35',
},
borders: {
bottom: {
width: [ 0, 0, 1, 0 ],
type: 'solid',
color: 'grey',
}
},
},
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago