1.0.39 • Published 6 years ago

styled-components-theme-builder v1.0.39

Weekly downloads
-
License
MIT
Repository
github
Last release
6 years ago

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

propvalue
margin1, 1, 1, 1
padding1, 1, 1, 1
centertrue/false

Buttons

propvalue
color{colorName}true/false
background{colorName}true/false

Block Elements

propvalue
background{colorName}true/false
border{borderName}true/false

Text (h1 -> h6, li, small, p)

propvalue
boldtrue/false
uppercasetrue/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',
    }
  },  
},
1.0.39

6 years ago

1.0.38

6 years ago

1.0.37

6 years ago

1.0.36

6 years ago

1.0.35

6 years ago

1.0.34

6 years ago

1.0.33

6 years ago

1.0.32

6 years ago

1.0.31

6 years ago

1.0.30

6 years ago

1.0.29

6 years ago

1.0.28

6 years ago

1.0.27

6 years ago

1.0.26

6 years ago

1.0.25

6 years ago

1.0.24

6 years ago

1.0.23

6 years ago

1.0.22

6 years ago

1.0.21

6 years ago

1.0.20

6 years ago

1.0.19

6 years ago

1.0.18

6 years ago

1.0.17

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.10

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

7 years ago

1.0.5

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago