diff --git a/.storybook/main.js b/.storybook/main.js index c8e0b9d9d..2989e3bbc 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -29,7 +29,8 @@ module.exports = { // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook require.resolve('babel-plugin-remove-graphql-queries'), // use babel-plugin-react-docgen to ensure PropTables still appear - require.resolve('babel-plugin-react-docgen') + require.resolve('babel-plugin-react-docgen'), + require.resolve('babel-plugin-styled-components') ] } } diff --git a/.storybook/preview.js b/.storybook/preview.js index 2dc9fe840..f3664684f 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,9 +1,8 @@ -import { ThemeProvider } from 'styled-components' import { LocationProvider } from '@gatsbyjs/reach-router' - +import { ThemeProvider } from 'styled-components' import Flex from 'components/elements/Flex' +import themeSpec, { themeCss } from 'theme' import React from 'react' -import theme from 'theme' import '@storybook/addon-console' @@ -24,13 +23,15 @@ window.___navigate = pathname => { export const decorators = [ Story => ( - + diff --git a/package.json b/package.json index 144e48474..cad1bc9e7 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "@techstack/styled-system": "~1.0.341", "@tippyjs/react": "~4.2.6", "@vercel/analytics": "~1.1.1", + "babel-plugin-styled-components": "~2.1.4", "beauty-error": "~1.2.18", "cssnano": "~6.0.2", "cssnano-preset-advanced": "~6.0.2", diff --git a/src/components/elements/Button/Button.js b/src/components/elements/Button/Button.js index 95b98c025..3316f2c67 100644 --- a/src/components/elements/Button/Button.js +++ b/src/components/elements/Button/Button.js @@ -2,15 +2,15 @@ import styled, { css } from 'styled-components' import { createCssState } from 'helpers/style' import { colors } from 'theme' -import ButtonBase from './ButtonBase' +import ButtonBase, { getColorVariant } from './ButtonBase' export const hoverStyle = createCssState({ selector: '&:hover:not([disabled])', state: 'hover', css: css` - background-color: ${({ color }) => colors[color]}; - color: ${({ bg }) => colors[bg]}; - box-shadow: 0 0 0 1px ${({ bg }) => colors[bg]}; + background: ${getColorVariant('color')}; + color: ${getColorVariant('background')}; + box-shadow: 0 0 0 1px ${getColorVariant('background')}; ` }) diff --git a/src/components/elements/Button/ButtonBase.js b/src/components/elements/Button/ButtonBase.js index 36f72bcc3..daceac726 100644 --- a/src/components/elements/Button/ButtonBase.js +++ b/src/components/elements/Button/ButtonBase.js @@ -1,34 +1,47 @@ +import { transition, themeCss } from 'theme' import styled from 'styled-components' -import { transition } from 'theme' import Text from '../Text' -const Button = styled(Text)({ - transition: `background-color ${transition.medium}, color ${transition.medium}, box-shadow ${transition.medium}`, - appearance: 'none', - display: 'inline-block', - textAlign: 'center', - lineHeight: 16 / 14, - textDecoration: 'none', - verticalAlign: 'middle', - WebkitFontSmoothing: 'antialiased', - whiteSpace: 'nowrap', - outline: 0, - '&:hover': { - cursor: 'pointer' - } -}) +const getColor = ({ theme, variant }, propName) => + theme.colors[theme.variants.button[variant][propName]] + +export const getColorVariant = propName => props => getColor(props, propName) + +const Button = styled(Text)( + props => { + return { + transition: `background-color ${transition.medium}, color ${transition.medium}, box-shadow ${transition.medium}`, + appearance: 'none', + display: 'inline-block', + textAlign: 'center', + lineHeight: 16 / 14, + textDecoration: 'none', + verticalAlign: 'middle', + WebkitFontSmoothing: 'antialiased', + whiteSpace: 'nowrap', + outline: 0, + '&:hover': { + cursor: 'pointer' + }, + color: getColorVariant('color'), + background: getColorVariant('background'), + boxShadow: props.variant === 'white' ? '0 0 0 1px black' : undefined + } + }, + themeCss({ + fontFamily: 'sans', + fontSize: 1, + fontWeight: 'bold', + px: 3, + py: 2, + border: 0, + borderRadius: 2 + }) +) Button.defaultProps = { as: 'button', - fontFamily: 'sans', - fontSize: 1, - fontWeight: 'bold', - px: 3, - py: 2, - color: 'white', - bg: 'link', - border: 0, - borderRadius: 2 + variant: 'base' } export default Button diff --git a/src/components/elements/Button/Buttons.stories.js b/src/components/elements/Button/Buttons.stories.js index e32552536..ca0852686 100644 --- a/src/components/elements/Button/Buttons.stories.js +++ b/src/components/elements/Button/Buttons.stories.js @@ -1,12 +1,15 @@ -import React from 'react' +import React, { useState } from 'react' import { storiesOf } from '@storybook/react' import { Caps, Flex, Button } from 'components/elements' +import { themeCss } from 'theme' import { Story } from 'story' const states = [null, 'hover', 'disabled', 'loading'] -const text = 'Get it' +const variants = ['base', 'black', 'white'] + +const text = 'BUY' const code = ` import { Button } from 'components/elements' @@ -16,21 +19,53 @@ export default () => ( ) ` +const BuyButton = ({ children, loading: initialLoading, ...props }) => { + const [isLoading, setIsLoading] = useState(initialLoading) + + const onClick = async () => { + setIsLoading(true) + await new Promise(resolve => setTimeout(resolve, 2000)) + setIsLoading(false) + } + + return ( + + ) +} + storiesOf('Elements', module).add('Button', () => ( - - {states.map(state => ( - - ))} + + BUY + BUY NOW + {variants.map((variant, index) => ( + 0 ? 4 : 0 })} key={variant}> + {states.map(state => ( + + BUY + + ))} + + ))} )) diff --git a/src/components/elements/Dot/Dot.js b/src/components/elements/Dot/Dot.js index 80ea04491..8441372c1 100644 --- a/src/components/elements/Dot/Dot.js +++ b/src/components/elements/Dot/Dot.js @@ -1,5 +1,6 @@ -import { createElement } from 'react' import styled from 'styled-components' +import { colors } from 'theme' +import React from 'react' import Text from '../Text' @@ -14,9 +15,20 @@ Dot.defaultProps = { as: 'span' } -const DotSuccess = props => createElement(Dot, { bg: 'teal3', ...props }) -const DotError = props => createElement(Dot, { bg: 'red6', ...props }) -const DotWarning = props => createElement(Dot, { bg: 'yellow6', ...props }) +const createDot = color => props => + ( + + ) + +const DotSuccess = createDot(colors.teal3) +const DotError = createDot(colors.red6) +const DotWarning = createDot(colors.yellow6) Dot.Success = DotSuccess Dot.Error = DotError diff --git a/src/components/elements/Input/Input.js b/src/components/elements/Input/Input.js index 6053525ea..65f5c27c4 100644 --- a/src/components/elements/Input/Input.js +++ b/src/components/elements/Input/Input.js @@ -1,34 +1,35 @@ -import { transition, colors, borders } from 'theme' +import { transition, colors, borders, themeCss } from 'theme' import React, { useMemo, useState } from 'react' import styled, { css } from 'styled-components' import Text from '../Text' import Flex from '../Flex' -const InputBase = styled(Text)({ - maxWidth: '100%', - display: 'inline-block', - verticalAlign: 'middle', - border: 0, - appearance: 'none', - '&:focus': { - outline: '0' +const InputBase = styled(Text)( + { + lineHeight: 'inherit', + background: 'transparent', + maxWidth: '100%', + display: 'inline-block', + verticalAlign: 'middle', + appearance: 'none', + '&:focus': { + outline: '0' + }, + '&:disabled': { + opacity: 1 / 4 + } }, - '&:disabled': { - opacity: 1 / 4 - } -}) + themeCss({ + border: 0, + p: 0, + mx: 2 + }) +) InputBase.defaultProps = { as: 'input', - type: 'text', - lineHeight: 'inherit', - width: 1, - border: 0, - p: 0, - mx: 2, - color: 'inherit', - bg: 'transparent' + type: 'text' } const focusStyle = css` @@ -58,11 +59,10 @@ const Input = ({ iconComponent: Icon, suggestions, children, - theme, + isDark, ...props }) => { const [isFocus, setFocus] = useState(props.autoFocus) - const isDark = theme === 'dark' const list = useMemo(() => { if (!suggestions) return undefined @@ -77,13 +77,15 @@ const Input = ({ return ( {Icon && {Icon}} { +const LinkSolid = props => { return ( - - {children} - + ) } diff --git a/src/components/patterns/Footer/Footer.js b/src/components/patterns/Footer/Footer.js index 4b4f1256c..efcf4b40c 100644 --- a/src/components/patterns/Footer/Footer.js +++ b/src/components/patterns/Footer/Footer.js @@ -1,5 +1,5 @@ +import { layout, colors, themeCss } from 'theme' import { Microlink } from 'components/logos' -import { layout, colors } from 'theme' import { Mail } from 'react-feather' import { issueUrl } from 'helpers' import React from 'react' @@ -24,8 +24,6 @@ import { const LIGHT_THEME = { bg: 'white', textColor: 'black60', - buttonColor: 'white', - buttonBg: 'black', inputIconColor: colors.black40, iconColor: colors.black80 } @@ -33,42 +31,54 @@ const LIGHT_THEME = { const DARK_THEME = { bg: 'black', textColor: 'white60', - buttonColor: 'black', - buttonBg: 'white', inputIconColor: colors.white40, iconColor: colors.white80 } const Footer = ({ theme, ...props }) => { const isDark = theme === 'dark' - const { bg, textColor, buttonColor, buttonBg, inputIconColor } = isDark - ? DARK_THEME - : LIGHT_THEME + const { bg, textColor, inputIconColor } = isDark ? DARK_THEME : LIGHT_THEME return ( - + - - - + + + - - + + Turn websites into data - +
{ type='email' name='EMAIL' placeholder='you@domain.com' - width='8rem' - fontSize={0} iconComponent={} - theme={theme} + isDark={isDark} + css={themeCss({ fontSize: 1, width: '8rem' })} required />
- + Early access & updates on new releases.
- - - - API - - - Blog - - - Community - - - Status - + + + {[ + { children: 'API', href: '/docs/api/getting-started/overview' }, + { children: 'Blog', href: '/blog' }, + { children: 'Chat', href: '/community' }, + { children: 'Status', href: '/status' } + ].map(({ href, children }) => ( + + {children} + + ))} - - - - SDK - - - Pricing - - - Open Source - - - Bug Reports - + + + {[ + { children: 'SDK', href: '/docs/sdk/getting-started/overview/' }, + { children: 'Pricing', href: '/#pricing' }, + { children: 'Open Source', href: '/oss' }, + { children: 'Bug Reports', href: issueUrl.bug() } + ].map(({ href, children }) => ( + + {children} + + ))} - - + + - + {({ isHealthy, isLoading }) => { if (isLoading) { return ( - Status Page + + Status Page + ) } return ( - + All systems operational - + System performance degradation @@ -251,38 +276,56 @@ const Footer = ({ theme, ...props }) => { - - + + © Microlink - - Terms - - - Privacy - + {[ + { + href: '/tos', + children: 'Terms' + }, + { + href: '/privacy', + children: 'Privacy' + } + ].map(({ href, children }) => ( + + {children} + + ))} {[ { @@ -304,10 +347,12 @@ const Footer = ({ theme, ...props }) => { 0 ? 2 : 0} - fontSize={0} + css={themeCss({ + pl: index > 0 ? 2 : 0, + fontSize: 1 + })} icon {...props} /> diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index bff56342e..68fe14c7f 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -1,7 +1,7 @@ +import { ThemeProvider } from 'styled-components' import { Toolbar, Footer } from 'components/patterns' import React, { useEffect, createElement } from 'react' import { BreakpointProvider } from 'context/breakpoint' -import { ThemeProvider } from 'styled-components' import { Box, Flex } from 'components/elements' import { useBreakpoint } from 'components/hook' import { noop } from 'helpers' @@ -73,11 +73,11 @@ const Layout = ({ }, children )} */} - {/* {footer && ( + {footer && (