diff --git a/.eslintrc b/.eslintrc index 72da4130..0806faac 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,10 @@ { "parser": "babel-eslint", "extends": [ - "standard", - "standard-react" + "airbnb" + ], + "plugins": [ + "no-unused-vars-rest" ], "env": { "browser": true, @@ -15,8 +17,25 @@ "__COVERAGE__": true, "__BASENAME__": true }, + "settings": { + "import/resolver": "webpack" + }, "rules": { - "jsx-quotes": [2, "prefer-double"], - "indent": [2, 2] + "semi": [2, "never"], + "comma-dangle": 0, + "max-len": 0, + "no-shadow": 0, + "arrow-body-style": 0, + "arrow-parens": 0, + "global-require": 0, + "no-unused-expressions": 0, + "no-confusing-arrow": 0, + "no-unused-vars": 0, + "import/no-dynamic-require": 0, + "import/no-extraneous-dependencies": 0, + "import/prefer-default-export": 0, + "react/require-default-props": 0, + "react/jsx-filename-extension": ["error", {"extensions": [".js", ".jsx"]}], + "no-unused-vars-rest/no-unused-vars": ["error", {"ignoreDestructuredVarsWithRest": true}] } } diff --git a/.storybook/config.js b/.storybook/config.js index 00afc06d..bce3ef59 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -6,11 +6,11 @@ import theme from 'components/themes/default' const req = require.context('components', true, /.stories.js$/) -function loadStories () { - req.keys().forEach((filename) => req(filename)) +function loadStories() { + req.keys().forEach(filename => req(filename)) } -addDecorator((story) => ( +addDecorator(story => ( {story()} )) diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index b8db8704..311784ec 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -1,7 +1,9 @@ -var baseConfig = require('../webpack.config') +const baseConfig = require('../webpack.config') -module.exports = function (storybookBaseConfig, configType) { - storybookBaseConfig.resolve = baseConfig.resolve - storybookBaseConfig.module.loaders.push(...baseConfig.module.loaders) - return storybookBaseConfig -} +module.exports = storybookBaseConfig => + Object.assign({}, storybookBaseConfig, { + resolve: baseConfig.resolve, + module: Object.assign({}, storybookBaseConfig.module, { + loaders: storybookBaseConfig.module.loaders.concat(baseConfig.module.loaders) + }) + }) diff --git a/package.json b/package.json index 57a3a354..6b99d176 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "jest", "coverage": "npm test -- --coverage", "postcoverage": "opn coverage/lcov-report/index.html", - "lint": "eslint src src-clean .storybook webpack.config.js server.js", + "lint": "eslint src src-clean .storybook", "storybook": "start-storybook -p 9001 -c .storybook", "build:clean": "del \"dist/!(.git*|Procfile)**\"", "build:copy": "copyfiles -u 1 public/* public/**/* dist", @@ -41,12 +41,13 @@ "cross-env": "^3.1.4", "del-cli": "^0.2.1", "enzyme": "^2.7.0", - "eslint": "^3.12.2", - "eslint-config-standard": "^6.2.1", - "eslint-config-standard-react": "^4.2.0", - "eslint-plugin-promise": "^3.4.0", - "eslint-plugin-react": "^6.8.0", - "eslint-plugin-standard": "^2.0.1", + "eslint": "^3.13.1", + "eslint-config-airbnb": "^14.0.0", + "eslint-import-resolver-webpack": "^0.8.1", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^3.0.2", + "eslint-plugin-no-unused-vars-rest": "^1.0.4", + "eslint-plugin-react": "^6.9.0", "file-loader": "^0.9.0", "html-webpack-plugin": "^2.26.0", "jest-cli": "^18.1.0", diff --git a/server.js b/server.js index f700a0f7..b171ee2a 100644 --- a/server.js +++ b/server.js @@ -1,9 +1,10 @@ -var webpack = require('webpack') -var WebpackDevServer = require('webpack-dev-server') -var config = require('./webpack.config') +/* eslint-disable */ +const webpack = require('webpack') +const WebpackDevServer = require('webpack-dev-server') +const config = require('./webpack.config') -var ip = process.env.IP || '0.0.0.0' -var port = process.env.PORT || 3000 +const ip = process.env.IP || '0.0.0.0' +const port = process.env.PORT || 3000 new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, @@ -12,10 +13,10 @@ new WebpackDevServer(webpack(config), { stats: false, historyApiFallback: true, contentBase: 'public' -}).listen(port, ip, function (err, result) { +}).listen(port, ip, (err) => { if (err) { return console.log(err) } - console.log('Listening at http://' + ip + ':' + port) + console.log(`Listening at http://${ip}:${port}`) }) diff --git a/src-clean/components/App.js b/src-clean/components/App.js index bd164fce..cfcaeeec 100644 --- a/src-clean/components/App.js +++ b/src-clean/components/App.js @@ -16,7 +16,10 @@ const App = ({ children }) => { } App.propTypes = { - children: PropTypes.any + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) } export default App diff --git a/src-clean/components/templates/PageTemplate/index.js b/src-clean/components/templates/PageTemplate/index.js index 928d2bf0..10101a22 100644 --- a/src-clean/components/templates/PageTemplate/index.js +++ b/src-clean/components/templates/PageTemplate/index.js @@ -1,4 +1,4 @@ -import React, { PropTypes } from 'react' +import React from 'react' import styled from 'styled-components' const Wrapper = styled.div` @@ -9,14 +9,10 @@ const Wrapper = styled.div` height: 100%; ` -const PageTemplate = ({ children, ...props }) => { +const PageTemplate = (props) => { return ( - {children} + ) } -PageTemplate.propTypes = { - children: PropTypes.any.isRequired -} - export default PageTemplate diff --git a/src/components/App.js b/src/components/App.js index b760f274..45c0b511 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -18,7 +18,10 @@ const App = ({ children }) => { } App.propTypes = { - children: PropTypes.any + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) } export default App diff --git a/src/components/atoms/Button/index.js b/src/components/atoms/Button/index.js index 7671885b..becf36a6 100644 --- a/src/components/atoms/Button/index.js +++ b/src/components/atoms/Button/index.js @@ -45,7 +45,7 @@ const styles = css` } ` -const StyledLink = styled(({ disabled, transparent, reverse, color, height, theme, ...props }) => +const StyledLink = styled(({ disabled, transparent, reverse, palette, height, theme, ...props }) => )`${styles}` const Anchor = styled.a`${styles}` diff --git a/src/components/atoms/Heading/index.js b/src/components/atoms/Heading/index.js index 65144c73..b7be2934 100644 --- a/src/components/atoms/Heading/index.js +++ b/src/components/atoms/Heading/index.js @@ -2,7 +2,7 @@ import React, { PropTypes } from 'react' import styled, { css } from 'styled-components' import { font, palette } from 'styled-theme' -export const fontSize = ({ level }) => `${0.75 + 1 * (1 / level)}rem` +export const fontSize = ({ level }) => `${0.75 + (1 * (1 / level))}rem` const styles = css` font-family: ${font('primary')}; @@ -14,9 +14,9 @@ const styles = css` color: ${palette({ grayscale: 0 }, 1)}; ` -const Heading = styled(({ level, children, reverse, palette, theme, ...props }) => { - return React.createElement(`h${level}`, props, children) -})`${styles}` +const Heading = styled(({ level, children, reverse, palette, theme, ...props }) => + React.createElement(`h${level}`, props, children) +)`${styles}` Heading.propTypes = { level: PropTypes.number, diff --git a/src/components/atoms/List/index.js b/src/components/atoms/List/index.js index d1c01209..c3266d20 100644 --- a/src/components/atoms/List/index.js +++ b/src/components/atoms/List/index.js @@ -19,9 +19,12 @@ const List = ({ ordered, children, ...props }) => { List.propTypes = { ordered: PropTypes.bool, - children: PropTypes.any, palette: PropTypes.string, - reverse: PropTypes.bool + reverse: PropTypes.bool, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) } List.defaultProps = { diff --git a/src/components/atoms/LogoImage/index.js b/src/components/atoms/LogoImage/index.js index 1bb154c5..2087741c 100644 --- a/src/components/atoms/LogoImage/index.js +++ b/src/components/atoms/LogoImage/index.js @@ -1,7 +1,8 @@ import React from 'react' +// eslint-disable-next-line import/no-webpack-loader-syntax import logo from 'url!./logo.svg' -const LogoImage = (props) => Logo +const LogoImage = props => Logo export default LogoImage diff --git a/src/components/atoms/TableCell/index.js b/src/components/atoms/TableCell/index.js index 11d104c2..efbe29ec 100644 --- a/src/components/atoms/TableCell/index.js +++ b/src/components/atoms/TableCell/index.js @@ -15,7 +15,10 @@ const TableCell = ({ heading, children, ...props }) => { TableCell.propTypes = { heading: PropTypes.bool, - children: PropTypes.any + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) } export default TableCell diff --git a/src/components/atoms/Tooltip/index.js b/src/components/atoms/Tooltip/index.js index 3d8bf825..c5a8c7c7 100644 --- a/src/components/atoms/Tooltip/index.js +++ b/src/components/atoms/Tooltip/index.js @@ -15,7 +15,7 @@ export const opposite = ({ position }) => opposites[position] export const perpendicular = ({ position }) => position === 'left' || position === 'right' ? 'top' : 'left' -export const perpendicularOpposite = (props) => opposites[perpendicular(props)] +export const perpendicularOpposite = props => opposites[perpendicular(props)] export const perpendicularAxis = ({ position }) => position === 'left' || position === 'right' ? 'Y' : 'X' @@ -62,16 +62,16 @@ const styles = css` ${opposite}: calc(100% + 2rem); ${({ align }) => { switch (align) { - case 'start': return css` - ${perpendicular}: 0; - ` - case 'center': return css` - ${perpendicular}: 50%; - transform: translate${perpendicularAxis}(-50%); - ` - case 'end': return css` - ${perpendicularOpposite}: 0; - ` + case 'start': return css` + ${perpendicular}: 0; + ` + case 'center': return css` + ${perpendicular}: 50%; + transform: translate${perpendicularAxis}(-50%); + ` + default: return css` + ${perpendicularOpposite}: 0; + ` } }} } @@ -90,7 +90,7 @@ const styles = css` ` const Tooltip = styled(({ position, align, reverse, children, theme, ...props }) => - React.cloneElement(children, { tabIndex: 0, ...props }) + React.cloneElement(children, props) )`${styles}` Tooltip.propTypes = { @@ -103,7 +103,8 @@ Tooltip.propTypes = { Tooltip.defaultProps = { position: 'top', - align: 'center' + align: 'center', + tabIndex: 0 } export default Tooltip diff --git a/src/components/atoms/Tooltip/index.stories.js b/src/components/atoms/Tooltip/index.stories.js index 78fe2e4d..49a52fbf 100644 --- a/src/components/atoms/Tooltip/index.stories.js +++ b/src/components/atoms/Tooltip/index.stories.js @@ -6,49 +6,49 @@ storiesOf('Tooltip', module) .add('default', () => (
- Hover me + Hover me
)) .add('reverse', () => (
- Hover me + Hover me
)) .add('position right', () => (
- Hover me + Hover me
)) .add('position bottom', () => (
- Hover me + Hover me
)) .add('position left', () => (
- Hover me + Hover me
)) .add('align start', () => (
- Hover me + Hover me
)) .add('align end', () => (
- Hover me + Hover me
)) diff --git a/src/components/molecules/Feature/index.js b/src/components/molecules/Feature/index.js index fa9d06e4..a0b3ae7c 100644 --- a/src/components/molecules/Feature/index.js +++ b/src/components/molecules/Feature/index.js @@ -8,7 +8,7 @@ const Wrapper = styled.div` display: flex; padding: 1rem; box-sizing: border-box; - opacity: ${(props) => props.soon ? 0.4 : 1}; + opacity: ${props => props.soon ? 0.4 : 1}; ` const StyledIcon = styled(Icon)` @@ -34,7 +34,7 @@ const Feature = ({ icon, title, link, children, ...props, soon }) => { {icon && } - {link && {title} || title} + {link ? {title} : title} {children} @@ -48,7 +48,10 @@ Feature.propTypes = { icon: PropTypes.string, link: PropTypes.string, soon: PropTypes.bool, - children: PropTypes.any + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) } export default Feature diff --git a/src/components/molecules/IconButton/index.js b/src/components/molecules/IconButton/index.js index f66e763f..a280e78c 100644 --- a/src/components/molecules/IconButton/index.js +++ b/src/components/molecules/IconButton/index.js @@ -1,5 +1,6 @@ import React, { PropTypes } from 'react' import styled, { css, keyframes } from 'styled-components' +import { ifProp, get } from 'styled-tools' import { Icon, Button } from 'components' @@ -9,13 +10,13 @@ const fadeIn = keyframes` 100% { display: block; opacity: 1; } ` -const buttonStyles = ({ hasText, right, responsive, breakpoint, collapsed }) => css` - max-width: ${hasText && !collapsed ? '100%' : '2.5em'}; - width: ${hasText ? 'auto' : '2.5em'}; - padding: ${hasText ? '0 0.4375em' : 0}; +const StyledButton = styled(Button)` + max-width: ${props => props.hasText && !props.collapsed ? '100%' : '2.5em'}; + width: ${ifProp('hasText', 'auto', '2.5em')}; + padding: ${ifProp('hasText', '0 0.4375em', 0)}; flex: 0 0 2.5em; box-sizing: border-box; - ${collapsed && css` + ${ifProp('collapsed', css` overflow: hidden; transition: max-width 250ms ease-in-out; will-change: max-width; @@ -29,19 +30,19 @@ const buttonStyles = ({ hasText, right, responsive, breakpoint, collapsed }) => animation: ${fadeIn} 250ms; } } - `} - ${responsive && css` - @media screen and (max-width: ${breakpoint}px) { + `)} + ${ifProp('responsive', css` + @media screen and (max-width: ${get('breakpoint')}px) { width: auto; flex: 0 !important; } - `} + `)} ` -const textStyle = ({ responsive, breakpoint }) => css` +const Text = styled.span` padding: 0.4375em; - @media screen and (max-width: ${breakpoint}px) { - display: ${responsive && 'none !important'}; + @media screen and (max-width: ${get('breakpoint')}px) { + display: ${ifProp('responsive', 'none !important')}; } ` @@ -57,12 +58,6 @@ const StyledIcon = styled(Icon)` flex: none; ` -const StyledButton = styled(({ hasText, right, responsive, collapsed, breakpoint, ...props }) => -