├── .gitignore ├── .travis.yml ├── contributing.md ├── demo └── src │ └── index.js ├── example.gif ├── license ├── logo.png ├── nwb.config.js ├── package.json ├── readme.md └── src ├── components ├── box.js ├── flex.js └── index.js ├── context.js ├── index.js ├── provider.js └── styled.js /.gitignore: -------------------------------------------------------------------------------- 1 | /coverage 2 | /demo/dist 3 | /es 4 | /lib 5 | /node_modules 6 | npm-debug.log* 7 | package-lock.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - 6 6 | 7 | before_install: 8 | - npm install codecov.io coveralls 9 | 10 | after_success: 11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js 12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js 13 | 14 | branches: 15 | only: 16 | - master 17 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | 3 | [Node.js](http://nodejs.org/) >= v4 must be installed. 4 | 5 | ## Installation 6 | 7 | - Running `npm install` in the components's root directory will install everything you need for development. 8 | 9 | ## Demo Development Server 10 | 11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading. 12 | 13 | ## Running Tests 14 | 15 | - `npm test` will run the tests once. 16 | 17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`. 18 | 19 | - `npm run test:watch` will run the tests on every change. 20 | 21 | ## Building 22 | 23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app. 24 | 25 | - `npm run clean` will delete built resources. 26 | -------------------------------------------------------------------------------- /demo/src/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { render } from 'react-dom' 3 | import inject from 'insert-css' 4 | 5 | import { 6 | StyleProvider, 7 | createRenderer, 8 | Flex, 9 | Box 10 | } from '../../src' 11 | 12 | const renderer = createRenderer() 13 | 14 | renderer.renderStatic( 15 | { 16 | margin: 0 17 | }, 18 | 'body, html' 19 | ) 20 | 21 | renderer.renderStatic( 22 | { 23 | boxSizing: 'border-box' 24 | }, 25 | '*' 26 | ) 27 | 28 | const CenteredBox = ({ children, ...props }) => ( 29 | 35 | {children} 36 | 37 | ) 38 | 39 | const fontFamily = ` 40 | -apple-system, 41 | BlinkMacSystemFont, 42 | Segoe UI, 43 | Helvetica Neue, 44 | sans-serif 45 | ` 46 | 47 | const App = () => ( 48 | 53 | 1 54 | 2 55 | 56 | ) 57 | 58 | class Demo extends Component { 59 | render () { 60 | return ( 61 | 62 | 63 | 64 | ) 65 | } 66 | } 67 | 68 | render(, document.querySelector('#demo')) 69 | inject(renderer.renderToString()) 70 | -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/queckezz/veel/dfb6dc825c7f722dd062c457db4a61006aa3672d/example.gif -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2017 Fabian Eichenberger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/queckezz/veel/dfb6dc825c7f722dd062c457db4a61006aa3672d/logo.png -------------------------------------------------------------------------------- /nwb.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | type: 'react-component', 3 | npm: { 4 | esModules: true, 5 | umd: false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "veel", 3 | "version": "1.0.0-beta.3", 4 | "description": "Base react styling components using fela with a design system", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "files": [ 8 | "css", 9 | "es", 10 | "lib", 11 | "umd" 12 | ], 13 | "scripts": { 14 | "build": "nwb build-react-component", 15 | "clean": "nwb clean-module && nwb clean-demo", 16 | "start": "nwb serve-react-demo", 17 | "test": "nwb test-react", 18 | "test:coverage": "nwb test-react --coverage", 19 | "test:watch": "nwb test-react --server" 20 | }, 21 | "dependencies": { 22 | "@f/is-function": "^1.1.1", 23 | "fela": "^5.0.2", 24 | "prop-types": "^15.5.10", 25 | "styled-system": "^1.0.0-7" 26 | }, 27 | "peerDependencies": { 28 | "react": "15.x" 29 | }, 30 | "devDependencies": { 31 | "insert-css": "^2.0.0", 32 | "nwb": "0.17.x", 33 | "react": "^15.6.1", 34 | "react-dom": "^15.6.1" 35 | }, 36 | "author": "queckezz ", 37 | "license": "MIT", 38 | "repository": "queckezz/veel", 39 | "keywords": [ 40 | "react-component", 41 | "design system", 42 | "fela", 43 | "styling", 44 | "css-in-js", 45 | "ui", 46 | "react" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | ![logo](./logo.png) 3 | 4 | # veel [![NPM version][version-image]][version-url] [![Js Standard Style][standard-image]][standard-url] 5 | 6 | :package: Base React styling components using [`Fela`](http://fela.js.org) with a [design system](https://github.com/jxnblk/styled-system) 7 | 8 | * **Low-Level** - Exposes only a few components which can be used as a base layer to build your UI components upon 9 | * **Consistency** - Uses `styled-system` which encourages consistency of spacing, typography and color 10 | * **Universal** - By using fela it's really easy to prerender your styles on the server or anywhere 11 | 12 | ``` 13 | npm install veel 14 | ``` 15 | 16 | ```js 17 | const Badge = (props) => ( 18 | 25 | ) 26 | ``` 27 | 28 | ## Contents 29 | 30 | * [Example](#example) 31 | * [Usage](#usage) 32 | * [Components](#components) 33 | + [Box](#box) 34 | + [Flex](#flex) 35 | * [Plugins](#plugins) 36 | + [Recommend plugins](#recommend-plugins) 37 | * [Author](#author) 38 | 39 | ## Example 40 | 41 | The following renders a responsive row with two equally divided divs collapsing on mobile. 42 | 43 | ![Example](./example.gif) 44 | 45 | ```js 46 | const CenteredBox = props => ( 47 | 53 | ) 54 | 55 | const App = () => ( 56 | 61 | 1 62 | 2 63 | 64 | ) 65 | ``` 66 | 67 | ## Usage 68 | 69 | 1. Create a [`fela`](http://fela.js.org/docs/api/fela-native/createRenderer.html) renderer. 70 | 71 | ```js 72 | import { createRenderer } from 'veel' 73 | const renderer = createRenderer() 74 | ``` 75 | 76 | 2. Wrap your application in a `StyleProvider` so that each `veel` component has access to the renderer and the optional theme. 77 | 78 | ```js 79 | import { StyleProvider, Box } from 'veel' 80 | 81 | class App extends React.Component { 82 | render() { 83 | return ( 84 | 85 | Application 86 | 87 | ) 88 | } 89 | } 90 | ``` 91 | 92 | 3. Now you need some way of injecting the generated css into the html. There are many ways to do it, each with their positive and negative aspects. 93 | 94 | **Injecting the css dynamically** 95 | ```js 96 | require('inject-css')(renderer.renderToString()) 97 | ``` 98 | 99 | **Render to a sheet list ([Next.js](http://ghub.io/next) example)** 100 | 101 | This makes the most sense when you create the document skeleton with JSX. 102 | 103 | ```js 104 | import Document, { Head } from 'next/document' 105 | 106 | class CustomDocument extends Document { 107 | static getInitialProps ({ renderPage }) { 108 | const page = renderPage() 109 | const sheets = renderer.renderToSheetList() 110 | renderer.clear() 111 | return { ...page, sheets } 112 | } 113 | 114 | render () { 115 | const sheets = this.props.sheets 116 | return ( 117 | 118 | {sheets.map(({ type, media, css }) => ( 119 | 120 | ))} 121 | 122 | 123 | ... 124 | ) 125 | } 126 | } 127 | ``` 128 | 129 | 4. You're done! 130 | 131 | ## Components 132 | 133 | ### Box 134 | 135 | ```js 136 | Hello Veel! 137 | ``` 138 | 139 | The core layout component. Take a look at [`styled-system`](https://github.com/jxnblk/styled-system/blob/master/README.md) for documentation on `` `props`. 140 | 141 | #### `Box.is` 142 | 143 | By default a `` component will render out to a `div`. You can change the tag by providing an `is` property. 144 | 145 | ### Flex 146 | 147 | ```js 148 | 149 | ``` 150 | 151 | [View the example](./demo/src/index.js) on how to use it. 152 | 153 | #### `Flex.center` 154 | 155 | Sets both `alignItems` and `justifyContent` to `center`. 156 | 157 | #### `Flex.wrap` 158 | 159 | Sets `flexWrap` to `wrap`. 160 | 161 | #### `Flex.column` 162 | 163 | Sets `flexDirection` to `column`. 164 | 165 | #### `Flex.justify` 166 | 167 | CSS `justifyContent` property. 168 | 169 | #### `Flex.align` 170 | 171 | CSS `alignItem` property. 172 | 173 | #### `Flex.order` 174 | 175 | CSS `order` property. 176 | 177 | ## Plugins 178 | 179 | By using fela you have a wide variety of plugins available. Check out the [plugin list](http://fela.js.org/docs/introduction/Ecosystem.html#plugins) 180 | 181 | ### Recommend plugins 182 | 183 | * [**`fela-plugin-embedded`**](https://github.com/rofrischmann/fela/tree/master/packages/fela-plugin-embedded) - Inline keyframes and font-faces 184 | 185 | ```js 186 | 192 | 193 | // -> { animationName: 'k1' } 194 | ``` 195 | 196 | ## Author 197 | 198 | **veel** © [Fabian Eichenberger](https://github.com/queckezz), Released under the [MIT](./license) License.
199 | Authored and maintained by Fabian Eichenberger with help from contributors ([list](https://github.com/queckezz/veel/contributors)). 200 | 201 | > GitHub [@queckezz](https://github.com/queckezz) · Twitter [@queckezz](https://twitter.com/queckezz) 202 | 203 | [version-image]: https://img.shields.io/npm/v/veel.svg?style=flat-square 204 | [version-url]: https://npmjs.org/package/veel 205 | 206 | [standard-image]: https://img.shields.io/badge/code-standard-brightgreen.svg?style=flat-square 207 | [standard-url]: https://github.com/feross/standard 208 | -------------------------------------------------------------------------------- /src/components/box.js: -------------------------------------------------------------------------------- 1 | import styled from '../styled' 2 | 3 | const Box = styled('div') 4 | 5 | export default Box 6 | -------------------------------------------------------------------------------- /src/components/flex.js: -------------------------------------------------------------------------------- 1 | import { oneOf, bool, number } from 'prop-types' 2 | import styled from '../styled' 3 | import React from 'react' 4 | 5 | const Flex = styled( 6 | ( 7 | theme, 8 | { 9 | justify, 10 | column, 11 | center, 12 | order, 13 | align, 14 | wrap, 15 | ...props 16 | } 17 | ) => ({ 18 | props, 19 | css: { 20 | display: 'flex', 21 | alignItems: align, 22 | justifyContent: justify, 23 | flexWrap: wrap ? 'wrap' : null, 24 | flexDirection: column ? 'column' : null, 25 | order, 26 | 27 | ...(center 28 | ? { 29 | alignItems: 'center', 30 | justifyContent: 'center' 31 | } 32 | : {}) 33 | } 34 | }) 35 | ) 36 | 37 | Flex.PropTypes = { 38 | align: oneOf([ 39 | 'flex-start', 40 | 'flex-end', 41 | 'baseline', 42 | 'center', 43 | 'stretch' 44 | ]), 45 | 46 | justify: oneOf([ 47 | 'flex-start', 48 | 'flex-end', 49 | 'center', 50 | 'space-between', 51 | 'space-around' 52 | ]), 53 | 54 | order: number, 55 | column: bool, 56 | wrap: bool 57 | } 58 | 59 | export default Flex 60 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Flex } from './flex' 2 | export { default as Box } from './box' -------------------------------------------------------------------------------- /src/context.js: -------------------------------------------------------------------------------- 1 | import { shape, object, array, number } from 'prop-types' 2 | 3 | const ns = '__VEEL__' 4 | 5 | const types = { 6 | [ns]: shape({ 7 | renderer: object.isRequired, 8 | 9 | config: shape({ 10 | space: array, 11 | fontSizes: array, 12 | breakpoints: array, 13 | colors: object 14 | }) 15 | }) 16 | } 17 | 18 | export default { types, ns } 19 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as StyleProvider } from './provider' 2 | export { createRenderer } from 'fela' 3 | export * from './components' 4 | -------------------------------------------------------------------------------- /src/provider.js: -------------------------------------------------------------------------------- 1 | import context from './context' 2 | import { Component, Children } from 'react' 3 | 4 | class StyleProvider extends Component { 5 | getChildContext() { 6 | return { 7 | [context.ns]: this.props 8 | } 9 | } 10 | 11 | render() { 12 | const children = Children.only(this.props.children) 13 | return children 14 | } 15 | } 16 | 17 | StyleProvider.childContextTypes = context.types 18 | 19 | export default StyleProvider 20 | -------------------------------------------------------------------------------- /src/styled.js: -------------------------------------------------------------------------------- 1 | import context from './context' 2 | import isFunction from '@f/is-function' 3 | import React from 'react' 4 | 5 | import { 6 | removeProps, 7 | fontSize, 8 | space, 9 | width, 10 | color 11 | } from 'styled-system' 12 | 13 | import { combineRules } from 'fela' 14 | 15 | const styled = (BaseComponent = 'div', createComponent) => { 16 | if (isFunction(BaseComponent)) { 17 | createComponent = BaseComponent 18 | BaseComponent = 'div' 19 | } 20 | 21 | const VeelComponent = ({ is, css, ...props }, ctx) => { 22 | const { renderer, theme } = ctx[context.ns] 23 | 24 | const style = createComponent 25 | ? createComponent(theme, props) 26 | : { props } 27 | 28 | const cn = renderer.renderRule( 29 | combineRules(fontSize, space, width, color, () => ({ 30 | ...style.css, 31 | ...css 32 | })), 33 | props 34 | ) 35 | 36 | const Component = is || BaseComponent 37 | 38 | return ( 39 | 43 | ) 44 | } 45 | 46 | VeelComponent.contextTypes = context.types 47 | return VeelComponent 48 | } 49 | 50 | export default styled 51 | --------------------------------------------------------------------------------