From a0ffca98970da002177629542b4d825e1d8005ad Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Sun, 31 Dec 2023 18:24:25 +0100 Subject: [PATCH 01/57] refactor: remove Fixed component --- src/components/elements/Position.js | 56 ------------------- src/components/elements/index.js | 2 - .../patterns/Toolbar/ToolbarDesktop.js | 5 +- .../patterns/Toolbar/ToolbarMobile.js | 5 +- 4 files changed, 6 insertions(+), 62 deletions(-) delete mode 100644 src/components/elements/Position.js diff --git a/src/components/elements/Position.js b/src/components/elements/Position.js deleted file mode 100644 index c6f12a927..000000000 --- a/src/components/elements/Position.js +++ /dev/null @@ -1,56 +0,0 @@ -import { - compose, - position, - zIndex, - top, - right, - bottom, - left -} from 'styled-system' -import styled from 'styled-components' -import Box from './Box' - -export const Position = styled(Box)( - compose( - position, - zIndex, - top, - right, - bottom, - left - ) -) - -Position.propTypes = { - ...Box.propTypes, - ...position.propTypes, - ...zIndex.propTypes, - ...top.propTypes, - ...right.propTypes, - ...bottom.propTypes, - ...left.propTypes -} - -export const Relative = styled(Position)`` - -Relative.defaultProps = { - position: 'relative' -} - -export const Absolute = styled(Position)`` - -Absolute.defaultProps = { - position: 'absolute' -} - -export const Fixed = styled(Position)`` - -Fixed.defaultProps = { - position: 'fixed' -} - -export const Sticky = styled(Position)`` - -Sticky.defaultProps = { - position: 'sticky' -} diff --git a/src/components/elements/index.js b/src/components/elements/index.js index 0e4b06da0..d48f41512 100644 --- a/src/components/elements/index.js +++ b/src/components/elements/index.js @@ -1,6 +1,5 @@ import { withTitle } from 'helpers/hoc' -import { Fixed } from './Position' import { Link, LinkSolid } from './Link' import AnimatedBox from './AnimatedBox' import Badge from './Badge/Badge' @@ -75,7 +74,6 @@ export { Container, Dot, DotSpinner, - Fixed, Flex, Heading, Hide, diff --git a/src/components/patterns/Toolbar/ToolbarDesktop.js b/src/components/patterns/Toolbar/ToolbarDesktop.js index d1289becd..b185c1a16 100644 --- a/src/components/patterns/Toolbar/ToolbarDesktop.js +++ b/src/components/patterns/Toolbar/ToolbarDesktop.js @@ -82,7 +82,8 @@ const ToolbarDesktop = ({ theme }) => { const setToolbar = name => () => setSecondary(name) return ( - { - + ) } diff --git a/src/components/patterns/Toolbar/ToolbarMobile.js b/src/components/patterns/Toolbar/ToolbarMobile.js index 45507a5ad..42538b4a4 100644 --- a/src/components/patterns/Toolbar/ToolbarMobile.js +++ b/src/components/patterns/Toolbar/ToolbarMobile.js @@ -30,7 +30,8 @@ const ToolbarMobile = ({ theme }) => { const isDark = theme === 'dark' return ( - { - + ) } From b034218644364d49c337bd13af8a83fd8cc212ba Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Sun, 31 Dec 2023 18:26:05 +0100 Subject: [PATCH 02/57] refactor: initial migration --- package.json | 3 +- src/components/elements/Box.js | 64 ++++---------------- src/components/elements/Button/ButtonBase.js | 44 ++++++-------- src/components/elements/Caps.js | 9 +-- src/components/elements/Flex.js | 30 +-------- src/components/elements/Image/Image.js | 39 +++--------- src/components/elements/Svg.js | 22 +------ src/components/elements/Text.js | 21 +------ src/components/patterns/Toolbar/NavLink.js | 8 +-- src/theme/index.js | 40 +++--------- 10 files changed, 62 insertions(+), 218 deletions(-) diff --git a/package.json b/package.json index ef602666e..a01d651d1 100644 --- a/package.json +++ b/package.json @@ -109,6 +109,7 @@ "@stripe/react-stripe-js": "~2.4.0", "@stripe/stripe-js": "~2.2.2", "@styled-system/prop-types": "~5.1.5", + "@techstack/styled-system": "~1.0.341", "@tippyjs/react": "~4.2.6", "@vercel/analytics": "~1.2.2", "beauty-error": "~1.2.18", @@ -152,7 +153,7 @@ "react-twitter-widgets": "~1.11.0", "remark-slug": "~7.0.1", "sass": "~1.70.0", - "styled-components": "5", + "styled-components": "~6.1.6", "styled-is": "~1.3.0", "styled-system": "~5.1.5", "swr": "~2.2.4", diff --git a/src/components/elements/Box.js b/src/components/elements/Box.js index bb54d861c..a8b60fcb0 100644 --- a/src/components/elements/Box.js +++ b/src/components/elements/Box.js @@ -1,63 +1,21 @@ import { - compose, - space, color, - borders, - lineHeight, - width, - flex, - order, - alignSelf, - position, - fontSize, + space, variant, - textAlign, - maxWidth, - boxShadow, - display, - height -} from 'styled-system' + border, + position, + layout +} from '@techstack/styled-system' import styled from 'styled-components' -import propTypes from '@styled-system/prop-types' const Box = styled('div')( - compose( - space, - textAlign, - maxWidth, - boxShadow, - display, - borders, - lineHeight, - height, - width, - fontSize, - color, - flex, - order, - alignSelf, - position, - variant({ key: 'boxStyles' }) - ) + border, + color, + layout, + position, + space, + variant({ key: 'button' }) ) -Box.propTypes = { - ...propTypes.space, - ...propTypes.textAlign, - ...propTypes.maxWidth, - ...propTypes.boxShadow, - ...propTypes.border, - ...propTypes.display, - ...propTypes.width, - ...propTypes.height, - ...propTypes.fontSize, - ...propTypes.color, - ...propTypes.flex, - ...propTypes.order, - ...propTypes.alignSelf, - ...propTypes.position, - ...propTypes.lineHeight -} - export default Box diff --git a/src/components/elements/Button/ButtonBase.js b/src/components/elements/Button/ButtonBase.js index d87437016..36f72bcc3 100644 --- a/src/components/elements/Button/ButtonBase.js +++ b/src/components/elements/Button/ButtonBase.js @@ -1,37 +1,27 @@ -import { compose, borders, buttonStyle } from 'styled-system' -import propTypes from '@styled-system/prop-types' -import { transition } 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' - } - }, - compose(borders, buttonStyle) -) - -Button.propTypes = { - ...propTypes.Text, - ...propTypes.border -} +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' + } +}) Button.defaultProps = { as: 'button', fontFamily: 'sans', - fontSize: '1', + fontSize: 1, fontWeight: 'bold', px: 3, py: 2, diff --git a/src/components/elements/Caps.js b/src/components/elements/Caps.js index e3df1a261..27df003fc 100644 --- a/src/components/elements/Caps.js +++ b/src/components/elements/Caps.js @@ -1,16 +1,11 @@ import styled from 'styled-components' -import { letterSpacing } from 'styled-system' import Text from './Text' -const Caps = styled(Text)( - { - textTransform: 'uppercase' - }, - letterSpacing -) +const Caps = styled(Text)`` Caps.defaultProps = { + textTransform: 'uppercase', fontSize: 1, letterSpacing: 2 } diff --git a/src/components/elements/Flex.js b/src/components/elements/Flex.js index e063349d6..aad285215 100644 --- a/src/components/elements/Flex.js +++ b/src/components/elements/Flex.js @@ -1,15 +1,6 @@ -import { - compose, - flexWrap, - flexDirection, - alignItems, - justifyContent, - alignContent, - display -} from 'styled-system' +import { flexbox } from '@techstack/styled-system' import styled from 'styled-components' -import propTypes from '@styled-system/prop-types' import Box from './Box' @@ -17,24 +8,7 @@ const Flex = styled(Box)( { display: 'flex' }, - compose( - display, - alignContent, - alignItems, - flexDirection, - flexWrap, - justifyContent - ) + flexbox ) -Flex.propTypes = { - ...Box.propTypes, - ...propTypes.alignContent, - ...propTypes.alignItems, - ...propTypes.flexDirection, - ...propTypes.flexWrap, - ...propTypes.justifyContent, - ...propTypes.display -} - export default Flex diff --git a/src/components/elements/Image/Image.js b/src/components/elements/Image/Image.js index c2dfa608b..b5a9840af 100644 --- a/src/components/elements/Image/Image.js +++ b/src/components/elements/Image/Image.js @@ -1,47 +1,26 @@ -import propTypes from '@styled-system/prop-types' import styled from 'styled-components' import { withLazy } from 'helpers/hoc' import { - compose, space, color, - maxWidth, - width, - height, - display, - textAlign, - borderRadius -} from 'styled-system' + layout, + typography, + border +} from '@techstack/styled-system' const Image = styled('img')( { display: 'block', maxWidth: '100%' }, - compose( - space, - color, - width, - height, - maxWidth, - display, - textAlign, - borderRadius - ) + space, + color, + layout, + typography, + border ) -Image.propTypes = { - ...propTypes.space, - ...propTypes.color, - ...propTypes.width, - ...propTypes.height, - ...propTypes.maxWidth, - ...propTypes.display, - ...propTypes.textAlign, - ...propTypes.borderRadius -} - Image.defaultProps = { decoding: 'async', loading: 'lazy' diff --git a/src/components/elements/Svg.js b/src/components/elements/Svg.js index 62edecdc4..9f9db44be 100644 --- a/src/components/elements/Svg.js +++ b/src/components/elements/Svg.js @@ -1,31 +1,15 @@ -import { compose, color, space, height, width, style } from 'styled-system' -import propTypes from '@styled-system/prop-types' +import { compose, color, space, layout, system } from '@techstack/styled-system' import styled from 'styled-components' -const transform = style({ +const transform = system({ prop: 'transform', cssProperty: 'transform' }) -const Svg = styled('svg')( - compose( - color, - space, - height, - width, - transform - ) -) +const Svg = styled('svg')(color, space, layout, transform) Svg.defaultProps = { fill: 'currentColor' } -Svg.propTypes = { - ...propTypes.space, - ...propTypes.width, - ...propTypes.height, - ...propTypes.color -} - export default Svg diff --git a/src/components/elements/Text.js b/src/components/elements/Text.js index 7237f2b78..ab83e61e0 100644 --- a/src/components/elements/Text.js +++ b/src/components/elements/Text.js @@ -1,26 +1,9 @@ -import { - compose, - variant, - fontFamily, - fontWeight, - letterSpacing -} from 'styled-system' - +import { variant, typography } from '@techstack/styled-system' import styled from 'styled-components' -import propTypes from '@styled-system/prop-types' import Box from './Box' -const Text = styled(Box)( - compose(fontFamily, fontWeight, letterSpacing, variant({ key: 'textStyles' })) -) - -Text.propTypes = { - ...Box.propTypes, - ...propTypes.fontFamily, - ...propTypes.fontWeight, - ...propTypes.letterSpacing -} +const Text = styled(Box)(typography, variant({ key: 'text' })) Text.defaultProps = { fontWeight: 'normal', diff --git a/src/components/patterns/Toolbar/NavLink.js b/src/components/patterns/Toolbar/NavLink.js index 9ea087dc0..c854fce7d 100644 --- a/src/components/patterns/Toolbar/NavLink.js +++ b/src/components/patterns/Toolbar/NavLink.js @@ -21,7 +21,6 @@ const style = css` const NavLink = styled(Caps)( { - bg: 'transparent', display: 'inline-flex', alignItems: 'center', alignSelf: 'stretch', @@ -36,9 +35,10 @@ const NavLink = styled(Caps)( ) NavLink.defaultProps = { - pl: 3, - fontSize: 0, - as: 'div' + // TODO: this seems like a bug + // https://github.com/The-Code-Monkey/styled-system/issues/640 + fontSize: [0, 0, 0, 0], + pl: 3 } export default withAnalytics(withLink(NavLink)) diff --git a/src/theme/index.js b/src/theme/index.js index d8db7b18e..f0c03a295 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -225,8 +225,7 @@ export const colors = Object.assign({}, flattened, { export const fonts = { sans: "'Inter', sans-serif", - mono: - '"Operator Mono", "Fira Code", "SF Mono", "Roboto Mono", Menlo, monospace' + mono: '"Operator Mono", "Fira Code", "SF Mono", "Roboto Mono", Menlo, monospace' } export const cx = key => colors[key] || key @@ -249,24 +248,7 @@ export const shadows = shadowOffsets.map( export const lineHeights = ['normal', 1.25, 1.5, 1.6, 1.65] export const sizes = [ - 1, - 2, - 4, - 8, - 12, - 16, - 20, - 24, - 28, - 32, - 36, - 40, - 44, - 48, - 64, - 72, - 82, - 96 + 1, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 64, 72, 82, 96 ].map(toEm) export const speed = { @@ -301,13 +283,12 @@ export const textGradient = { } } -export const textStyles = { - gradient: textGradient -} - -export const boxStyles = { - gradient: { - backgroundImage: gradient +export const variants = { + text: { + gradient: textGradient + }, + button: { + gradient } } @@ -321,7 +302,6 @@ export const letterSpacings = [0, -0.025, 0.025, 0.1, 0.25].map(toEm) const theme = { borders, - boxStyles, breakpoints, colors, fonts, @@ -337,9 +317,9 @@ const theme = { sizes, space, speed, - textStyles, timings, - transition + transition, + variants } export default theme From 7d0d35578c93568f8cbbe7c60ead829110239e59 Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Thu, 8 Feb 2024 21:15:10 +0100 Subject: [PATCH 03/57] refactor: migrate header --- package.json | 1 - src/components/elements/Box.js | 16 +- src/components/elements/Caps.js | 15 +- src/components/elements/Svg.js | 2 +- src/components/elements/Text.js | 28 ++-- src/components/elements/Toolbar.js | 32 ++-- src/components/icons/GitHub.js | 2 +- src/components/logos/Microlink.js | 3 +- .../patterns/DotsBackground/DotsBackground.js | 26 ++-- src/components/patterns/Layout.js | 21 +-- src/components/patterns/Toolbar/NavLink.js | 22 ++- .../patterns/Toolbar/ToolbarDesktop.js | 138 ++++++++++++------ .../patterns/Toolbar/ToolbarLinks.js | 50 ++++--- .../patterns/Toolbar/ToolbarMobile.js | 33 +++-- src/theme/index.js | 31 ++-- 15 files changed, 232 insertions(+), 188 deletions(-) diff --git a/package.json b/package.json index a01d651d1..bb93f09df 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,6 @@ "mdx-scoped-runtime": "~0.8.0", "microsoft-capitalize": "~1.0.5", "normalize.css": "~8.0.1", - "palx": "~1.0.3", "path-browserify": "~1.0.1", "polished": "~4.3.1", "postcss": "~8.4.32", diff --git a/src/components/elements/Box.js b/src/components/elements/Box.js index a8b60fcb0..f366f97a5 100644 --- a/src/components/elements/Box.js +++ b/src/components/elements/Box.js @@ -1,21 +1,17 @@ import { - color, - space, - variant, border, + color, + compose, + layout, position, - layout + space, + variant } from '@techstack/styled-system' import styled from 'styled-components' const Box = styled('div')( - border, - color, - layout, - position, - space, - variant({ key: 'button' }) + compose(border, color, layout, position, space, variant({ key: 'button' })) ) export default Box diff --git a/src/components/elements/Caps.js b/src/components/elements/Caps.js index 27df003fc..0c2940e26 100644 --- a/src/components/elements/Caps.js +++ b/src/components/elements/Caps.js @@ -1,13 +1,14 @@ import styled from 'styled-components' +import { themeCss } from 'theme' import Text from './Text' -const Caps = styled(Text)`` - -Caps.defaultProps = { - textTransform: 'uppercase', - fontSize: 1, - letterSpacing: 2 -} +const Caps = styled(Text)( + themeCss({ + textTransform: 'uppercase', + fontSize: 1, + letterSpacing: 2 + }) +) export default Caps diff --git a/src/components/elements/Svg.js b/src/components/elements/Svg.js index 9f9db44be..aade43177 100644 --- a/src/components/elements/Svg.js +++ b/src/components/elements/Svg.js @@ -6,7 +6,7 @@ const transform = system({ cssProperty: 'transform' }) -const Svg = styled('svg')(color, space, layout, transform) +const Svg = styled('svg')(compose(color, space, layout, transform)) Svg.defaultProps = { fill: 'currentColor' diff --git a/src/components/elements/Text.js b/src/components/elements/Text.js index ab83e61e0..ae62e1244 100644 --- a/src/components/elements/Text.js +++ b/src/components/elements/Text.js @@ -1,21 +1,19 @@ -import { variant, typography } from '@techstack/styled-system' +import { compose, variant, typography } from '@techstack/styled-system' +import { themeCss, defaultProps } from 'theme' import styled from 'styled-components' import Box from './Box' -const Text = styled(Box)(typography, variant({ key: 'text' })) - -Text.defaultProps = { - fontWeight: 'normal', - letterSpacing: 0, - as: 'div', - fontFamily: 'sans', - mt: 0, - mb: 0, - mr: 0, - ml: 0, - lineHeight: 3, - fontSize: [1, 1, 2, 2] -} +const Text = styled(Box).attrs(defaultProps({ as: 'div' }))( + compose(typography, variant({ key: 'text' })), + themeCss({ + fontWeight: 'normal', + letterSpacing: 0, + fontFamily: 'sans', + m: 0, + lineHeight: 3, + fontSize: [1, 1, 2, 2] + }) +) export default Text diff --git a/src/components/elements/Toolbar.js b/src/components/elements/Toolbar.js index a16b5b40c..e804ff0c4 100644 --- a/src/components/elements/Toolbar.js +++ b/src/components/elements/Toolbar.js @@ -1,6 +1,6 @@ +import { defaultProps, layout, themeCss } from 'theme' import { hideScrollbar } from 'helpers/style' import styled from 'styled-components' -import { layout } from 'theme' import React from 'react' import Flex from './Flex' @@ -8,22 +8,20 @@ import Flex from './Flex' export const TOOLBAR_PRIMARY_HEIGHT = '64px' export const TOOLBAR_SECONDARY_HEIGHT = '48px' -const ToolbarBase = styled(Flex)` - overflow-x: auto; - overflow-y: hidden; +const ToolbarBase = styled(Flex).attrs(defaultProps({ as: 'nav' }))` + ${themeCss({ + justifyContent: 'center', + color: 'black60', + mx: 'auto', + alignItems: 'center', + maxWidth: layout.large, + px: 0, + 'overflow-x': 'auto', + 'overflow-y': 'hidden' + })})} ${hideScrollbar}; ` -ToolbarBase.defaultProps = { - as: 'nav', - justifyContent: 'center', - color: 'black60', - mx: 'auto', - alignItems: 'center', - maxWidth: layout.large, - px: 0 -} - const secondaryProps = { justifyContent: 'center' } @@ -34,8 +32,10 @@ const Toolbar = ({ type = 'primary', ...props }) => { return ( ) diff --git a/src/components/icons/GitHub.js b/src/components/icons/GitHub.js index 401ca7b9e..6e4d012a8 100644 --- a/src/components/icons/GitHub.js +++ b/src/components/icons/GitHub.js @@ -5,7 +5,7 @@ export const GitHub = ({ width = 18, ...props }) => ( diff --git a/src/components/logos/Microlink.js b/src/components/logos/Microlink.js index 2b4fd69aa..dd84042e8 100644 --- a/src/components/logos/Microlink.js +++ b/src/components/logos/Microlink.js @@ -7,8 +7,7 @@ const Microlink = props => { return ( diff --git a/src/components/patterns/DotsBackground/DotsBackground.js b/src/components/patterns/DotsBackground/DotsBackground.js index 11fa86990..69a0d66ee 100644 --- a/src/components/patterns/DotsBackground/DotsBackground.js +++ b/src/components/patterns/DotsBackground/DotsBackground.js @@ -1,16 +1,14 @@ import styled, { css } from 'styled-components' import { slide } from 'components/keyframes' import { Box } from 'components/elements' +import { defaultProps } from 'theme' import is from 'styled-is' const darkStyle = css` background: #000; background-color: #000; - background-image: radial-gradient( - rgba(215, 215, 215, 0.15) 1px, - transparent 0 - ), - radial-gradient(rgba(215, 215, 215, 0.15) 1px, transparent 0); + background-image: radial-gradient(rgba(215, 215, 215, 0.3) 1px, transparent 0), + radial-gradient(rgba(215, 215, 215, 0.3) 1px, transparent 0); ` const lightStyle = css` @@ -23,9 +21,16 @@ const animateStyle = css` animation-direction: reverse; ` -const Dots = styled(Box)` - position: relative; - overflow: hidden; +const Dots = styled(Box) + .attrs(defaultProps({ theme: 'light', animate: true })) + .withConfig({ shouldForwardProp: prop => !['animate'].includes(prop) })` + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + min-height: 100vh; + z-index: -1; &:before { content: ''; @@ -42,9 +47,4 @@ const Dots = styled(Box)` } ` -Dots.defaultProps = { - theme: 'light', - animate: true -} - export default Dots diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index b8459e1f9..bff56342e 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -6,7 +6,8 @@ import { Box, Flex } from 'components/elements' import { useBreakpoint } from 'components/hook' import { noop } from 'helpers' -import themeSpec from 'theme' +import themeSpec, { themeCss } from 'theme' + import 'styles/main.scss' import { @@ -50,16 +51,16 @@ const Layout = ({ - {createElement( + {/* {createElement( component, { as: 'main', @@ -71,12 +72,12 @@ const Layout = ({ style: { flex: 1 } }, children - )} - {footer && ( + )} */} + {/* {footer && (
- )} + )} */}
diff --git a/src/components/patterns/Toolbar/NavLink.js b/src/components/patterns/Toolbar/NavLink.js index c854fce7d..7b84c564e 100644 --- a/src/components/patterns/Toolbar/NavLink.js +++ b/src/components/patterns/Toolbar/NavLink.js @@ -1,8 +1,7 @@ +import { colors, fontWeights, transition, themeCss } from 'theme' +import { withLink, withAnalytics } from 'helpers/hoc' import styled, { css } from 'styled-components' -import { colors, fontWeights, transition } from 'theme' - import { Caps } from 'components/elements' -import { withLink, withAnalytics } from 'helpers/hoc' const activeStyle = css` font-weight: ${fontWeights.bold}; @@ -19,8 +18,12 @@ const style = css` } ` -const NavLink = styled(Caps)( - { +const NavLink = styled(Caps).withConfig({ + shouldForwardProp: prop => !['isDark'].includes(prop) +})( + themeCss({ + fontSize: 0, + pl: 3, display: 'inline-flex', alignItems: 'center', alignSelf: 'stretch', @@ -30,15 +33,8 @@ const NavLink = styled(Caps)( '&:disabled': { opacity: 1 / 4 } - }, + }), style ) -NavLink.defaultProps = { - // TODO: this seems like a bug - // https://github.com/The-Code-Monkey/styled-system/issues/640 - fontSize: [0, 0, 0, 0], - pl: 3 -} - export default withAnalytics(withLink(NavLink)) diff --git a/src/components/patterns/Toolbar/ToolbarDesktop.js b/src/components/patterns/Toolbar/ToolbarDesktop.js index b185c1a16..31c38ee97 100644 --- a/src/components/patterns/Toolbar/ToolbarDesktop.js +++ b/src/components/patterns/Toolbar/ToolbarDesktop.js @@ -1,10 +1,10 @@ -import { Choose, Toolbar, Flex, Box, Fixed } from 'components/elements' +import { Choose, Toolbar, Flex, Box } from 'components/elements' import { useLocation } from '@gatsbyjs/reach-router' import { GitHub, Twitter } from 'components/icons' +import { colors, themeCss } from 'theme' import React, { useState } from 'react' import { css } from 'styled-components' import { rgba } from 'polished' -import { colors } from 'theme' import NavContainer from './NavContainer' @@ -49,8 +49,15 @@ const iconDark = css` const ToolbarSecondary = ({ isDark, children }) => ( - - + + {children} @@ -83,59 +90,72 @@ const ToolbarDesktop = ({ theme }) => { return ( - + - + + > + Products + - + - + - + @@ -143,29 +163,59 @@ const ToolbarDesktop = ({ theme }) => { - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + diff --git a/src/components/patterns/Toolbar/ToolbarLinks.js b/src/components/patterns/Toolbar/ToolbarLinks.js index ca138ca4a..3845ddc86 100644 --- a/src/components/patterns/Toolbar/ToolbarLinks.js +++ b/src/components/patterns/Toolbar/ToolbarLinks.js @@ -1,30 +1,33 @@ import React, { createElement } from 'react' import { Microlink } from 'components/logos' import { navigate } from 'gatsby' +import { fontSizes } from 'theme' import NavLink from './NavLink' const createNavItem = opts => { - const NavItemWrapper = props => + const NavItemWrapper = ({ isMobile, ...props }) => createElement(NavLink, { 'data-event-location': 'Toolbar', 'data-event-name': opts.children, - icon: false, ...opts, - ...props + ...props, + as: 'li' }) + return NavItemWrapper } const NavLogoMobile = props => ( - - + + ) @@ -34,22 +37,23 @@ const NavLogoDesktop = props => ( event.preventDefault() navigate('/design') }} + css={{ + display: 'flex', + width: '52px' + }} href='/' - width='40px' - display='flex' {...props} > ) -export const NavMicrolinkLogo = ({ mobile, ...props }) => - createElement(mobile ? NavLogoMobile : NavLogoDesktop, { px: 0, ...props }) - -NavMicrolinkLogo.defaultProps = { - 'data-event-location': 'Toolbar', - 'data-event-name': 'Logo' -} +export const NavMicrolinkLogo = ({ isMobile, ...props }) => + createElement(isMobile ? NavLogoMobile : NavLogoDesktop, { + 'data-event-location': 'Toolbar', + 'data-event-name': 'Logo', + ...props + }) export const NavPricing = createNavItem({ children: 'Pricing', @@ -182,11 +186,13 @@ NavCompany.pages = ['/blog', '/oss', '/newsletter'] export const NavGitHub = createNavItem({ children: 'GitHub', href: 'https://github.com/microlinkhq', - title: '@microlinkhq on GitHub' + title: '@microlinkhq on GitHub', + icon: false }) export const NavTwitter = createNavItem({ children: 'Twitter', href: 'https://twitter.com/microlinkhq', - title: '@microlinkhq on Twitter' + title: '@microlinkhq on Twitter', + icon: false }) diff --git a/src/components/patterns/Toolbar/ToolbarMobile.js b/src/components/patterns/Toolbar/ToolbarMobile.js index 42538b4a4..6803ad7ba 100644 --- a/src/components/patterns/Toolbar/ToolbarMobile.js +++ b/src/components/patterns/Toolbar/ToolbarMobile.js @@ -1,5 +1,6 @@ -import { Box, Fixed, Toolbar } from 'components/elements' +import { Box, Toolbar } from 'components/elements' import styled from 'styled-components' +import { themeCss } from 'theme' import React from 'react' import NavContainer from './NavContainer' @@ -31,26 +32,28 @@ const ToolbarMobile = ({ theme }) => { return ( - - - + + + diff --git a/src/theme/index.js b/src/theme/index.js index f0c03a295..9c892034a 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -1,11 +1,21 @@ -import palx from 'palx' import { lighten } from 'polished' +export { css as themeCss } from '@techstack/styled-system' + export const toPx = n => `${n}px` export const toEm = n => `${n}em` export const toMs = n => `${n}ms` export const toRaw = n => Number(n.replace(/px|em/, '')) +export const defaultProps = obj => props => { + return Object.keys(obj).reduce((acc, key) => { + if (props[key] === undefined) { + acc[key] = obj[key] + } + return acc + }, {}) +} + export const breakpoints = [600, 768, 1200, 1200].map(toPx) export const space = [0, 4, 8, 16, 32, 64, 128, 256, 512].map(toPx) @@ -23,24 +33,9 @@ export const radii = [0, 2, 4, 6, 8, 16].map(toPx) export const borders = [0, '1px solid', '2px solid', '2px dashed'] -const palette = palx('#449bf8') - -const flattened = Object.keys(palette).reduce((a, key) => { - const value = palette[key] - if (Array.isArray(value)) { - a[key] = value[5] - value.forEach((val, i) => { - a[key + i] = val - }) - } else { - a[key] = value - } - return a -}, {}) - // https://palx.jxnblk.com/067df7 // https://github.com/yeun/open-color -export const colors = Object.assign({}, flattened, { +export const colors = { link: '#067df7', hoverLink: lighten(0.15, '#067df7'), secondary: '#EA407B', @@ -221,7 +216,7 @@ export const colors = Object.assign({}, flattened, { orange7: '#f76707', orange8: '#e8590c', orange9: '#d9480f' -}) +} export const fonts = { sans: "'Inter', sans-serif", From 6f246e0fea5c6d1ce801440d0356879418d76dea Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Sun, 3 Mar 2024 11:07:27 +0100 Subject: [PATCH 04/57] refactor: migrate footer --- .storybook/main.js | 3 +- .storybook/preview.js | 17 +- package.json | 1 + src/components/elements/Button/Button.js | 8 +- src/components/elements/Button/ButtonBase.js | 63 +-- .../elements/Button/Buttons.stories.js | 65 ++- src/components/elements/Dot/Dot.js | 20 +- src/components/elements/Input/Input.js | 58 +-- src/components/elements/Link/solid.js | 14 +- src/components/patterns/Footer/Footer.js | 369 ++++++++++-------- src/components/patterns/Layout.js | 6 +- src/helpers/hoc/with-spinner.js | 53 ++- src/helpers/style/index.js | 16 +- src/theme/index.js | 14 +- 14 files changed, 411 insertions(+), 296 deletions(-) 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 bb93f09df..624f6ba78 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.2.2", + "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 && (
- )} */} + )}
diff --git a/src/helpers/hoc/with-spinner.js b/src/helpers/hoc/with-spinner.js index 32dc5be0f..81fa7ba27 100644 --- a/src/helpers/hoc/with-spinner.js +++ b/src/helpers/hoc/with-spinner.js @@ -1,5 +1,4 @@ -import React, { Component, createElement } from 'react' - +import React, { createElement, useState, useEffect, useRef } from 'react' import SpinnerIcon from '../../components/elements/Spinner' import Flex from '../../components/elements/Flex' @@ -12,34 +11,34 @@ export const withSpinner = ChildComponent => { ) - class SpinnerWrapper extends Component { - componentDidMount () { - if (this.button) { - const { width } = this.button.getBoundingClientRect() - this.setState({ width }) - } - } + const SpinnerWrapper = ({ loading, ...props }) => { + const [width, setWidth] = useState(undefined) + const [height, setHeight] = useState(undefined) + const ref = useRef(null) - render () { - const { loading, ...props } = this.props - if (!loading) { - return ( - (this.button = button)} {...props} /> - ) - } else { - const children = createElement(SpinnerIcon) - const width = this.state && this.state.width - return createElement( - SpinnerButton, - { - ...props, - disabled: true, - style: { width, cursor: 'wait' } - }, - children - ) + useEffect(() => { + if (ref.current) { + const computed = window.getComputedStyle(ref.current) + setWidth(parseInt(computed.getPropertyValue('width'))) + setHeight(parseInt(computed.getPropertyValue('height'))) } + }, []) + + if (!loading) { + return } + + const children = createElement(SpinnerIcon) + + return createElement( + SpinnerButton, + { + ...props, + disabled: true, + style: { width, height, cursor: 'wait' } + }, + children + ) } return SpinnerWrapper diff --git a/src/helpers/style/index.js b/src/helpers/style/index.js index ef76f0dc0..9dc3c6f5e 100644 --- a/src/helpers/style/index.js +++ b/src/helpers/style/index.js @@ -1,12 +1,14 @@ import { css } from 'styled-components' -export const createCssState = ({ selector, state, css: cssStyle }) => props => - css` - ${props => props.state === state && cssStyle} - ${selector} { - ${cssStyle}; - } - ` +export const createCssState = + ({ selector, state, css: cssStyle }) => + () => + css` + ${props => props.state === state && cssStyle} + ${selector} { + ${cssStyle}; + } + ` export const wordBreak = css` /* These are technically the same, but use both */ diff --git a/src/theme/index.js b/src/theme/index.js index 9c892034a..75eec435f 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -283,7 +283,19 @@ export const variants = { gradient: textGradient }, button: { - gradient + gradient, + base: { + color: 'white', + background: 'link' + }, + black: { + background: 'black', + color: 'white' + }, + white: { + background: 'white', + color: 'black' + } } } From 7692d3721c83182a7b1a2829ff6762584e21ed41 Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Wed, 6 Mar 2024 15:20:18 +0100 Subject: [PATCH 05/57] refactor: rename themeCss into theme --- .storybook/preview.js | 4 +- src/components/elements/Button/ButtonBase.js | 8 +- .../elements/Button/Buttons.stories.js | 10 +-- src/components/elements/Caps.js | 4 +- src/components/elements/Container.js | 17 ++-- src/components/elements/Hide.js | 4 +- src/components/elements/Input/Input.js | 10 ++- src/components/elements/Link/base.js | 7 +- src/components/elements/Link/solid.js | 16 ++-- src/components/elements/Text.js | 10 ++- src/components/elements/Toolbar.js | 10 ++- src/components/patterns/Footer/Footer.js | 90 +++++++++---------- src/components/patterns/Layout.js | 9 +- src/components/patterns/Toolbar/NavLink.js | 4 +- .../patterns/Toolbar/ToolbarDesktop.js | 64 ++++++------- .../patterns/Toolbar/ToolbarMobile.js | 10 +-- src/helpers/hoc/with-link.js | 7 +- src/theme/index.js | 2 +- 18 files changed, 147 insertions(+), 139 deletions(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index f3664684f..a8b84bc0f 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,7 +1,7 @@ import { LocationProvider } from '@gatsbyjs/reach-router' import { ThemeProvider } from 'styled-components' import Flex from 'components/elements/Flex' -import themeSpec, { themeCss } from 'theme' +import themeSpec, { theme } from 'theme' import React from 'react' import '@storybook/addon-console' @@ -26,7 +26,7 @@ export const decorators = [ export const getColorVariant = propName => props => getColor(props, propName) -const Button = styled(Text)( +const Button = styled(Text).withConfig({ + shouldForwardProp: prop => !['variant'].includes(prop) +})( props => { return { transition: `background-color ${transition.medium}, color ${transition.medium}, box-shadow ${transition.medium}`, @@ -28,7 +30,7 @@ const Button = styled(Text)( boxShadow: props.variant === 'white' ? '0 0 0 1px black' : undefined } }, - themeCss({ + theme({ fontFamily: 'sans', fontSize: 1, fontWeight: 'bold', diff --git a/src/components/elements/Button/Buttons.stories.js b/src/components/elements/Button/Buttons.stories.js index ca0852686..e608aaa7c 100644 --- a/src/components/elements/Button/Buttons.stories.js +++ b/src/components/elements/Button/Buttons.stories.js @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { storiesOf } from '@storybook/react' import { Caps, Flex, Button } from 'components/elements' -import { themeCss } from 'theme' +import { theme } from 'theme' import { Story } from 'story' @@ -32,11 +32,11 @@ const BuyButton = ({ children, loading: initialLoading, ...props }) => { {variants.map((variant, index) => ( 0 ? 4 : 0 })} key={variant}> - {states.map(state => { - return createElement( + {states.map(state => + createElement( BuyButton, { key: state, @@ -87,7 +86,7 @@ storiesOf('Elements', module).add('Button', () => ( }, 'BUY' ) - })} + )} ))} diff --git a/src/components/elements/Card/Card.stories.js b/src/components/elements/Card/Card.stories.js index 9c3aa9822..82169e004 100644 --- a/src/components/elements/Card/Card.stories.js +++ b/src/components/elements/Card/Card.stories.js @@ -1,7 +1,8 @@ -import React from 'react' -import { storiesOf } from '@storybook/react' import { Card, Box, Flex } from 'components/elements' +import { storiesOf } from '@storybook/react' import { Story } from 'story' +import { theme } from 'theme' +import React from 'react' const RATIO = [0.7, 0.7, 0.7, 0.7] @@ -12,11 +13,11 @@ import { Card, Box, Flex } from 'components/elements' export default () => ( - - - - - + + + + + )` @@ -24,11 +25,11 @@ const CardStory = () => { return ( - - - - - + + + + + ) diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index ebba9f0b8..32c6dbca8 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -45,50 +45,43 @@ const generateHighlighLines = linesRange => { }) } -const getLanguage = (className, { language }) => { - if (language) return language - const languageFromClassName = className.split('-')[1] - if (languageFromClassName) return languageFromClassName.split('{')[0] - return 'js' -} - const getClassName = ({ className, metastring = '' }) => className ? className + metastring : '' const CustomSyntaxHighlighter = styled(SyntaxHighlighter)` ${hideScrollbar}; - ${props => codeTheme[props.$theme]}; - ${({ $highlightLines, $theme }) => { - const isLight = $theme === 'light' + ${props => codeTheme[props.isDark]}; + ${({ highlightLines, isDark }) => { return ` - ${generateHighlighLines($highlightLines)} { + ${generateHighlighLines(highlightLines)} { display: block; - background: ${cx(isLight ? 'black05' : 'whitek05')}; + background: ${cx(isDark ? 'whitek05' : 'black05')}; border-radius: ${radii[2]}; } ` }} ` -const TerminalTextWrapper = styled.div` +const TerminalTextWrapper = styled('div')` ${wordBreak}; width: 100%; + font-size: 14px; ` const CodeEditor = ({ children, interactive: runkitProps, showLineNumbers, - theme, + isDark, title, ...props }) => { const className = getClassName(props) const highlightLines = getLines(className) - const language = toAlias(getLanguage(className, props)) + const language = toAlias(props.language) const pretty = get(prettier, language, identity) const text = pretty(template(children)).trim() - const id = `codeditor-${hash(children)}-${theme}` + const id = `codeditor-${hash(children)}-${isDark ? 'dark' : 'light'}` const isInteractive = runkitProps !== false && Runkit.isSupported({ language, text }) @@ -98,7 +91,7 @@ const CodeEditor = ({ const TerminalComponent = ( ( - - - {['Interactive', 'Non Interactive']} - - - - - + + {""} @@ -135,8 +130,8 @@ storiesOf('Elements', module).add('CodeEditor', () => ( - - + + {""} @@ -144,15 +139,15 @@ storiesOf('Elements', module).add('CodeEditor', () => ( - - - {""} + + + {""} {bashCode} diff --git a/src/components/elements/CodeEditor/theme.js b/src/components/elements/CodeEditor/theme.js index 3509ec143..856463e09 100644 --- a/src/components/elements/CodeEditor/theme.js +++ b/src/components/elements/CodeEditor/theme.js @@ -5,8 +5,8 @@ const base = ({ background, primary, secondary }) => css` margin: 0; code { font-family: ${fonts.mono}; - font-size ${fontSizes[0]}; - line-height ${lineHeights[2]}; + font-size: ${fontSizes[0]}; + line-height: ${lineHeights[2]}; direction: ltr; text-align: left; white-space: pre; @@ -51,8 +51,8 @@ const theme = { const codeTheme = { theme, - light: base(theme.light), - dark: base(theme.dark) + false: base(theme.light), + true: base(theme.dark) } export default codeTheme diff --git a/src/components/elements/Color/Color.js b/src/components/elements/Color/Color.js index f886e99e8..97570a62f 100644 --- a/src/components/elements/Color/Color.js +++ b/src/components/elements/Color/Color.js @@ -1,19 +1,23 @@ -import React from 'react' import styled from 'styled-components' +import { theme } from 'theme' import Text from '../Text' +import React from 'react' -const Colored = styled(Text)`` +const Colored = styled(Text)( + theme({ + border: 1, + borderColor: 'gray7', + borderRadius: '3px', + display: 'inline-block', + width: '13px', + height: '13px', + mb: '-1px', + mr: '2px' + }) +) Colored.defaultProps = { - as: 'span', - border: 1, - borderColor: 'gray7', - borderRadius: '3px', - display: 'inline-block', - width: '13px', - height: '13px', - mb: '-1px', - mr: '2px' + as: 'span' } const Color = ({ children, ...props }) => ( diff --git a/src/components/elements/Color/Color.stories.js b/src/components/elements/Color/Color.stories.js index f9d731a0d..5ecdba30e 100644 --- a/src/components/elements/Color/Color.stories.js +++ b/src/components/elements/Color/Color.stories.js @@ -1,7 +1,7 @@ -import React from 'react' import { storiesOf } from '@storybook/react' import { Text, Color } from 'components/elements' import { Story } from 'story' +import React from 'react' const code = ` import { Color, Text } from 'components/elements' diff --git a/src/components/elements/Dot/Dot.js b/src/components/elements/Dot/Dot.js index 8441372c1..d27ffdaaa 100644 --- a/src/components/elements/Dot/Dot.js +++ b/src/components/elements/Dot/Dot.js @@ -15,8 +15,8 @@ Dot.defaultProps = { as: 'span' } -const createDot = color => props => - ( +const createDot = color => { + const ColoredDot = props => ( props => /> ) + return ColoredDot +} + const DotSuccess = createDot(colors.teal3) const DotError = createDot(colors.red6) const DotWarning = createDot(colors.yellow6) diff --git a/src/components/elements/Dot/Dot.stories.js b/src/components/elements/Dot/Dot.stories.js index 7990f22f0..085fe5de4 100644 --- a/src/components/elements/Dot/Dot.stories.js +++ b/src/components/elements/Dot/Dot.stories.js @@ -2,6 +2,7 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { Dot, Box } from 'components/elements' import { Story } from 'story' +import { theme } from 'theme' const storyName = 'Dot' @@ -19,9 +20,9 @@ export default () => ( const DotStory = () => { return ( - - - + + + diff --git a/src/components/elements/Iframe/Iframe.stories.js b/src/components/elements/Iframe/Iframe.stories.js index 250cdea6a..a3074dabe 100644 --- a/src/components/elements/Iframe/Iframe.stories.js +++ b/src/components/elements/Iframe/Iframe.stories.js @@ -1,7 +1,8 @@ -import React from 'react' +import { Flex, Box, CodeEditor, Iframe } from 'components/elements' import { storiesOf } from '@storybook/react' import { Story } from 'story' -import { Flex, Box, CodeEditor, Iframe } from 'components/elements' +import { theme } from 'theme' +import React from 'react' const code = ` import { Iframe } from 'components/elements' @@ -26,7 +27,7 @@ storiesOf('Elements', module).add('Iframe', () => ( src='https://www.youtube.com/embed/9P6rdqiybaw?feature=oembed' /> - +
diff --git a/src/components/elements/Image/Image.stories.js b/src/components/elements/Image/Image.stories.js index bf0762fa4..6b8c32d52 100644 --- a/src/components/elements/Image/Image.stories.js +++ b/src/components/elements/Image/Image.stories.js @@ -6,8 +6,7 @@ import { Image, Flex } from 'components/elements' const storyName = 'Image' -const imageUrl = - 'http://www.effigis.com/wp-content/uploads/2015/02/DigitalGlobe_WorldView1_50cm_8bit_BW_DRA_Bangkok_Thailand_2009JAN06_8bits_sub_r_1.jpg' +const imageUrl = 'https://cdn.microlink.io/file-examples/sample-big.jpg' const code = ` import { Image } from 'components/elements' @@ -23,8 +22,10 @@ const ImageStory = () => { diff --git a/src/components/elements/Input/Input.stories.js b/src/components/elements/Input/Input.stories.js index a9fd469e7..e1d31e3aa 100644 --- a/src/components/elements/Input/Input.stories.js +++ b/src/components/elements/Input/Input.stories.js @@ -1,19 +1,27 @@ import { storiesOf } from '@storybook/react' import { serializeFmt } from 'helpers/prettier' import { Input, InputIcon } from 'components/elements' +import { theme } from 'theme' import { Story } from 'story' import React from 'react' const createCode = (props = '') => ` -import { Select } from 'components/elements' + import { Select } from 'components/elements' -export default () => (
) -` + export default () => (
) + ` const createStory = (name, props) => (
- } {...props} /> + } + css={theme({ + width: '9rem', + fontSize: 1 + })} + {...props} + />
) @@ -31,16 +39,12 @@ storiesOf('Elements', module).add('Input', () => ( <> {createStory('Input', { type: 'email', - placeholder: 'you@domain.com', - width: '9rem', - fontSize: 1 + placeholder: 'you@domain.com' })} {createStory('Input required', { type: 'email', placeholder: 'you@domain.com', - width: '9rem', - fontSize: 1, required: true })} @@ -48,9 +52,7 @@ storiesOf('Elements', module).add('Input', () => ( type: 'email', id: 'input', placeholder: 'you@domain.com', - suggestions: [{ value: 'you@gmail.com' }, { value: 'you@hotmail.com' }], - width: '9rem', - fontSize: 1 + suggestions: [{ value: 'you@gmail.com' }, { value: 'you@hotmail.com' }] })} )) diff --git a/src/components/elements/Link/Links.stories.js b/src/components/elements/Link/Links.stories.js index b6e22d314..5475ef3d1 100644 --- a/src/components/elements/Link/Links.stories.js +++ b/src/components/elements/Link/Links.stories.js @@ -1,7 +1,8 @@ -import React from 'react' -import { storiesOf } from '@storybook/react' import { Box, Link, LinkSolid } from 'components/elements' +import React, { createElement } from 'react' +import { storiesOf } from '@storybook/react' import { Story } from 'story' +import { theme } from 'theme' const buttons = [ { name: 'Link', Component: Link }, @@ -23,15 +24,24 @@ storiesOf('Elements', module).add('Link', () => ( {buttons.map(({ name, Component }) => ( {states.map(state => ( - - - {`${name}${state ? `:${state}` : ''}`} - + + {createElement( + Component, + { + key: `${name}:${state}`, + [`data-${state}`]: true, + disabled: state === 'disabled', + loading: state === 'loading' + }, + `${name}${state ? `:${state}` : ''}` + )} ))} diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js index f2bad77cd..5fda1e537 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js @@ -1,7 +1,7 @@ import { useLocalStorage } from 'components/hook' import React, { useEffect, useMemo } from 'react' import styled from 'styled-components' -import { cx } from 'theme' +import { theme } from 'theme' import CodeEditor from '../CodeEditor/CodeEditor' import CodeCopy from '../Codecopy' @@ -11,10 +11,6 @@ import Box from '../Box' export const SelectLanguage = ({ isDark, value, onClick, ...props }) => ( { - const id = isDark ? 'white' : 'black' - return cx(isActive ? id : `${id}50`) - }} value={value} onClick={event => { const label = event.target.textContent @@ -42,15 +38,17 @@ const ActionComponent = ({ return ( <> - + diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.stories.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.stories.js index 4eddae4c1..e5b350f8b 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.stories.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.stories.js @@ -1,8 +1,9 @@ import { MultiCodeEditor, Box, Text } from 'components/elements' import { storiesOf } from '@storybook/react' +import { mqlCode } from 'helpers' +import { theme } from 'theme' import { Story } from 'story' import React from 'react' -import { mqlCode } from 'helpers' const languages = mqlCode('https://example.com', { data: { @@ -19,16 +20,16 @@ const languages = mqlCode('https://example.com', { storiesOf('Elements', module).add('MultiCodeEditor', () => ( - - + + {''} - - - {""} + + + {''} - + )) diff --git a/src/components/elements/Notification/Notification.js b/src/components/elements/Notification/Notification.js index c8761383c..79046bd7d 100644 --- a/src/components/elements/Notification/Notification.js +++ b/src/components/elements/Notification/Notification.js @@ -1,9 +1,10 @@ import { hideNotification, showNotification } from 'components/keyframes' import React, { createElement, useState } from 'react' import FeatherIcon from 'components/icons/Feather' -import { Text, Flex } from 'components/elements' +import { theme, transition } from 'theme' import styled from 'styled-components' -import { transition } from 'theme' +import Text from '../Text' +import Flex from '../Flex' const Wrapper = styled(Flex)` bottom: 0; @@ -21,45 +22,50 @@ const Wrapper = styled(Flex)` const Notification = ({ icon, iconColor, children, ...props }) => { const [isHidden, setIsHidden] = useState(false) const [isClosed, setIsClosed] = useState(false) - if (isClosed) return null return ( - - - - + + + {children} { setIsHidden(true) setTimeout(() => setIsClosed(true), 300) }} /> - + ) } diff --git a/src/components/elements/Notification/Notification.stories.js b/src/components/elements/Notification/Notification.stories.js index 4fbd57e8c..ba775c6e8 100644 --- a/src/components/elements/Notification/Notification.stories.js +++ b/src/components/elements/Notification/Notification.stories.js @@ -1,3 +1,8 @@ +import { storiesOf } from '@storybook/react' +import React, { useState } from 'react' +import { Story } from 'story' +import { theme } from 'theme' + import { Caps, Choose, @@ -6,9 +11,6 @@ import { Box, Flex } from 'components/elements' -import { storiesOf } from '@storybook/react' -import React, { useState } from 'react' -import { Story } from 'story' const storyName = 'Notification' @@ -53,17 +55,17 @@ const NotificationStory = () => { return ( - + - + - + diff --git a/src/components/elements/Placeholder/Placeholder.stories.js b/src/components/elements/Placeholder/Placeholder.stories.js index 7ed8661a6..28b6ef358 100644 --- a/src/components/elements/Placeholder/Placeholder.stories.js +++ b/src/components/elements/Placeholder/Placeholder.stories.js @@ -1,4 +1,5 @@ import { storiesOf } from '@storybook/react' +import { theme } from 'theme' import { Story } from 'story' import React from 'react' @@ -18,8 +19,13 @@ export default () => ( const PlaceholderStory = () => { return ( - - + + ) diff --git a/src/components/elements/Runkit/Runkit.js b/src/components/elements/Runkit/Runkit.js index ff44665a0..39692fa2f 100644 --- a/src/components/elements/Runkit/Runkit.js +++ b/src/components/elements/Runkit/Runkit.js @@ -4,12 +4,7 @@ import { Script } from 'gatsby' const NODE_VERSION = '18' -const THEME = { - light: 'untilted-3iiuludkfm6r', - dark: 'untilted-0iw2lny2mmwa' -} - -const Runkit = ({ onLoad, placeholderComponent, theme, ...opts }) => { +const Runkit = ({ onLoad, placeholderComponent, isDark, ...opts }) => { if (!placeholderComponent.props.id) { throw new Error('Runkit placeholder must to have an id.') } @@ -27,7 +22,7 @@ const Runkit = ({ onLoad, placeholderComponent, theme, ...opts }) => { evaluateOnLoad: false, element, nodeVersion: NODE_VERSION, - theme: THEME[theme], + theme: isDark ? 'untilted-0iw2lny2mmwa' : 'untilted-3iiuludkfm6r', gutterStyle: 'outside', tabSize: 2, onLoad: () => onLoad(element), @@ -47,10 +42,13 @@ const Runkit = ({ onLoad, placeholderComponent, theme, ...opts }) => { } Runkit.defaultProps = { - theme: 'light' + isDark: false } -Runkit.isSupported = ({ language, text }) => - language === 'js' && !text.includes('import') && !text.startsWith('{') +Runkit.isSupported = ({ language, text }) => { + const isSupported = + language === 'js' && !text.includes('import') && !text.startsWith('{') + return isSupported +} export default Runkit diff --git a/src/components/elements/Runkit/Runkit.stories.js b/src/components/elements/Runkit/Runkit.stories.js index 1534d2c19..2ce1a74fa 100644 --- a/src/components/elements/Runkit/Runkit.stories.js +++ b/src/components/elements/Runkit/Runkit.stories.js @@ -1,6 +1,7 @@ -import { CodeEditor } from 'components/elements' +import { CodeEditor, Box } from 'components/elements' import { storiesOf } from '@storybook/react' import { Story } from 'story' +import { theme } from 'theme' import React from 'react' const jsCode = ` @@ -13,11 +14,8 @@ console.log(data) const code = ` <> - - ${jsCode - .split('\n') - .filter(Boolean) - .join('\n')} + + ${jsCode.split('\n').filter(Boolean).join('\n')} @@ -25,7 +23,11 @@ const code = ` storiesOf('Elements', module).add('Runkit', () => ( - + + {jsCode} + + + {jsCode} diff --git a/src/components/elements/Select/Select.js b/src/components/elements/Select/Select.js index a1ad8d213..2be751f12 100644 --- a/src/components/elements/Select/Select.js +++ b/src/components/elements/Select/Select.js @@ -1,51 +1,54 @@ import styled from 'styled-components' +import { theme, transition, fonts } from 'theme' import Box from '../Box' -import { transition, colors, fonts } from 'theme' - const arrow = encodeURI( "data:image/svg+xml;utf8, " ) const ARROW_SIZE = '7px' -const Select = styled(Box)({ - fontFamily: fonts.sans, - cursor: 'pointer', - transition: `border-color ${transition.medium}`, - fontSize: 'inherit', - lineHeight: 'inherit', - appearance: 'none', - border: `1px solid ${colors.black20}`, - backgroundImage: `url("${arrow}")`, - backgroundPosition: `calc(100% - ${ARROW_SIZE}) center`, - backgroundRepeat: 'no-repeat', - backgroundSize: `${ARROW_SIZE} ${ARROW_SIZE}`, - '&:disabled': { - opacity: 1 / 4 - }, - '&:focus': { - outline: 'none', - border: `1px solid ${colors.black80}` +const Select = styled(Box)( + { + background: 'transparent', + color: 'inherit', + width: 'inherit', + cursor: 'pointer', + transition: `border-color ${transition.medium}`, + fontSize: 'inherit', + lineHeight: 'inherit', + appearance: 'none', + backgroundImage: `url("${arrow}")`, + backgroundPosition: `calc(100% - ${ARROW_SIZE}) center`, + backgroundRepeat: 'no-repeat', + backgroundSize: `${ARROW_SIZE} ${ARROW_SIZE}` }, - '&:hover': { - border: `1px solid ${colors.black80}` - } -}) + theme({ + pl: '8px', + pr: '4px', + m: 0, + border: 1, + borderRadius: 2, + fontFamily: fonts.sans, + borderColor: 'black20', + _hover: { + '&:hover': { + borderColor: 'black80' + } + }, + _focus: { + outline: 'none', + borderColor: 'black80' + }, + _disabled: { + opacity: 1 / 4 + } + }) +) Select.defaultProps = { - as: 'select', - pl: '8px', - pr: '4px', - mt: 0, - mb: 0, - mr: 0, - ml: 0, - width: 'inherit', - borderRadius: 2, - color: 'inherit', - bg: 'transparent' + as: 'select' } export default Select diff --git a/src/components/elements/Select/Select.stories.js b/src/components/elements/Select/Select.stories.js index 30762e703..4c39a2b22 100644 --- a/src/components/elements/Select/Select.stories.js +++ b/src/components/elements/Select/Select.stories.js @@ -1,7 +1,8 @@ -import React, { useState } from 'react' -import { storiesOf } from '@storybook/react' import { Select, Text } from 'components/elements' +import { storiesOf } from '@storybook/react' +import React, { useState } from 'react' import { Story } from 'story' +import { theme } from 'theme' const options = ['Markup', 'CSS', 'C-like', 'JavaScript'] @@ -20,10 +21,12 @@ const MySelect = ({ ...props }) => { return ( @@ -42,7 +45,9 @@ const MySelectWithDefault = ({ placeholder, ...props }) => { setState(language) }} value={placeholder} - color={lang === placeholder ? 'black60' : 'inherit'} + css={theme({ + color: lang === placeholder ? 'black60' : 'inherit' + })} {...props} > {[ @@ -54,10 +59,12 @@ const MySelectWithDefault = ({ placeholder, ...props }) => { return ( @@ -89,15 +96,29 @@ export default () => ( storiesOf('Elements', module).add('Select', () => ( - - + + diff --git a/src/components/elements/Tabs.js b/src/components/elements/Tabs.js index ad0ee7950..f29720705 100644 --- a/src/components/elements/Tabs.js +++ b/src/components/elements/Tabs.js @@ -1,5 +1,5 @@ import styled from 'styled-components' -import { space } from 'theme' +import { cx, theme } from 'theme' import is from 'styled-is' import React from 'react' @@ -7,15 +7,20 @@ import Text from './Text' import Flex from './Flex' import Box from './Box' +const getColor = ({ isActive, isDark }) => { + const id = isDark ? 'white' : 'red' + return cx(isActive ? id : `${id}50`) +} + const StyledTab = styled(Box)` list-style: none; width: 100%; text-align: center; cursor: pointer; margin-right: 12px; - padding-bottom: ${space[2]}; - + ${theme({ pb: 2 })} ${is('active')` + color: ${props => getColor(props)}; border-bottom: 1px solid ${props => props.background}; `}; ` @@ -23,8 +28,8 @@ const StyledTab = styled(Box)` const Tabs = ({ children, ...props }) => ( ( {children.map(lang => { const isActive = lang === props.value return ( - - + + {lang} diff --git a/src/components/elements/Terminal/Terminal.js b/src/components/elements/Terminal/Terminal.js index 683534b2e..2a3404e1c 100644 --- a/src/components/elements/Terminal/Terminal.js +++ b/src/components/elements/Terminal/Terminal.js @@ -4,17 +4,7 @@ import { blink } from 'components/keyframes' import { wordBreak } from 'helpers/style' import React from 'react' -import { - speed, - toMs, - timings, - cx, - colors, - radii, - borders, - fonts, - fontWeights -} from 'theme' +import { theme, speed, toMs, timings, cx, colors, radii, borders } from 'theme' import CodeCopy from '../Codecopy' import Text from '../Text' @@ -30,10 +20,7 @@ export const TerminalWindow = styled(Box)` ` export const { width: TERMINAL_WIDTH, height: TERMINAL_HEIGHT } = aspectRatio([ - 0.41, - 0.48, - 0.68, - 0.68 + 0.41, 0.48, 0.68, 0.68 ]) const createBgAnimation = color => keyframes` @@ -147,17 +134,20 @@ const TerminalTitleWrapper = styled('div')` export const TerminalTitle = ({ isDark, children }) => ( - + {children} ) const TerminalText = styled('div')` - font-weight: ${fontWeights.normal}; padding: 0 8px 16px 8px; overflow: visible; - font-family: ${fonts.mono}; font-size: 13px; line-height: 20px; border-bottom-right-radius: 4px; @@ -172,6 +162,11 @@ const TerminalText = styled('div')` > div { width: 100%; } + + ${theme({ + fontWeight: 'normal', + fontFamily: 'mono' + })} ` const blinkCursorStyle = css` @@ -209,13 +204,11 @@ const TerminalProvider = ({ text, children, loading, - theme, + isDark, title, header, ...props }) => { - const isDark = theme === 'dark' - return ( @@ -248,7 +241,7 @@ Terminal.defaultProps = { blinkCursor: true, loading: false, shellSymbol: false, - theme: 'light', + isDark: false, width: TERMINAL_WIDTH } diff --git a/src/components/elements/Terminal/Terminal.stories.js b/src/components/elements/Terminal/Terminal.stories.js index d30a5dd27..11330efab 100644 --- a/src/components/elements/Terminal/Terminal.stories.js +++ b/src/components/elements/Terminal/Terminal.stories.js @@ -2,7 +2,7 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { Image, Box, Text, Terminal } from 'components/elements' import styled from 'styled-components' -import { colors } from 'theme' +import { cx, theme } from 'theme' import { Story } from 'story' const cmd = 'curl https://api.microlink.io?url=https://kikobeats.com' @@ -16,80 +16,75 @@ export default () => ( ` const SpanKey = styled.span` - color: ${colors.green5}; + color: ${cx('green5')}; ` const Span = styled.span` - color: ${colors.gray8}; + color: ${cx('gray8')}; ` const SpanLabel = styled.span` - background: ${colors.green5}; + background: ${cx('green5')}; color: white; padding: 0 8px; text-transform: uppercase; ` -const cliCode = ( - <> -
- npx @microlink/cli - https://kikobeats.com?&screenshot&embed=screenshot.url&border=false&force - - kikobeats.com screenshot - - SUCCESS 57.9 kB in 13830.018ms - - - - {' '} - uri - - https://api.microlink.io?url=https://kikobeats.com?&screenshot&embed=screenshot.url - - - - cache - MISS - - - {' '} - mode - prerender (4654.865ms) - - - -) - storiesOf('Elements', module).add('Terminal', () => ( - + {''} - {cmd} + {cmd} - + {""} - + {cmd} - - {""} + + {''} - + {cmd} - + {''} - {cliCode} + + + npx @microlink/cli + https://kikobeats.com?&screenshot&embed=screenshot.url&border=false&force + + kikobeats.com screenshot + + SUCCESS 57.9 kB in 13830.018ms + + + + {' '} + uri + + https://api.microlink.io?url=https://kikobeats.com?&screenshot&embed=screenshot.url + + + + cache + MISS + + + {' '} + mode + prerender (4654.865ms) + + + )) diff --git a/src/components/elements/Toggle/Toggle.js b/src/components/elements/Toggle/Toggle.js index b7b3f066b..bfb263cf0 100644 --- a/src/components/elements/Toggle/Toggle.js +++ b/src/components/elements/Toggle/Toggle.js @@ -2,30 +2,29 @@ import { Text, Flex, Box, Caps } from 'components/elements' import React, { useState } from 'react' import styled from 'styled-components' import { noop } from 'helpers' +import { theme } from 'theme' import Button from '../Button/Button' const ButtonToggle = styled(Button)` - box-shadow: none; - - &:hover { - cursor: ${props => (props.active ? 'auto' : 'pointer')}; - } + ${theme({ + bg: 'transparent', + py: 0, + px: 0, + borderRadius: 0, + _hover: { + cursor: props => (props.active ? 'auto' : 'pointer'), + boxShadow: 'none' + } + })} ` -ButtonToggle.defaultProps = { - bg: 'transparent', - py: 0, - px: 0, - borderRadius: 0 -} - function Toggle ({ onChange, children, defaultValue, ...props }) { const [active, setActive] = useState(defaultValue || children[0]) return ( - - + + {children.map((value, index) => { const isLast = index + 1 === children.length const isActive = active === value @@ -41,16 +40,20 @@ function Toggle ({ onChange, children, defaultValue, ...props }) { {value} diff --git a/src/components/elements/Tooltip/Tooltip.js b/src/components/elements/Tooltip/Tooltip.js index 8d695fb46..a897cc825 100644 --- a/src/components/elements/Tooltip/Tooltip.js +++ b/src/components/elements/Tooltip/Tooltip.js @@ -1,9 +1,10 @@ -import { Box, Text } from 'components/elements' +import { theme, space, radii, colors, shadows, speed } from 'theme' import styled from 'styled-components' import Tippy from '@tippyjs/react' import React from 'react' -import { space, radii, colors, shadows, speed } from 'theme' +import Text from '../Text' +import Box from '../Box' /* https://atomiks.github.io/tippyjs/v6/all-props/ */ const TOOLTIPS_OPTS = { @@ -61,7 +62,12 @@ const TippyContainer = styled(Box)` cursor: help; ` -const TooltipContent = props => +const TooltipContent = styled(Text)` + ${theme({ fontSize: 0 })} + > * { + font-size: inherit; + } +` const Tooltip = ({ content, diff --git a/src/components/elements/Tooltip/Tooltip.stories.js b/src/components/elements/Tooltip/Tooltip.stories.js index 8b3a44618..9a80be756 100644 --- a/src/components/elements/Tooltip/Tooltip.stories.js +++ b/src/components/elements/Tooltip/Tooltip.stories.js @@ -1,6 +1,7 @@ import { Box, Flex, Text } from 'components/elements' import { ProBadge } from 'components/markdown' import { storiesOf } from '@storybook/react' +import { theme } from 'theme' import { Story } from 'story' import React from 'react' @@ -34,8 +35,8 @@ const tooltipsOpts = { storiesOf('Elements', module).add('Tooltip', () => ( - - + + This is a feature. diff --git a/src/components/elements/Unavatar/Unavatar.js b/src/components/elements/Unavatar/Unavatar.js index 6f2c7d04b..cb7505f61 100644 --- a/src/components/elements/Unavatar/Unavatar.js +++ b/src/components/elements/Unavatar/Unavatar.js @@ -1,15 +1,15 @@ import React, { createElement } from 'react' import { Image } from 'components/elements' import styled from 'styled-components' +import { theme } from 'theme' const StyledImage = styled(Image)` max-width: inherit; -` - -StyledImage.defaultProps = { - borderRadius: 2, height: '100%' -} + ${theme({ + borderRadius: 2 + })}; +` const Unavatar = ({ query, ...props }) => { return ( diff --git a/src/components/elements/Video/Video.stories.js b/src/components/elements/Video/Video.stories.js index b669aac29..7721d9f2b 100644 --- a/src/components/elements/Video/Video.stories.js +++ b/src/components/elements/Video/Video.stories.js @@ -19,8 +19,8 @@ export default () => ( const VideoStory = () => { return ( - - ) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index d94c03a76..88c89f407 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -1,5 +1,5 @@ import { withContainer, withTitle, withSlug } from 'helpers/hoc' -import { space, fontSizes, colors } from 'theme' +import { space, fontSizes, colors, theme } from 'theme' import styled, { css } from 'styled-components' import { wordBreak } from 'helpers/style' import Mdx from 'mdx-scoped-runtime' @@ -36,12 +36,14 @@ const { Container, CONTAINER_SPACE } = withContainer const ProBadge = ({ top, ...props }) => ( You have to buy{' '} - + pro {' '} plan to use this feature. diff --git a/src/components/patterns/DotsBackground/DotsBackground.js b/src/components/patterns/DotsBackground/DotsBackground.js index 88d7c1154..badadf6fa 100644 --- a/src/components/patterns/DotsBackground/DotsBackground.js +++ b/src/components/patterns/DotsBackground/DotsBackground.js @@ -1,7 +1,6 @@ import styled, { css } from 'styled-components' import { slide } from 'components/keyframes' import { Box } from 'components/elements' -import { defaultProps } from 'theme' import is from 'styled-is' const darkStyle = css` diff --git a/src/story.js b/src/story.js index ad6f0c54f..d663e4b2a 100644 --- a/src/story.js +++ b/src/story.js @@ -6,7 +6,6 @@ export function Story ({ name, children, code, ...props }) { return ( <> {code && ( - + {code} )} - + ) } From da894a388ae5ff4b4c48f2f4083e176ca01dda1c Mon Sep 17 00:00:00 2001 From: Brad Adams Date: Sun, 12 May 2024 23:29:39 +0200 Subject: [PATCH 08/57] fix: footer attributes (#1709) --- src/components/patterns/Footer/Footer.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/patterns/Footer/Footer.js b/src/components/patterns/Footer/Footer.js index a01366b33..2a494ae41 100644 --- a/src/components/patterns/Footer/Footer.js +++ b/src/components/patterns/Footer/Footer.js @@ -141,15 +141,15 @@ const Footer = ({ isDark, ...props }) => { {[ { children: 'API', href: '/docs/api/getting-started/overview' }, { children: 'Blog', href: '/blog' }, - { children: 'Chat', href: '/community' }, + { children: 'Community', href: '/community' }, { children: 'Status', href: '/status' } ].map(({ href, children }) => ( { key={href} isDark={isDark} href={href} - data-event-name='Footer' - data-event-location={children} + data-event-name={children} + data-event-location='Footer' css={theme({ fontSize: [0, 0, 0, 1], mr: [2, 2, 2, 0], @@ -306,8 +306,8 @@ const Footer = ({ isDark, ...props }) => { key={href} isDark={isDark} href={href} - data-event-name='Footer' - data-event-location={children} + data-event-name={children} + data-event-location='Footer' css={theme({ fontWeight: 'normal', mr: 2, From f9f243d1fd79000bca580dd219e7e0b17899bae8 Mon Sep 17 00:00:00 2001 From: Brad Adams Date: Wed, 15 May 2024 20:55:08 +0200 Subject: [PATCH 09/57] migrate styled-system (components & product pages) (#1712) * docs(fix): prerender auto by default * fix: toolbar * fix: `Select` story * feat: update `patterns` components * fix: `PricingTable` styles * fix: `Footer` bottom padding * feat: update `home` * fix: `home` features title text-align * feat: update `markdown` components * feat: cleanup home + Mitigate all warnings about props being passed to dom * feat: migrate `formats` page * feat: migrate `insights` page * feat: migrate `logo` page * feat: migrate `meta` page * fix: invalid bg color * feat: migrate `pdf` page * feat: migrate `screenshot` page * feat: migrate `sdk` page * build(deps): bump pnpm/action-setup from 3 to 4 (#1707) Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 3 to 4. - [Release notes](https://github.com/pnpm/action-setup/releases) - [Commits](https://github.com/pnpm/action-setup/compare/v3...v4) --- updated-dependencies: - dependency-name: pnpm/action-setup dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build: tweaks * fix: use cdn.microlink.io * build: lock react-codecopy * Update src/components/elements/Container.js * Update src/components/elements/PriceMonthly.js * refactor: mx shortcut * refactor: padding shortcut --------- Signed-off-by: dependabot[bot] Co-authored-by: Kiko Beats Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pull_request.yml | 6 +- .npmrc | 2 +- package.json | 9 +- scripts/fetch-data/providers/fetch-formats.js | 3 +- .../BackgroundSlider.stories.js | 2 +- src/components/elements/Button/Button.js | 4 +- src/components/elements/Card/Card.js | 45 +- .../elements/CodeEditor/CodeEditor.js | 23 +- src/components/elements/Codecopy.js | 10 +- src/components/elements/Container.js | 4 +- src/components/elements/Highlight.js | 4 +- src/components/elements/Iframe/Iframe.js | 4 +- src/components/elements/Input/Input.js | 3 +- src/components/elements/Label.js | 12 +- src/components/elements/Link/base.js | 1 + src/components/elements/Link/index.js | 8 - .../MultiCodeEditor/MultiCodeEditor.js | 6 +- src/components/elements/PriceMonthly.js | 8 +- src/components/elements/PricePicker.js | 39 +- .../elements/Select/Select.stories.js | 8 +- src/components/elements/Tabs.js | 4 +- src/components/elements/Terminal/Terminal.js | 33 +- src/components/elements/Text.js | 4 +- src/components/elements/Toggle/Toggle.js | 3 +- src/components/elements/Toolbar.js | 2 +- src/components/elements/Unavatar/Unavatar.js | 4 +- src/components/icons/Feather.js | 14 +- src/components/markdown/index.js | 265 +++++---- src/components/pages/home/analytics.js | 101 ++-- src/components/pages/home/faqs.js | 31 +- src/components/pages/home/hero.js | 178 +++--- src/components/pages/home/pricing.js | 21 +- .../patterns/Announcement/Announcement.js | 3 +- src/components/patterns/ArrowLink.js | 2 - src/components/patterns/Aside/Aside.js | 22 +- src/components/patterns/Aside/AsideBase.js | 50 +- src/components/patterns/Average/Average.js | 20 +- src/components/patterns/Block/Block.js | 16 +- src/components/patterns/Chat/Chat.js | 10 +- src/components/patterns/Checkout.js | 3 +- .../patterns/CubeBackground/CubeBackground.js | 12 +- .../patterns/DemoLinks/DemoLinks.js | 7 +- src/components/patterns/Faq/Faq.js | 51 +- src/components/patterns/Features/Features.js | 23 +- src/components/patterns/Footer/Footer.js | 4 +- src/components/patterns/Grid.js | 34 +- src/components/patterns/Layout.js | 7 +- src/components/patterns/List/List.js | 18 +- .../patterns/MQLEditor/MQLEditor.js | 20 +- .../patterns/PricingTable/PricingTable.js | 141 +++-- .../patterns/Toolbar/ToolbarDesktop.js | 2 +- src/helpers/hoc/with-container.js | 11 +- src/helpers/hoc/with-link.js | 12 +- src/helpers/hoc/with-slug.js | 6 +- src/helpers/hoc/with-spinner.js | 2 +- src/helpers/hoc/with-title.js | 8 +- src/pages/docs/api/parameters/prerender.md | 2 +- src/pages/formats.js | 104 ++-- src/pages/index.js | 57 +- src/pages/insights.js | 547 +++++++++++------- src/pages/logo.js | 516 ++++++++++------- src/pages/meta.js | 395 ++++++++----- src/pages/pdf.js | 428 ++++++++------ src/pages/screenshot.js | 446 ++++++++------ src/pages/sdk.js | 147 +++-- 65 files changed, 2314 insertions(+), 1673 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 704f7ab57..0daf5226a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -22,7 +22,7 @@ jobs: with: node-version: lts/* - name: Setup PNPM - uses: pnpm/action-setup@v3 + uses: pnpm/action-setup@v4 with: version: latest run_install: true @@ -41,7 +41,7 @@ jobs: with: node-version: lts/* - name: Setup PNPM - uses: pnpm/action-setup@v3 + uses: pnpm/action-setup@v4 with: version: latest run_install: false @@ -63,7 +63,7 @@ jobs: with: node-version: lts/* - name: Setup PNPM - uses: pnpm/action-setup@v3 + uses: pnpm/action-setup@v4 with: version: latest run_install: false diff --git a/.npmrc b/.npmrc index 448376a8c..67a9f2035 100644 --- a/.npmrc +++ b/.npmrc @@ -1,5 +1,5 @@ audit=false -enable-pre-post-scripts=true + fund=false loglevel=error package-lock=false diff --git a/package.json b/package.json index 624f6ba78..8bc4a5b92 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "prepend-http": "~4.0.0", "prettier": "2", "react": "18", - "react-codecopy": "~5.0.3", + "react-codecopy": "5.0.3", "react-confetti": "~6.1.0", "react-dom": "18", "react-feather": "~2.0.10", @@ -241,7 +241,12 @@ "commitlint": { "extends": [ "@commitlint/config-conventional" - ] + ], + "rules": { + "body-max-line-length": [ + 0 + ] + } }, "nano-staged": { "*.js": [ diff --git a/scripts/fetch-data/providers/fetch-formats.js b/scripts/fetch-data/providers/fetch-formats.js index 69e44cd87..7a38e9990 100644 --- a/scripts/fetch-data/providers/fetch-formats.js +++ b/scripts/fetch-data/providers/fetch-formats.js @@ -9,8 +9,7 @@ const path = require('path') /* We avoid cdn.microlink.io explicity since it runs on top of CloudFlare and the compression removes 'content-length' header */ -const MICROLINK_CDN_URL = - 'https://cdn-e6etw8l60-microlink.vercel.app/file-examples' +const MICROLINK_CDN_URL = 'https://cdn.microlink.io/file-examples' const fileUrls = async () => (await fetch(`${MICROLINK_CDN_URL}/index.json`).then(res => res.json())).map( diff --git a/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js b/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js index d8e5be2db..dc066c396 100644 --- a/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js +++ b/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js @@ -55,7 +55,7 @@ export default () => ( storiesOf('Elements', module).add('BackgroundSlider', () => ( - + {range(30).map(index => ( diff --git a/src/components/elements/Button/Button.js b/src/components/elements/Button/Button.js index de4728811..19f8932fb 100644 --- a/src/components/elements/Button/Button.js +++ b/src/components/elements/Button/Button.js @@ -18,7 +18,9 @@ export const hoverStyle = ({ theme, variant }) => { } } -const Button = styled(Box)` +const Button = styled(Box).withConfig({ + shouldForwardProp: prop => !['variant'].includes(prop) +})` transition: background-color ${transition.medium}, color ${transition.medium}, box-shadow ${transition.medium}; appearance: none; diff --git a/src/components/elements/Card/Card.js b/src/components/elements/Card/Card.js index 2bcf2683b..cd4f8ed78 100644 --- a/src/components/elements/Card/Card.js +++ b/src/components/elements/Card/Card.js @@ -1,6 +1,6 @@ import React from 'react' import styled from 'styled-components' -import { transition, toPx, colors } from 'theme' +import { transition, toPx, colors, theme } from 'theme' import Flex from '../Flex' import Text from '../Text' @@ -24,34 +24,41 @@ const Card = ({ height = ratio.map(n => toPx(BASE_HEIGHT * n)), ...props }) => { - return + return ( + + ) } Card.defaultProps = { - bg: 'white', - border: 1, - borderColor: 'black10', - borderRadius: 3, ratio: [0.55, 0.75, 1, 1] } const CardOption = ({ children, value, ...props }) => ( theme.transition.medium}; - - &:hover { - color: ${({ theme }) => theme.colors.black}; + css={theme({ + color: children === value ? 'black' : 'black60', + fontWeight: children === value ? 'regular' : 'normal', + pt: 3, + pr: 2, + fontSize: 1, + textAlign: 'right', + cursor: children !== value ? 'pointer' : 'default', + transition: `color ${transition.medium}`, + _hover: { + color: 'black' } - `} + })} {...props} > {children} diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index 32c6dbca8..edb54033b 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -4,7 +4,7 @@ import { hideScrollbar, wordBreak } from 'helpers/style' import React, { useState } from 'react' import identity from 'lodash/identity' import styled from 'styled-components' -import { cx, radii } from 'theme' +import { cx, radii, theme } from 'theme' import range from 'lodash/range' import get from 'dlv' @@ -33,7 +33,7 @@ const toAlias = (lang = '') => { } } -const generateHighlighLines = linesRange => { +const generateHighlightLines = linesRange => { if (!linesRange) return const [start, end] = linesRange @@ -50,12 +50,12 @@ const getClassName = ({ className, metastring = '' }) => const CustomSyntaxHighlighter = styled(SyntaxHighlighter)` ${hideScrollbar}; - ${props => codeTheme[props.isDark]}; - ${({ highlightLines, isDark }) => { + ${props => codeTheme[props.$isDark]}; + ${({ $highlightLines, $isDark }) => { return ` - ${generateHighlighLines(highlightLines)} { + ${generateHighlightLines($highlightLines)} { display: block; - background: ${cx(isDark ? 'whitek05' : 'black05')}; + background: ${cx($isDark ? 'white05' : 'black05')}; border-radius: ${radii[2]}; } ` @@ -73,12 +73,13 @@ const CodeEditor = ({ interactive: runkitProps, showLineNumbers, isDark, + language: languageProp, title, ...props }) => { const className = getClassName(props) const highlightLines = getLines(className) - const language = toAlias(props.language) + const language = toAlias(languageProp) const pretty = get(prettier, language, identity) const text = pretty(template(children)).trim() const id = `codeditor-${hash(children)}-${isDark ? 'dark' : 'light'}` @@ -95,13 +96,14 @@ const CodeEditor = ({ id={id} text={text} loading={!isLoaded} + css={theme({ width: TERMINAL_WIDTH })} {...props} > cx(isDark ? 'white50' : 'black20')}; + fill: ${({ $isDark }) => cx($isDark ? 'white50' : 'black20')}; &:hover { - fill: ${({ isDark }) => cx(isDark ? 'white' : 'black')}; + fill: ${({ $isDark }) => cx($isDark ? 'white' : 'black')}; } } ` -const CodeCopy = ({ isDark, ...props }) => ( - - +const CodeCopy = ({ isDark, text }) => ( + + ) diff --git a/src/components/elements/Container.js b/src/components/elements/Container.js index 8025a0543..2d7ce17de 100644 --- a/src/components/elements/Container.js +++ b/src/components/elements/Container.js @@ -8,14 +8,14 @@ const Container = styled(Flex).withConfig({ })` ${theme({ flexDirection: 'column', - ml: 'auto', - mr: 'auto', + mx: 'auto', pt: [5, 5, 6, 6], px: [3, 3, 0, 0] })} ` Container.defaultProps = { + // TODO: can we remove this? px: [3, 3, 0, 0] } diff --git a/src/components/elements/Highlight.js b/src/components/elements/Highlight.js index 49fd1771d..734261112 100644 --- a/src/components/elements/Highlight.js +++ b/src/components/elements/Highlight.js @@ -14,7 +14,7 @@ const highlightCss = css` ` const HighlightBase = styled(Box)` - ${props => props.isHighlight && highlightCss}; + ${props => props.$isHighlight && highlightCss}; ` const Highlight = ({ sx, ...props }) => { @@ -25,7 +25,7 @@ const Highlight = ({ sx, ...props }) => { const isHighlight = previous ? props.children !== previous : false if (isHighlight) setTimeout(forceUpdate, HIGHLIGHT_DURATION) - return + return } export default Highlight diff --git a/src/components/elements/Iframe/Iframe.js b/src/components/elements/Iframe/Iframe.js index e9b107ac4..a45d81c9e 100644 --- a/src/components/elements/Iframe/Iframe.js +++ b/src/components/elements/Iframe/Iframe.js @@ -1,5 +1,6 @@ import React, { createElement, useRef, useEffect, useState } from 'react' import { aspectRatio, noop } from 'helpers' +import { theme } from 'theme' import Placeholder from '../Placeholder/Placeholder' import Flex from '../Flex' @@ -37,8 +38,7 @@ const Iframe = ({ style={isLoading ? { display: 'none' } : undefined} frameBorder='0' target='_parent' - width={width} - height={height} + css={theme({ width, height })} {...props} /> ) diff --git a/src/components/elements/Input/Input.js b/src/components/elements/Input/Input.js index 37956fab0..689e93227 100644 --- a/src/components/elements/Input/Input.js +++ b/src/components/elements/Input/Input.js @@ -13,6 +13,7 @@ const InputBase = styled(Text)( display: 'inline-block', verticalAlign: 'middle', appearance: 'none', + color: 'inherit', '&:focus': { outline: '0' }, @@ -42,7 +43,7 @@ const focusStyle = css` ` const InputWrapper = styled(Flex).withConfig({ - shouldForwardProp: prop => !['focus'].includes(prop) + shouldForwardProp: prop => !['focus', 'isDark'].includes(prop) })` background: ${({ isDark }) => (isDark ? colors.black : colors.white)}; border: ${borders[1]}; diff --git a/src/components/elements/Label.js b/src/components/elements/Label.js index 2aa2d363e..97f231549 100644 --- a/src/components/elements/Label.js +++ b/src/components/elements/Label.js @@ -1,5 +1,5 @@ import styled, { css } from 'styled-components' -import { colors, fontWeights } from 'theme' +import { colors, fontWeights, theme } from 'theme' import is from 'styled-is' import Text from './Text' @@ -13,7 +13,11 @@ export const labelStyle = css` color: ${props => getColor(props)}; ` -const Label = styled(Text)` +const Label = styled(Text).withConfig({ + shouldForwardProp: prop => !['suffix'].includes(prop) +})` + ${theme({ fontSize: 1 })}; + ${is('suffix')` &::after { content: '${props => props.suffix}'; @@ -23,9 +27,7 @@ const Label = styled(Text)` ` Label.defaultProps = { - as: 'label', - fontSize: 1, - mb: 1 + as: 'label' } export default Label diff --git a/src/components/elements/Link/base.js b/src/components/elements/Link/base.js index dd85176ae..7a77e6046 100644 --- a/src/components/elements/Link/base.js +++ b/src/components/elements/Link/base.js @@ -18,6 +18,7 @@ export const LinkBase = styled(Text)` const Link = styled(LinkBase)` ${theme({ color: 'link', + fontSize: 'inherit', _hover: { color: colors.hoverLink } diff --git a/src/components/elements/Link/index.js b/src/components/elements/Link/index.js index cfad46a29..818a7d8c1 100644 --- a/src/components/elements/Link/index.js +++ b/src/components/elements/Link/index.js @@ -1,15 +1,7 @@ import { withAnalytics, withLink } from 'helpers/hoc' -import styled from 'styled-components' import solid from './solid' import base from './base' -import Box from '../Box' - -const Span = styled(Box)`` - -Span.defaultProps = { - as: 'span' -} export const LinkSolid = withAnalytics(withLink(solid)) export const Link = withAnalytics(withLink(base)) diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js index 5fda1e537..2d4891824 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js @@ -42,10 +42,8 @@ const ActionComponent = ({ { return ( { } return ( - + + ) } diff --git a/src/components/elements/Select/Select.stories.js b/src/components/elements/Select/Select.stories.js index 4c39a2b22..49b04e824 100644 --- a/src/components/elements/Select/Select.stories.js +++ b/src/components/elements/Select/Select.stories.js @@ -77,6 +77,7 @@ const MySelectWithDefault = ({ placeholder, ...props }) => { const code = ` import { Select } from 'components/elements' +import { theme } from 'theme' export default () => ( - + @@ -103,8 +104,7 @@ storiesOf('Elements', module).add('Select', () => ( > getColor(props)}; border-bottom: 1px solid ${props => props.background}; `}; @@ -40,7 +40,7 @@ const Tabs = ({ children, ...props }) => ( {children.map(lang => { const isActive = lang === props.value return ( - + cx(isDark ? 'white10' : 'black10')}; - background: ${({ isDark }) => cx(isDark ? 'black' : 'white')}; - color: ${({ isDark }) => cx(isDark ? 'white' : 'black')}; + border-color: ${({ $isDark }) => cx($isDark ? 'white10' : 'black10')}; + background: ${({ $isDark }) => cx($isDark ? 'black' : 'white')}; + color: ${({ $isDark }) => cx($isDark ? 'white' : 'black')}; ` export const { width: TERMINAL_WIDTH, height: TERMINAL_HEIGHT } = aspectRatio([ @@ -39,7 +39,7 @@ const fromString = text => const TerminalHeader = styled('div')` background: linear-gradient( - ${props => (props.isDark ? 'black' : 'white')} 75%, + ${props => (props.$isDark ? 'black' : 'white')} 75%, transparent ); border-top-right-radius: ${radii[3]}; @@ -84,9 +84,9 @@ const TerminalButtonRed = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(1), - animationDuration - } + animationDelay: animationDelay(1), + animationDuration + } : undefined } {...props} @@ -112,9 +112,9 @@ const TerminalButtonGreen = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(3), - animationDuration - } + animationDelay: animationDelay(3), + animationDuration + } : undefined } {...props} @@ -194,9 +194,9 @@ const TerminalTextWrapper = styled('div')` width: 100%; white-space: pre; &::before { - content: ${props => (props.shellSymbol ? `'${props.shellSymbol} '` : '')}; + content: ${props => (props.$shellSymbol ? `'${props.$shellSymbol} '` : '')}; } - ${props => props.blinkCursor && blinkCursorStyle} + ${props => props.$blinkCursor && blinkCursorStyle} ` const TerminalProvider = ({ @@ -210,8 +210,8 @@ const TerminalProvider = ({ ...props }) => { return ( - - + + @@ -229,7 +229,10 @@ const Terminal = ({ children, shellSymbol, blinkCursor, ...props }) => { return ( - + {content} diff --git a/src/components/elements/Text.js b/src/components/elements/Text.js index 7760f2f8d..170eb6864 100644 --- a/src/components/elements/Text.js +++ b/src/components/elements/Text.js @@ -4,7 +4,9 @@ import { theme } from 'theme' import Box from './Box' -const Text = styled(Box)( +const Text = styled(Box).withConfig({ + shouldForwardProp: prop => !['variant'].includes(prop) +})( compose(typography, variant({ key: 'text' })), theme({ fontWeight: 'normal', diff --git a/src/components/elements/Toggle/Toggle.js b/src/components/elements/Toggle/Toggle.js index bfb263cf0..004b3112f 100644 --- a/src/components/elements/Toggle/Toggle.js +++ b/src/components/elements/Toggle/Toggle.js @@ -43,8 +43,7 @@ function Toggle ({ onChange, children, defaultValue, ...props }) { css={theme({ borderRight: !isLast ? 1 : undefined, borderColor: !isLast ? 'black05' : undefined, - pl: 3, - pr: 3 + px: 3 })} > diff --git a/src/components/elements/Toolbar.js b/src/components/elements/Toolbar.js index 553968442..e3a865952 100644 --- a/src/components/elements/Toolbar.js +++ b/src/components/elements/Toolbar.js @@ -18,7 +18,7 @@ const ToolbarBase = styled(Flex)` px: 0, 'overflow-x': 'auto', 'overflow-y': 'hidden' - })})} + })} ${hideScrollbar}; ` diff --git a/src/components/elements/Unavatar/Unavatar.js b/src/components/elements/Unavatar/Unavatar.js index cb7505f61..a8525b40b 100644 --- a/src/components/elements/Unavatar/Unavatar.js +++ b/src/components/elements/Unavatar/Unavatar.js @@ -21,8 +21,8 @@ const Unavatar = ({ query, ...props }) => { ) } -const UnavatarMicrolink = props => ( - +const UnavatarMicrolink = ({ url, ...props }) => ( + ) Unavatar.Microlink = UnavatarMicrolink diff --git a/src/components/icons/Feather.js b/src/components/icons/Feather.js index 0b12fb2c8..b9f644214 100644 --- a/src/components/icons/Feather.js +++ b/src/components/icons/Feather.js @@ -1,23 +1,25 @@ import * as FeatherIcons from 'react-feather' import React, { createElement } from 'react' import { Flex } from 'components/elements' -import { fontSizes, cx } from 'theme' +import { fontSizes, cx, theme } from 'theme' const getWidth = size => { if (Array.isArray(size)) return size.map(index => fontSizes[index]) return fontSizes[size] } -const FeatherIcon = ({ icon, size = [1, 1, 2, 2], ...props }) => ( +const FeatherIcon = ({ color, icon, size = [1, 1, 2, 2], ...props }) => ( {createElement(FeatherIcons[icon], { - color: props.color ? cx(props.color) : undefined + color: color ? cx(color) : undefined })} ) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index 88c89f407..9d2af4abd 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -65,128 +65,153 @@ export const Code = withContainer(CodeEditor) export const MultiCodeEditor = withContainer(MultiCodeEditorBase) -export const H1 = withTitle(withSlug(styled(Heading)``)) +export const H1 = withTitle( + withSlug(styled(Heading)` + ${theme({ + maxWidth: layout.small, + fontSize: `calc(${fontSizes[5]} * 0.75)`, + lineHeight: [1, 2], + textAlign: 'left', + mx: 'auto', + mt: 5, + mb: 4 + })} + `) +) H1.defaultProps = { - maxWidth: layout.small, as: 'h1', - fontSize: `calc(${fontSizes[5]} * 0.75)`, - lineHeight: [1, 2], - textAlign: 'left', - variant: null, - ml: 'auto', - mr: 'auto', - mt: 5, - mb: 4 + variant: null } -const H2Base = styled(Heading)`` +const H2Base = styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: `calc(${fontSizes[4]} * 0.75)`, + lineHeight: [1, 2], + textAlign: 'left', + mt: 5, + mb: 4 + })} +` H2Base.defaultProps = { - ml: 'auto', - mr: 'auto', - maxWidth: layout.small, as: 'h2', - fontSize: `calc(${fontSizes[4]} * 0.75)`, - lineHeight: [1, 2], - textAlign: 'left', - variant: null, - mt: 5, - mb: 4 + variant: null } export const H2 = withTitle(withSlug(H2Base)) -export const H3 = withTitle(withSlug(styled(Heading)``)) +export const H3 = withTitle( + withSlug(styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: `calc(${fontSizes[4]} * 0.75 * 0.75)`, + lineHeight: 1, + textAlign: 'left', + mt: 5, + mb: 4 + })} + `) +) H3.defaultProps = { - ml: 'auto', - mr: 'auto', - maxWidth: layout.small, as: 'h3', - fontSize: `calc(${fontSizes[4]} * 0.75 * 0.75)`, - lineHeight: 1, - textAlign: 'left', - variant: null, - mt: 5, - mb: 4 + variant: null } -export const H4 = withTitle(withSlug(styled(Heading)``)) +export const H4 = withTitle( + withSlug(styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 2, + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} + `) +) H4.defaultProps = { - ml: 'auto', - mr: 'auto', - maxWidth: layout.small, as: 'h4', - fontSize: 2, - lineHeight: 1, - textAlign: 'left', - variant: null, - mt: 4, - mb: 3 + variant: null } -export const H5 = withTitle(withSlug(styled(Heading)``)) +export const H5 = withTitle( + withSlug(styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 1, + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} + `) +) H5.defaultProps = { - ml: 'auto', - mr: 'auto', - maxWidth: layout.small, as: 'h5', - fontSize: 1, - lineHeight: 1, - textAlign: 'left', - variant: null, - mt: 4, - mb: 3 + variant: null } -export const H6 = withTitle(withSlug(styled(Heading)``)) +export const H6 = withTitle( + withSlug(styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 1, + color: 'gray9', + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} + `) +) H6.defaultProps = { - ml: 'auto', - mr: 'auto', - maxWidth: layout.small, as: 'h6', - fontSize: 1, - color: 'gray9', - lineHeight: 1, - textAlign: 'left', - variant: null, - mt: 4, - mb: 3 + variant: null } export const Paraph = props => { const isMedia = get(props, 'children.props.name') === 'img' const maxWidth = isMedia ? layout.large : layout.small - return -} - -Paraph.defaultProps = { - as: 'div', - ml: 'auto', - mr: 'auto', - ...CONTAINER_SPACE + return ( + + ) } -export const Strong = styled(Text)`` +export const Strong = styled(Text)` + display: inline; + font-weight: bold; +` Strong.defaultProps = { - as: 'b', - display: 'inline', - fontWeight: 'bold' + as: 'b' } -export const Ul = styled(Text)`` +export const Ul = styled(Text)` + max-width: ${layout.small}; + + ${theme({ + mx: 'auto', + ...CONTAINER_SPACE + })} +` Ul.defaultProps = { - ml: 'auto', - mr: 'auto', - as: 'ul', - maxWidth: layout.small, - ...CONTAINER_SPACE + as: 'ul' } export const Ol = styled(Ul)`` @@ -195,14 +220,17 @@ Ol.defaultProps = { as: 'ol' } -export const Li = styled(Text)`` +export const Li = styled(Text)` + max-width: ${layout.small}; + + ${theme({ + mx: 'auto', + mb: 3 + })} +` Li.defaultProps = { - ml: 'auto', - mr: 'auto', - mb: 3, - as: 'li', - maxWidth: layout.small + as: 'li' } const codeStyle = css` @@ -231,48 +259,44 @@ CodeInline.defaultProps = { const mediaStyle = { borderRadius: '3px', - ml: 'auto', - mr: 'auto', + mx: 'auto', textAlign: 'center' } -const _ImageBase = styled(ImageBase)`` - -_ImageBase.defaultProps = { - ...mediaStyle -} +const _ImageBase = styled(ImageBase)` + ${theme(mediaStyle)} +` export const Image = withContainer(_ImageBase, { maxWidth: 'inherit' }) -const _VideoBase = styled(VideoBase)`` +const _VideoBase = styled(VideoBase)` + ${theme(mediaStyle)} + + width: 100%, +` _VideoBase.defaultProps = { - ...mediaStyle, - width: '100%', autoPlay: true } export const Video = withContainer(_VideoBase) -const _IframeBase = styled(IframeBase)`` +const _IframeBase = styled(IframeBase)` + ${theme({ mx: 'auto' })} -_IframeBase.defaultProps = { - mx: 'auto', - width: CodeEditor.width, - height: CodeEditor.height -} + width: ${CodeEditor.width}; + height: ${CodeEditor.height}; +` export const Iframe = withContainer(_IframeBase) -const FigcaptionBase = styled(Text)`` +const FigcaptionBase = styled(Text)` + ${theme({ fontSize: 0, color: 'black50' })} -FigcaptionBase.defaultProps = { - fontSize: 0, - color: 'black50', - textAlign: 'center' -} + text-align: center; +` export const Figcaption = withContainer(FigcaptionBase) @@ -286,30 +310,33 @@ export const Blockquote = styled.blockquote` ` const Type = styled(Text)` + ${theme({ + bg: 'gray1', + color: 'gray7', + fontFamily: 'mono', + fontSize: 0, + fontWeight: 'regular' + })} + padding: 0.2em 0.4em; margin: 0; border-radius: 3px; ` Type.defaultProps = { - as: 'span', - bg: 'gray1', - color: 'gray7', - fontFamily: 'mono', - fontSize: 0, - fontWeight: 'regular' + as: 'span' } const TypeContainer = styled(Box)` + ${theme({ + fontFamily: 'mono', + fontSize: 0, + color: 'gray7' + })} + display: inline; ` -TypeContainer.defaultProps = { - fontFamily: 'mono', - fontSize: 0, - color: 'gray7' -} - const PriceMonthly = props => ( { - const bytes = (() => { - const [value, unit] = bytesPretty.split(' ') - const fixedValue = Number(value).toFixed(0) - return `${fixedValue}${unit}` - })() +const Stat = ({ value, name, isLast }) => ( + + + + {value} + + + + {name} + + + + {!isLast && } + +) - const stats = [ - { value: 240, name: 'CDN Edges' }, - { value: reqsPretty, name: 'reqs per month' }, - { value: bytes, name: 'data served' }, - { value: '99.9%', name: 'uptime' } - ] +const bytes = (() => { + const [value, unit] = bytesPretty.split(' ') + const fixedValue = Number(value).toFixed(0) + return `${fixedValue}${unit}` +})() - const Stat = ({ value, name, isLast }) => ( - - - - {value} - - - - {name} - - - - {!isLast && } - - ) +const stats = [ + { value: 240, name: 'CDN Edges' }, + { value: reqsPretty, name: 'reqs per month' }, + { value: bytes, name: 'data served' }, + { value: '99.9%', name: 'uptime' } +] - const blockOne = ( - <> +const Analytics = () => { + return ( + - + {stats.map((stat, index) => ( { - + {take(stats, stats.length - 1).map((stat, index) => ( { ))} - - ) - - return ( - + ) } diff --git a/src/components/pages/home/faqs.js b/src/components/pages/home/faqs.js index 097c1fc44..e4ca0a60d 100644 --- a/src/components/pages/home/faqs.js +++ b/src/components/pages/home/faqs.js @@ -1,6 +1,7 @@ import { Box, Link } from 'components/elements' import { Faq } from 'components/patterns' import React from 'react' +import { theme } from 'theme' const FAQs = props => ( (
The API key need to be attached to all your requests: - + At{' '} @@ -77,7 +78,7 @@ const FAQs = props => ( , attach it as{' '} apiKey. - + At{' '} Microlink API @@ -96,11 +97,8 @@ const FAQs = props => ( <>
Our Service-Level Agreements commitment is 99.9% (three nines).{' '} - {'\n'}You can see the live{' '} - - status - {' '} - of the service. + {'\n'}You can see the live status of + the service.
) @@ -124,9 +122,7 @@ const FAQs = props => (
You can upgrade, downgrade, or cancel your monthly account at any time with no further obligation, sending an email to{' '} - - hello@microlink.io - {' '} + hello@microlink.io{' '} with the email you signed up.
@@ -150,9 +146,7 @@ const FAQs = props => ( <>
Yes, send an email to{' '} - - hello@microlink.io - {' '} + hello@microlink.io{' '} requesting the change. You will receive a link from where you’ll be able to securely update your details.
@@ -165,10 +159,8 @@ const FAQs = props => ( <>
Yes, by sending an email to{' '} - - hello@microlink.io - - . Your request will be processed within 24hrs. + hello@microlink.io. + Your request will be processed within 24hrs.
) @@ -179,10 +171,7 @@ const FAQs = props => ( <>
We’re always available at{' '} - - hello@microlink.io - - . + hello@microlink.io.
) diff --git a/src/components/pages/home/hero.js b/src/components/pages/home/hero.js index 72031d588..d30d10473 100644 --- a/src/components/pages/home/hero.js +++ b/src/components/pages/home/hero.js @@ -2,7 +2,7 @@ import { Subhead, Box, Flex, Heading } from 'components/elements' import FeatherIcon from 'components/icons/Feather' import { Caption } from 'components/patterns' import { useHover } from 'components/hook' -import { transition, layout } from 'theme' +import { transition, layout, theme } from 'theme' import { setSaturation } from 'polished' import React, { useState } from 'react' import styled from 'styled-components' @@ -30,18 +30,20 @@ const GridLink = ({ children, setColor, color, ...props }) => { setColor(color)} onMouseLeave={() => setColor('')} - flexDirection='column' - alignItems='center' - justifyContent='center' - m={2} - p={4} - border={1} - borderColor='black10' - borderRadius={3} - width='300px' + css={theme({ + bg: 'white', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + m: 2, + p: 4, + border: 1, + borderColor: 'black10', + borderRadius: 3, + width: '300px' + })} $color={color} {...props} > @@ -66,105 +68,97 @@ const Grid = styled(Flex)` justify-content: center; ` -const Hero = ({ children, ...props }) => { +const GRID_ITEMS = [ + { + title: 'Logo', + subtitle: 'Get and embed Favicons from any web', + color: '#d306aa', + href: '/logo' + }, + { + title: 'Screenshot', + subtitle: 'Turn websites into screenshots', + color: '#fd494a', + href: '/screenshot' + }, + { + title: 'SDK', + subtitle: 'Create beautiful link previews', + color: '#449bf8', + href: '/sdk' + }, + { + title: 'Insights', + subtitle: 'Performance metrics powered by Lighthouse', + color: 'rgb(181, 0, 237)', + href: '/insights' + }, + { + title: 'Meta', + subtitle: 'Get unified metadata', + color: '#3e55ff', + href: '/meta' + }, + { + title: 'PDF', + subtitle: 'PDF made simple', + color: '#e000ac', + href: '/pdf' + } +] + +const Hero = ({ children }) => { const [color, setColor] = useState('') return ( {children({ color })} - + Browser as API Microlink is a fast, scalable, and reliable high-level API to control a headless browser built for businesses and developers. Proudly Open Source. - - - Logo - - Get and embed Favicons from any web - - - - - Screenshot - - Turn websites into screenshots - - - - SDK - - Create beauty link previews - - - - Insights - - Performance metrics powered by Lighthouse - - - - Meta - - Get unified metadata - - - - PDF - - PDF made simple - - + + {GRID_ITEMS.map(gridItem => ( + + + {gridItem.title} + + + {gridItem.subtitle} + + + ))} diff --git a/src/components/pages/home/pricing.js b/src/components/pages/home/pricing.js index 8cbda8d54..3a470ed86 100644 --- a/src/components/pages/home/pricing.js +++ b/src/components/pages/home/pricing.js @@ -1,17 +1,11 @@ import { Caption, PricingTable } from 'components/patterns' import { Subhead, Container } from 'components/elements' -import { fontSizes, layout } from 'theme' +import { fontSizes, layout, theme } from 'theme' import React from 'react' -const Pricing = ({ - canonicalUrl, - apiKey, - stripeKey, - apiEndpoint, - ...props -}) => { +const Pricing = ({ canonicalUrl, stripeKey, apiEndpoint }) => { return ( - + Every plan comes with API access & 24/7 tech support. Use the forever free plan to try the service, no credit-card required. @@ -30,7 +26,6 @@ const Pricing = ({ diff --git a/src/components/patterns/Announcement/Announcement.js b/src/components/patterns/Announcement/Announcement.js index d43f592b3..85fd7147b 100644 --- a/src/components/patterns/Announcement/Announcement.js +++ b/src/components/patterns/Announcement/Announcement.js @@ -1,8 +1,9 @@ import React from 'react' import { Link } from 'components/elements' +import { theme } from 'theme' const Announcement = ({ href, children }) => ( - + <> {children} {' →'} diff --git a/src/components/patterns/ArrowLink.js b/src/components/patterns/ArrowLink.js index e83622349..31d433d3e 100644 --- a/src/components/patterns/ArrowLink.js +++ b/src/components/patterns/ArrowLink.js @@ -1,6 +1,5 @@ import FeatherIcon from 'components/icons/Feather' import { Link, Flex } from 'components/elements' -import { Caption } from 'components/patterns' import { useHover } from 'components/hook' import React from 'react' @@ -17,7 +16,6 @@ const ArrowLink = ({ children, ...props }) => { align-items: center; } `} - fontSize={Caption.defaultProps.fontSize} icon={false} {...props} > diff --git a/src/components/patterns/Aside/Aside.js b/src/components/patterns/Aside/Aside.js index d3abc5c20..293c72abb 100644 --- a/src/components/patterns/Aside/Aside.js +++ b/src/components/patterns/Aside/Aside.js @@ -3,7 +3,7 @@ import { Menu as MenuIcon, X as CloseIcon } from 'react-feather' import { useBreakpoint } from 'context/breakpoint' import { Box, Flex } from 'components/elements' import styled from 'styled-components' -import { shadows } from 'theme' +import { shadows, theme } from 'theme' import AsideBase from './AsideBase' @@ -28,17 +28,17 @@ const AsideButton = ({ title, iconComponent, ...props }) => ( ) +const css = ` + box-shadow: ${shadows[0]}; + background: white; + z-index: 3; + left: 0; +` + const AsideMobile = ({ children, ...props }) => { const [isOpen, setOpen] = useState(false) const toggleOpen = () => setOpen(!isOpen) - const css = ` - box-shadow: ${shadows[0]}; - background: white; - z-index: 3; - left: 0; - ` - return ( { <> {children} diff --git a/src/components/patterns/Aside/AsideBase.js b/src/components/patterns/Aside/AsideBase.js index c03fd5a86..eb8d4f274 100644 --- a/src/components/patterns/Aside/AsideBase.js +++ b/src/components/patterns/Aside/AsideBase.js @@ -1,6 +1,6 @@ import { Flex, Toggle, Box, Text, Caps } from 'components/elements' import { TOOLBAR_PRIMARY_HEIGHT } from 'components/elements/Toolbar' -import { transition, borders, colors, space } from 'theme' +import { transition, borders, colors, space, theme } from 'theme' import React, { useState, Fragment } from 'react' import styled, { css } from 'styled-components' import { withLink } from 'helpers/hoc' @@ -24,6 +24,8 @@ const LINK_ICON_CLASSNAME = 'nav-link-icon' const { isInternalLink } = withLink const linkStyle = css` + margin-bottom: ${space[2]}; + > a { display: flex; align-items: center; @@ -75,11 +77,13 @@ const AsideWrapper = styled(Box)` } ` -const Header = props => +const Header = props => ( + +) const Title = ({ children, href, Icon, ...props }) => { return ( - + {Icon && } {CloseButton && ( - - {CloseButton} - + {CloseButton} )} - + {ROUTES[tree].map(path => ( - +
{path.name}
{path.posts.map(post => { const hasSubEntries = Boolean(post.posts) @@ -162,12 +168,14 @@ const Aside = ({ {post.posts.map(post => ( diff --git a/src/components/patterns/Average/Average.js b/src/components/patterns/Average/Average.js index e81af6820..e4f223fcf 100644 --- a/src/components/patterns/Average/Average.js +++ b/src/components/patterns/Average/Average.js @@ -2,6 +2,7 @@ import { Text, Highlight } from 'components/elements' import uniqueRandomArray from 'unique-random-array' import React, { useEffect, useState } from 'react' import range from 'lodash/range' +import { theme } from 'theme' import Caption from '../Caption/Caption' @@ -33,7 +34,10 @@ const Average = ({ size, value }) => { if (size === 'tiny') { return ( <Highlight display='inline'> - <Text as='span' px='2px' color='black80' fontWeight='bold'> + <Text + as='span' + css={theme({ px: '2px', color: 'black80', fontWeight: 'bold' })} + > {prettyNumber(average)} {unit} </Text> </Highlight> @@ -41,15 +45,17 @@ const Average = ({ size, value }) => { } return ( - <Highlight px={3}> - <Text as='span' fontSize={6} fontWeight='bold'> + <Highlight css={theme({ px: 3 })}> + <Text as='span' css={theme({ fontSize: 6, fontWeight: 'bold' })}> {prettyNumber(average)} </Text> <Caption - ml={2} - color='white' - display='inline' - fontWeight='bold' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > {unit} diff --git a/src/components/patterns/Block/Block.js b/src/components/patterns/Block/Block.js index 15d186b7a..f95f2277d 100644 --- a/src/components/patterns/Block/Block.js +++ b/src/components/patterns/Block/Block.js @@ -1,6 +1,7 @@ import React from 'react' import { Container, Flex, Box } from 'components/elements' +import { theme } from 'theme' const Block = ({ blockOne, @@ -8,19 +9,20 @@ const Block = ({ bottom = null, top = null, flexDirection = 'row', - children = <Box ml={4} mr={4} />, + children = <Box css={theme({ mx: 4 })} />, width, ...props }) => ( <Container {...props}> {top} <Flex - justifyContent='center' - flexDirection={['column', 'column', 'column', flexDirection]} - alignItems='center' - ml='auto' - mr='auto' - width={width} + css={theme({ + justifyContent: 'center', + flexDirection: ['column', 'column', 'column', flexDirection], + alignItems: 'center', + mx: 'auto', + width + })} > {blockOne} {children} diff --git a/src/components/patterns/Chat/Chat.js b/src/components/patterns/Chat/Chat.js index 8b3f7980b..02667b425 100644 --- a/src/components/patterns/Chat/Chat.js +++ b/src/components/patterns/Chat/Chat.js @@ -1,21 +1,21 @@ import React from 'react' import { Button, Flex, Caps } from 'components/elements' +import { theme } from 'theme' const Chat = () => { return ( - <Flex justifyContent='center' alignItems='center'> + <Flex css={theme({ justifyContent: 'center', alignItems: 'center' })}> <Button onClick={() => window.open( 'https://join.slack.com/t/microlinkhq/shared_invite/zt-3oe805om-HzexWW5yQNcF6cJs3dFM_A', '_blank', 'noopener noreferrer' - )} + ) + } > - <Caps px={3} py={2}> - Join in the community - </Caps> + <Caps css={theme({ px: 3, py: 2 })}>Join in the community</Caps> </Button> </Flex> ) diff --git a/src/components/patterns/Checkout.js b/src/components/patterns/Checkout.js index 54ca576d0..efd445c57 100644 --- a/src/components/patterns/Checkout.js +++ b/src/components/patterns/Checkout.js @@ -4,6 +4,7 @@ import { loadStripe } from '@stripe/stripe-js/pure' import { Caps, Button } from 'components/elements' import { useSiteMetadata } from 'components/hook' import React, { useState } from 'react' +import { theme } from 'theme' const Checkout = ({ canonicalUrl, planId, stripeKey, ...props }) => { const [isLoading, setIsLoading] = useState(false) @@ -38,7 +39,7 @@ const Checkout = ({ canonicalUrl, planId, stripeKey, ...props }) => { data-event-name='Buy' {...props} > - <Caps fontSize={[0, 0, 2, 2]}>Buy</Caps> + <Caps css={theme({ fontSize: [0, 0, 2, 2] })}>Buy</Caps> </Button> ) } diff --git a/src/components/patterns/CubeBackground/CubeBackground.js b/src/components/patterns/CubeBackground/CubeBackground.js index 950e60987..7c130435f 100644 --- a/src/components/patterns/CubeBackground/CubeBackground.js +++ b/src/components/patterns/CubeBackground/CubeBackground.js @@ -26,14 +26,14 @@ const cubesStyle = CUBES_RANGE.reduce((acc, index) => { return acc + css }, '') -const CubesBackgroundWrapper = styled('ul')` +const CubeBackgroundWrapper = styled('ul')` margin: 0; li { border-radius: ${radii[4]}; position: absolute; display: block; list-style: none; - background: ${props => cx(props.bg)}; + background: ${props => cx(props.$bg)}; animation: ${rotation} 25s linear infinite; bottom: -150px; } @@ -41,12 +41,12 @@ const CubesBackgroundWrapper = styled('ul')` ${cubesStyle}; ` -const CubesBackground = ({ bg = 'rgba(255, 255, 255, 0.2)', ...props }) => ( - <CubesBackgroundWrapper bg={bg} {...props}> +const CubeBackground = ({ bg = 'rgba(255, 255, 255, 0.2)', ...props }) => ( + <CubeBackgroundWrapper $bg={bg} {...props}> {CUBES_RANGE.map(n => ( <li key={`circles_cube_${n}`} /> ))} - </CubesBackgroundWrapper> + </CubeBackgroundWrapper> ) -export default CubesBackground +export default CubeBackground diff --git a/src/components/patterns/DemoLinks/DemoLinks.js b/src/components/patterns/DemoLinks/DemoLinks.js index 152a42482..c4a514306 100644 --- a/src/components/patterns/DemoLinks/DemoLinks.js +++ b/src/components/patterns/DemoLinks/DemoLinks.js @@ -8,7 +8,7 @@ import { import React, { createElement } from 'react' import { LogoBrand } from 'components/logos' import styled from 'styled-components' -import { transition } from 'theme' +import { transition, theme } from 'theme' import chunk from 'lodash/chunk' const NoWrap = styled(Flex)` @@ -48,7 +48,10 @@ const DemoLinks = ({ children, chunkSize, onClick }) => { }) return ( - <BackgroundSliderContainer as='section' py={0} px={0} maxWidth='100%'> + <BackgroundSliderContainer + as='section' + css={theme({ p: 0, maxWidth: '100%' })} + > {chunk(links, chunkSize).map((chunkBrands, chunkIndex) => { const isEven = chunkIndex % 2 === 0 return ( diff --git a/src/components/patterns/Faq/Faq.js b/src/components/patterns/Faq/Faq.js index 198b14b9d..6e320ed46 100644 --- a/src/components/patterns/Faq/Faq.js +++ b/src/components/patterns/Faq/Faq.js @@ -3,14 +3,16 @@ import { Subhead, Text, Box, Container, Flex } from 'components/elements' import { slug as slugger } from 'github-slugger' import { Caption } from 'components/patterns' import { withSlug } from 'helpers/hoc' -import { layout } from 'theme' +import { layout, theme } from 'theme' const Question = withSlug(({ index, ...props }) => ( <Caption - fontWeight='bold' - pt={index === 0 ? 0 : 5} - pr={[3, 0, 0, 0]} - textAlign='left' + css={theme({ + fontWeight: 'bold', + pt: index === 0 ? 0 : 5, + pr: [3, 0, 0, 0], + textAlign: 'left' + })} {...props} /> )) @@ -18,15 +20,17 @@ const Question = withSlug(({ index, ...props }) => ( const Faq = ({ title, caption, questions, ...props }) => { return ( <Container id='faq' {...props}> - <Flex flexDirection='column' alignItems='center'> - <Subhead px={4} variant='gradient' titleize={false}> + <Flex css={theme({ flexDirection: 'column', alignItems: 'center' })}> + <Subhead css={theme({ px: 4 })} variant='gradient' titleize={false}> {title} </Subhead> <Caption - px={[4, 0, 0, 0]} - pt={[3, 4, 4, 4]} - pb={[4, 4, 4, 5]} - maxWidth={layout.normal} + css={theme({ + px: [4, 0, 0, 0], + pt: [3, 4, 4, 4], + pb: [4, 4, 4, 5], + maxWidth: layout.normal + })} titleize={false} > {caption} @@ -34,22 +38,29 @@ const Faq = ({ title, caption, questions, ...props }) => { </Flex> <Flex - justifyContent='center' - flexDirection='column' - alignItems='center' - px={[0, 0, 4, 6]} + css={theme({ + justifyContent: 'center', + flexDirection: 'column', + alignItems: 'center', + px: [0, 0, 4, 6] + })} > - <Box pb={[0, 0, 4, 4]}> + <Box css={theme({ pb: [0, 0, 4, 4] })}> {questions.map(({ answer, question }, index) => { return ( - <Text px={4} maxWidth={layout.small} key={question}> + <Text + css={theme({ px: 4, maxWidth: layout.small })} + key={question} + > <Question index={index}>{question}</Question> {React.Children.map(answer.props.children, (paraph, index) => ( <Text - pr={[3, 0, 0, 0]} - pt={[3, 4, 4, 4]} + css={theme({ + pr: [3, 0, 0, 0], + pt: [3, 4, 4, 4], + color: 'black80' + })} key={`${slugger(question)}-${index}`} - color='black80' > {paraph} </Text> diff --git a/src/components/patterns/Features/Features.js b/src/components/patterns/Features/Features.js index feb83dd85..5b44f0ebb 100644 --- a/src/components/patterns/Features/Features.js +++ b/src/components/patterns/Features/Features.js @@ -1,5 +1,5 @@ import { Container, Box, Hide } from 'components/elements' -import { layout } from 'theme' +import { layout, theme } from 'theme' import React from 'react' import Grid from '../Grid' @@ -10,15 +10,22 @@ const Features = ({ title, caption, features, ...props }) => { <Container as='section' id='features' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large] + })} {...props} > - <Box textAlign='left' width='100%'> - {title} - </Box> + <Box css={theme({ textAlign: 'left', width: '100%' })}>{title}</Box> - <Caption pt={[3, 3, 4, 4]} pb={3} width='100%' textAlign='left'> + <Caption + css={theme({ + pt: [3, 3, 4, 4], + pb: 3, + width: '100%', + textAlign: 'left' + })} + > {caption} </Caption> @@ -33,7 +40,7 @@ const Features = ({ title, caption, features, ...props }) => { breakpoints={[0]} style={{ margin: 0, width: '100%', paddingLeft: 0 }} > - <Grid pt={3} itemsPerRow={3}> + <Grid css={theme({ pt: 3 })} itemsPerRow={3}> {features} </Grid> </Hide> diff --git a/src/components/patterns/Footer/Footer.js b/src/components/patterns/Footer/Footer.js index 2a494ae41..60dce8f80 100644 --- a/src/components/patterns/Footer/Footer.js +++ b/src/components/patterns/Footer/Footer.js @@ -45,7 +45,7 @@ const Footer = ({ isDark, ...props }) => { css={theme({ px: 0, maxWidth: layout.large, - pb: Container.defaultProps.pt + pb: [5, 5, 6, 6] })} > <Flex @@ -91,7 +91,7 @@ const Footer = ({ isDark, ...props }) => { placeholder='you@domain.com' iconComponent={<Mail color={inputIconColor} size={16} />} isDark={isDark} - css={theme({ fontSize: 1, width: '8rem' })} + css={theme({ fontSize: 0, width: '8rem' })} required /> diff --git a/src/components/patterns/Grid.js b/src/components/patterns/Grid.js index baf005e97..c9a85e0bd 100644 --- a/src/components/patterns/Grid.js +++ b/src/components/patterns/Grid.js @@ -2,28 +2,32 @@ import { Caps, Flex, Text, Box } from 'components/elements' import Markdown from 'components/markdown' import chunk from 'lodash/chunk' import React from 'react' +import { theme } from 'theme' const Item = ({ title, description, ...props }) => ( <Box as='li' - maxWidth='16rem' - style={{ listStyle: 'none' }} - flex={1} - pt={4} - pr={[0, 3, 3, 3]} + css={theme({ + maxWidth: '16rem', + listStyle: 'none', + flex: 1, + pt: 4, + pr: [0, 3, 3, 3] + })} {...props} > - <Caps as='h4' pb={[1, 2]} fontWeight='bold'> + <Caps as='h4' css={theme({ pb: [1, 2], fontWeight: 'bold' })}> {title} </Caps> <Text css={` + ${theme({ fontSize: 1 })} + div { margin: 0; font-size: inherit; } `} - fontSize={1} > <Markdown>{description}</Markdown> </Text> @@ -40,14 +44,16 @@ const Grid = ({ {chunk(children, itemsPerRow).map((row, index) => ( <Flex as='ul' - justifyContent={[ - 'space-around', - 'flex-start', - 'space-between', - 'space-between' - ]} + css={theme({ + justifyContent: [ + 'space-around', + 'flex-start', + 'space-between', + 'space-between' + ], + pl: 0 + })} key={index} - pl={0} {...props} > {row.map(rowProps => ( diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index d3d11b1f0..3abc3f313 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -61,7 +61,7 @@ const Layout = ({ })} > <Toolbar as='header' isDark={isDark} style={style} /> - {/* {createElement( + {createElement( component, { as: 'main', @@ -69,11 +69,10 @@ const Layout = ({ alignItems, display, flexDirection, - pt: toolbarHeight, - style: { flex: 1 } + style: { flex: 1, paddingTop: toolbarHeight } }, children - )} */} + )} {footer && ( <Box as='footer' className='hidden-print'> <Footer isDark={isDark} {...footer} /> diff --git a/src/components/patterns/List/List.js b/src/components/patterns/List/List.js index ab4388c92..165534cf5 100644 --- a/src/components/patterns/List/List.js +++ b/src/components/patterns/List/List.js @@ -1,19 +1,23 @@ import FeatherIcon from 'components/icons/Feather' import { Flex, Text } from 'components/elements' -import { fontSizes } from 'theme' +import { fontSizes, theme } from 'theme' import React from 'react' -const List = props => <Flex as='ul' flexDirection='column' {...props} /> +const List = props => ( + <Flex as='ul' css={theme({ flexDirection: 'column' })} {...props} /> +) const ListItem = ({ type = 'yes', ...props }) => { const isYes = type === 'yes' return ( - <Flex as='li' alignItems='center' mb={3}> + <Flex as='li' css={theme({ alignItems: 'center', mb: 3 })}> <Flex - justifyContent='center' - mr={2} - width={[fontSizes[1], fontSizes[1], fontSizes[2], fontSizes[2]]} - height='100%' + css={theme({ + justifyContent: 'center', + mr: 2, + width: [fontSizes[1], fontSizes[1], fontSizes[2], fontSizes[2]], + height: '100%' + })} as='span' > <FeatherIcon diff --git a/src/components/patterns/MQLEditor/MQLEditor.js b/src/components/patterns/MQLEditor/MQLEditor.js index fab0c0ab8..292647094 100644 --- a/src/components/patterns/MQLEditor/MQLEditor.js +++ b/src/components/patterns/MQLEditor/MQLEditor.js @@ -1,5 +1,5 @@ import { useWindowSize } from 'components/hook' -import { shadows, breakpoints } from 'theme' +import { shadows, breakpoints, theme } from 'theme' import Microlink from '@microlink/react' import React, { useState } from 'react' import styled from 'styled-components' @@ -123,14 +123,16 @@ const MQLEditor = props => { </MQLCard> </Choose> <Flex - width='100%' - pl='15px' - pr='7px' - alignItems={['center', 'center', undefined, undefined]} - justifyContent='space-between' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + width: '100%', + pl: '15px', + pr: '7px', + alignItems: ['center', 'center', undefined, undefined], + justifyContent: 'space-between', + flexDirection: ['column', 'column', 'row', 'row'] + })} > - <Box pt={[5, 5, 4, 4]}> + <Box css={theme({ pt: [5, 5, 4, 4] })}> {MODES.map(children => ( <Card.Option key={children} @@ -141,7 +143,7 @@ const MQLEditor = props => { </Card.Option> ))} </Box> - <Box pt={[3, 3, 4, 4]}> + <Box css={theme({ pt: [3, 3, 4, 4] })}> {TYPES.map(children => ( <Card.Option key={children} diff --git a/src/components/patterns/PricingTable/PricingTable.js b/src/components/patterns/PricingTable/PricingTable.js index 0c298d299..2a91411ec 100644 --- a/src/components/patterns/PricingTable/PricingTable.js +++ b/src/components/patterns/PricingTable/PricingTable.js @@ -1,14 +1,13 @@ import PricePicker, { DEFAULT_PLAN } from 'components/elements/PricePicker' import { Caption, ArrowLink, Checkout } from 'components/patterns' import FeatherIcon from 'components/icons/Feather' -import { breakpoints, colors } from 'theme' +import { breakpoints, colors, theme } from 'theme' import React, { useState } from 'react' import { formatNumber } from 'helpers' import styled from 'styled-components' import { Box, - Container, Flex, Highlight, Label, @@ -22,7 +21,7 @@ const FREE_PLAN_RATE_LIMIT = 50 const Requests = ({ suffix, ...props }) => ( <Label - display='inline' + css={theme({ display: 'inline' })} aria-label={`requests per ${suffix}`} suffix={`/${suffix}`} {...props} @@ -33,12 +32,14 @@ const Requests = ({ suffix, ...props }) => ( const PricingLink = ({ children, ...props }) => { return ( - <Link.Base color='black' {...props}> + <Link.Base css={theme({ color: 'black' })} {...props}> <Caption - fontSize={[1, 1, 2, 2]} - display='inline' - color='inherit' - textAlign='left' + css={theme({ + fontSize: [1, 1, 2, 2], + display: 'inline', + color: 'inherit', + textAlign: 'left' + })} > {children} </Caption> @@ -46,19 +47,18 @@ const PricingLink = ({ children, ...props }) => { ) } -const PricingBox = props => ( - <Box - borderRadius={3} - textAlign='center' - width={['100%', '100%', 8, 8]} - px={[3, 3, 5, 5]} - py={[4, 4, 5, 5]} - my={[4, 4, 0, 0]} - border={1} - bg='white' - {...props} - /> -) +const PricingBox = styled(Box)` + ${theme({ + borderRadius: 3, + textAlign: 'center', + width: ['100%', '100%', 8, 8], + px: [3, 3, 5, 5], + py: [4, 4, 5, 5], + my: [4, 4, 0, 0], + border: 1, + bg: 'white' + })} +` const FreePricingBox = styled(PricingBox)` border-color: ${colors.black20}; @@ -74,11 +74,11 @@ const ProPricingBoxGradient = styled(PricingBox)` flex-direction: column; position: relative; left: -1px; - border none; + border: none; background: linear-gradient(90deg, #f76698, #c03fa2 60%, #8c1bab 100%); border-radius: 7px; padding: 2px; - ` +` const ProPricingBox = styled(Box)` background: #fff; @@ -104,8 +104,11 @@ const Check = ({ children, ...props }) => ( `} {...props} > - <Flex alignItems='center'> - <FeatherIcon display='inline-flex' pr={2} icon='Check' /> + <Flex css={theme({ alignItems: 'center' })}> + <FeatherIcon + css={theme({ display: 'inline-flex', pr: 2 })} + icon='Check' + /> <Text as='span'>{children}</Text> </Flex> </Text> @@ -123,62 +126,68 @@ export const createPricingTable = Checkout => { return ( <Flex - flexDirection={['column', 'column', 'row', 'row']} - ml='auto' - mr='auto' - px={[0, 0, 4, 4]} - pb={Container.defaultProps.pt} + css={theme({ + flexDirection: ['column', 'column', 'row', 'row'], + mx: 'auto', + px: [0, 0, 4, 4], + pb: [5, 5, 6, 6] + })} {...props} > - <FreePricingBox my={[0, 0, 5, 5]}> - <Subhead fontSize={[3, 3, 4, 4]}>Free</Subhead> + <FreePricingBox css={theme({ my: [0, 0, 5, 5] })}> + <Subhead css={theme({ fontSize: [3, 3, 4, 4] })}>Free</Subhead> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <Text> {FREE_PLAN_RATE_LIMIT} <Requests suffix='day' /> </Text> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <PriceMonthly>0</PriceMonthly> </Box> </Box> - <Box as='ul' m={0} pl={[3, 3, 4, 4]} pt={4} textAlign='left'> - <Check pt={2}> + <Box + as='ul' + css={theme({ m: 0, pl: [3, 3, 4, 4], pt: 4, textAlign: 'left' })} + > + <Check css={theme({ pt: 2 })}> <PricingLink href='/sdk'>Microlink SDK</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/pdf'>Microlink PDF</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/insights'>Microlink insights</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/recipes'>Microlink recipes</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/meta'>Microlink metadata</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/screenshot'>Microlink screenshot</PricingLink> </Check> </Box> - <Flex justifyContent='center' pt={4}> - <ArrowLink href='/docs/api/getting-started/overview' fontSize={2}> + <Flex css={theme({ justifyContent: 'center', pt: 4, fontSize: 2 })}> + <ArrowLink href='/docs/api/getting-started/overview'> Get started </ArrowLink> </Flex> </FreePricingBox> <ProPricingBoxGradient> - <ProPricingBox flex={1} px={[3, 3, 5, 5]} py={[4, 4, 6, 6]}> - <Subhead fontSize={[3, 3, 4, 4]}>Pro</Subhead> + <ProPricingBox + css={theme({ flex: 1, px: [3, 3, 5, 5], py: [4, 4, 6, 6] })} + > + <Subhead css={theme({ fontSize: [3, 3, 4, 4] })}>Pro</Subhead> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <Text> <PricePicker onChange={setPlan} /> <Requests suffix='month' /> </Text> - <Box pt='26px'> + <Box css={theme({ pt: '26px' })}> <Text fontSize={0}> <PriceMonthly> <Highlight as='span'>{humanMonthlyPrice}</Highlight> @@ -187,26 +196,29 @@ export const createPricingTable = Checkout => { </Box> </Box> - <Box as='ul' m={0} pl={[3, 3, 4, 4]} pt={4} textAlign='left'> + <Box + as='ul' + css={theme({ m: 0, pl: [3, 3, 4, 4], pt: 4, textAlign: 'left' })} + > <Check>Everything in Free</Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/docs/api/parameters/ttl'> Configurable TTL </PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/docs/api/parameters/headers'> Custom HTTP headers </PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/docs/api/parameters/proxy'> Automatic proxy resolution </PricingLink> </Check> </Box> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <Checkout planId={planId} canonicalUrl={canonicalUrl} @@ -216,37 +228,38 @@ export const createPricingTable = Checkout => { </ProPricingBox> </ProPricingBoxGradient> - <EnterprisePricingBox my={[0, 0, 5, 5]}> - <Subhead fontSize={[3, 3, 4, 4]}>Enterprise</Subhead> + <EnterprisePricingBox css={theme({ my: [0, 0, 5, 5] })}> + <Subhead css={theme({ fontSize: [3, 3, 4, 4] })}>Enterprise</Subhead> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <Text>Starts from</Text> - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <PriceMonthly>500</PriceMonthly> </Box> </Box> - <Box as='ul' m={0} pl={[3, 3, 4, 4]} pt={4} textAlign='left'> + <Box + as='ul' + css={theme({ m: 0, pl: [3, 3, 4, 4], pt: 4, textAlign: 'left' })} + > <Check>Everything in Pro</Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/enterprise'>Custom API endpoint</PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/enterprise'> Dedicated CDN distribution </PricingLink> </Check> - <Check pt={2}> + <Check css={theme({ pt: 2 })}> <PricingLink href='/enterprise'> S3 like storage integration </PricingLink> </Check> </Box> - <Flex justifyContent='center' pt={4}> - <ArrowLink href='/enterprise' fontSize={2}> - See details - </ArrowLink> + <Flex css={theme({ justifyContent: 'center', pt: 4, fontSize: 2 })}> + <ArrowLink href='/enterprise'>See details</ArrowLink> </Flex> </EnterprisePricingBox> </Flex> diff --git a/src/components/patterns/Toolbar/ToolbarDesktop.js b/src/components/patterns/Toolbar/ToolbarDesktop.js index cf6695451..7d9a2c9d5 100644 --- a/src/components/patterns/Toolbar/ToolbarDesktop.js +++ b/src/components/patterns/Toolbar/ToolbarDesktop.js @@ -52,7 +52,7 @@ const ToolbarSecondary = ({ isDark, children }) => ( <Flex css={theme({ alignItems: 'center', - justifyContent: 'center', + justifyContent: 'space-between', m: 0, p: 0 })} diff --git a/src/helpers/hoc/with-container.js b/src/helpers/hoc/with-container.js index b757184c6..1b826226a 100644 --- a/src/helpers/hoc/with-container.js +++ b/src/helpers/hoc/with-container.js @@ -1,7 +1,7 @@ import React from 'react' import Box from '../../components/elements/Box' -import { layout } from 'theme' +import { layout, theme } from 'theme' export const CONTAINER_SPACE = { mt: 3, @@ -10,10 +10,11 @@ export const CONTAINER_SPACE = { export const Container = props => ( <Box - maxWidth={['100%', '100%', layout.small, layout.small]} - mr='auto' - ml='auto' - {...CONTAINER_SPACE} + css={theme({ + maxWidth: ['100%', '100%', layout.small, layout.small], + mx: 'auto', + ...CONTAINER_SPACE + })} {...props} /> ) diff --git a/src/helpers/hoc/with-link.js b/src/helpers/hoc/with-link.js index 3a453239a..d213a2c07 100644 --- a/src/helpers/hoc/with-link.js +++ b/src/helpers/hoc/with-link.js @@ -28,6 +28,7 @@ const PrefetchLink = styled(GatsbyLink)` const linkIconWrapper = css` display: inline-flex; + align-items: center; svg { transition: stroke ${transition.medium}; @@ -51,7 +52,7 @@ const Icon = ({ children }) => { }, []) return ( - <Flex css={{ alignItems: 'center', ...linkIconWrapper }}> + <Flex css={linkIconWrapper}> {children} <ExternalIcon ref={ref} size={size} /> </Flex> @@ -106,6 +107,7 @@ export const withLink = Component => { href = '/', title, prefetch = true, + icon, ...props }) => { const [isIntersecting, setIsIntersecting] = useState(false) @@ -147,7 +149,13 @@ export const withLink = Component => { } return ( - <BaseLink href={href} isInternal={isInternal} title={title} {...props}> + <BaseLink + href={href} + icon={icon} + isInternal={isInternal} + title={title} + {...props} + > {children} </BaseLink> ) diff --git a/src/helpers/hoc/with-slug.js b/src/helpers/hoc/with-slug.js index a9a272158..b7ef33c7b 100644 --- a/src/helpers/hoc/with-slug.js +++ b/src/helpers/hoc/with-slug.js @@ -1,12 +1,12 @@ import { slug as slugger } from 'github-slugger' import React, { createElement } from 'react' import styled from 'styled-components' -import { colors } from 'theme' +import { colors, theme } from 'theme' import Svg from '../../components/elements/Svg' const PermalinkIcon = props => ( - <Svg viewBox='0 0 16 16' width='16px' {...props}> + <Svg viewBox='0 0 16 16' width='14px' {...props} css={theme({ ml: 2 })}> <g strokeWidth='1' fill='#000000' stroke='#000000'> <path fill='none' @@ -64,7 +64,7 @@ export const withSlug = Component => { <Component id={id} {...rest}> <AnchorLink href={`#${id}`}>{children}</AnchorLink> <Permalink> - <PermalinkIcon width='14px' ml={2} /> + <PermalinkIcon /> </Permalink> </Component> ) diff --git a/src/helpers/hoc/with-spinner.js b/src/helpers/hoc/with-spinner.js index 81fa7ba27..6a485a17f 100644 --- a/src/helpers/hoc/with-spinner.js +++ b/src/helpers/hoc/with-spinner.js @@ -5,7 +5,7 @@ import Flex from '../../components/elements/Flex' export const withSpinner = ChildComponent => { const SpinnerButton = ({ children, ...props }) => ( <ChildComponent state='hover' {...props}> - <Flex justifyContent='center' textAlign='center'> + <Flex css={{ justifyContent: 'center', textAlign: 'center' }}> {children} </Flex> </ChildComponent> diff --git a/src/helpers/hoc/with-title.js b/src/helpers/hoc/with-title.js index 3862d6ca2..776d734ad 100644 --- a/src/helpers/hoc/with-title.js +++ b/src/helpers/hoc/with-title.js @@ -1,13 +1,13 @@ import { createElement } from 'react' -import { title as titleize } from 'helpers' +import { title as titleizeFn } from 'helpers' export const withTitle = Component => { - const TitleWrapper = props => { - if (typeof props.children !== 'string' || props.titleize === false) { + const TitleWrapper = ({ titleize, omitTitleize, ...props }) => { + if (typeof props.children !== 'string' || titleize === false) { return createElement(Component, props) } - const title = titleize(props.children, props.omitTitleize) + const title = titleizeFn(props.children, omitTitleize) return createElement( Component, diff --git a/src/pages/docs/api/parameters/prerender.md b/src/pages/docs/api/parameters/prerender.md index 012048b51..b3c923aea 100644 --- a/src/pages/docs/api/parameters/prerender.md +++ b/src/pages/docs/api/parameters/prerender.md @@ -3,7 +3,7 @@ title: 'prerender' --- Type: <TypeContainer><Type children='<boolean>'/> | <Type children='<string>'/></TypeContainer><br/> -Default: <Type children='false'/><br/> +Default: <Type children="'auto'"/><br/> Values: <TypeContainer><Type children="'auto'"/> | <Type children='true'/> | <Type children='false'/></TypeContainer> It sets how the content over the target [url](/docs/api/parameters/url) should be fetched. diff --git a/src/pages/formats.js b/src/pages/formats.js index 954599461..b66064e68 100644 --- a/src/pages/formats.js +++ b/src/pages/formats.js @@ -1,6 +1,6 @@ import { Faq, Caption, Layout } from 'components/patterns' import { XCircle, CheckCircle } from 'react-feather' -import { cx, colors, borders, layout } from 'theme' +import { cx, colors, borders, layout, theme } from 'theme' import React, { createElement } from 'react' import { issueUrl } from 'helpers' @@ -35,7 +35,7 @@ const StatusIcon = value => { const color = isPresent ? cx('close') : cx('gray') return createElement( props => ( - <Box pl={2}> + <Box css={theme({ pl: 2 })}> <Icon {...props} /> </Box> ), @@ -58,7 +58,6 @@ const FAQs = props => ( id='information' title='FAQs' caption='Frequently asked questions.' - pb={Container.defaultProps.pt} questions={[ { question: 'What is it?', @@ -97,7 +96,7 @@ const FAQs = props => ( </div> <div> These techniques use tools like{' '} - <Link href='https://ffmpeg.org/'>ffmpeg</Link> or + <Link href='https://ffmpeg.org/'>ffmpeg</Link> or{' '} <Link href='https://github.com/Kikobeats/reachable-url'> reachable-url </Link> @@ -135,10 +134,7 @@ const FAQs = props => ( <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> - . + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link>. </div> </> ) @@ -151,27 +147,42 @@ const FAQs = props => ( const FormatsPage = () => { return ( <Layout> - <Container pt={2} pb={3} justifyContent='center' alignItems='center'> - <Heading px={5} maxWidth={layout.large}> + <Container + css={theme({ + pt: 2, + pb: 3, + justifyContent: 'center', + alignItems: 'center' + })} + > + <Heading css={theme({ px: 5, maxWidth: layout.large })}> Supported formats </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: [layout.small, layout.small, layout.small, layout.small] + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > Tested {formats.length} files, {score} resolved </Caption> <Flex - pt={[3, 3, 4, 4]} - flexDirection='column' - maxWidth={['95vw', '95vw', undefined, undefined]} - style={{ overflowX: 'auto' }} + css={theme({ + pt: [3, 3, 4, 4], + flexDirection: 'column', + maxWidth: ['95vw', '95vw', undefined, undefined], + overflowX: 'auto' + })} > <Flex as='header'> {HEADER.map(({ children, ...props }) => ( - <Text key={children} fontWeight='bold' p={2} {...props}> + <Text + key={children} + css={theme({ fontWeight: 'bold', p: 2 })} + {...props} + > {children} </Text> ))} @@ -180,33 +191,34 @@ const FormatsPage = () => { return ( <Flex key={file.url} - borderTop={`${borders[1]} ${colors.black05}`} - py={2} - css={` - &:hover { - background: ${cx('black025')}; + css={theme({ + borderTop: `${borders[1]} ${colors.black05}`, + py: 2, + _hover: { + bg: 'black025', + color: 'black' } - `} + })} > - <Text style={HEADER[0].style} p={2}> + <Text style={HEADER[0].style} css={theme({ p: 2 })}> <Link href={file.url}>{file.extension}</Link>{' '} </Text> - <Text style={HEADER[1].style} p={2}> + <Text style={HEADER[1].style} css={theme({ p: 2 })}> {file.type} </Text> - <Flex style={HEADER[2].style} p={2}> + <Flex style={HEADER[2].style} css={theme({ p: 2 })}> {StatusIcon(file.size)} </Flex> - <Text style={HEADER[3].style} p={2}> + <Text style={HEADER[3].style} css={theme({ p: 2 })}> <Flex>{StatusIcon(file.height)}</Flex> </Text> - <Text style={HEADER[4].style} p={2}> + <Text style={HEADER[4].style} css={theme({ p: 2 })}> <Flex>{StatusIcon(file.width)}</Flex> </Text> - <Text style={HEADER[5].style} p={2}> + <Text style={HEADER[5].style} css={theme({ p: 2 })}> <Flex>{StatusIcon(file.duration)}</Flex> </Text> - <Text style={HEADER[6].style} p={2}> + <Text style={HEADER[6].style} css={theme({ p: 2 })}> <Flex>{StatusIcon(file.palette)}</Flex> </Text> </Flex> @@ -214,19 +226,22 @@ const FormatsPage = () => { })} </Flex> <Flex - py={Container.defaultProps.pt} - justifyContent='space-between' - alignItems='center' - flexDirection={['column', 'column', 'row', 'row']} - width='100%' - maxWidth={layout.large} - px={4} + css={theme({ + py: [5, 5, 6, 6], + justifyContent: 'space-between', + alignItems: 'center', + flexDirection: ['column', 'column', 'row', 'row'], + width: '100%', + maxWidth: layout.large, + px: 4 + })} > <Subhead>Anything else?</Subhead> - <Box p={[4, 4, 0, 0]}> + <Box css={theme({ p: [4, 4, 0, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') + } > <Caps>Request a format</Caps> </Button> @@ -234,9 +249,12 @@ const FormatsPage = () => { </Flex> </Container> <FAQs - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} /> </Layout> ) diff --git a/src/pages/index.js b/src/pages/index.js index 17a7e9e4f..94aba0337 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,52 +1,28 @@ import { Analytics, Faqs, Hero, Overlay, Pricing } from 'components/pages/home' -import { Meta, Container, Link, Subhead } from 'components/elements' +import { Meta, Link, Subhead } from 'components/elements' import { useFeatures, useSiteMetadata } from 'components/hook' import { Features, Layout } from 'components/patterns' -import { colors, borders } from 'theme' +import { colors, borders, theme } from 'theme' import React from 'react' export const Head = () => <Meta /> const HomePage = () => { - const { - canonicalUrl, - paymentApiKey, - stripeKey, - paymentEndpoint - } = useSiteMetadata() + const { canonicalUrl, stripeKey, paymentEndpoint } = useSiteMetadata() return ( <Layout> - <Hero - css={` - position: relative; - `} - > - {({ color }) => <Overlay color={color} />} - </Hero> - <Analytics - pb={Container.defaultProps.pt} - color='white80' - bg='black' - borderTop={`${borders[1]} ${colors.white20}`} - borderBottom={`${borders[1]} ${colors.white20}`} - /> + <Hero>{({ color }) => <Overlay color={color} />}</Hero> + <Analytics /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - Production ready, - </Subhead> - <Subhead - color='#3e55ff' - width='100%' - textAlign='left' - titleize={false} - > + <Subhead css={{ textAlign: 'left' }}> + Production ready,{' '} + <span css={{ display: 'block', color: '#3e55ff' }}> browser as service - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -60,15 +36,16 @@ const HomePage = () => { /> <Pricing canonicalUrl={canonicalUrl} - apiKey={paymentApiKey} stripeKey={stripeKey} apiEndpoint={paymentEndpoint} /> <Faqs - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - pb={Container.defaultProps.pt} + css={theme({ + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}`, + pb: [5, 5, 6, 6] + })} /> </Layout> ) diff --git a/src/pages/insights.js b/src/pages/insights.js index a16eb7959..49cfa6944 100644 --- a/src/pages/insights.js +++ b/src/pages/insights.js @@ -1,4 +1,4 @@ -import { borders, breakpoints, layout, colors } from 'theme' +import { borders, breakpoints, layout, colors, theme } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -60,30 +60,41 @@ const SUGGESTIONS = [ const getEmbedUrl = (url, embed) => getApiUrl(url, { insights: true, embed })[0] -const Wappalyzer = ({ data, ...props }) => ( +const Wappalyzer = ({ data }) => ( <Flex - borderRadius={2} - border={1} - borderColor='black10' - width={256} - height={96} - m={[1, 1, 2, 2]} - py={3} - px={3} - flexDirection='row' - alignItems='center' - {...props} + css={theme({ + borderRadius: 2, + border: 1, + borderColor: 'black10', + width: 256, + height: 96, + m: [1, 1, 2, 2], + p: 3, + flexDirection: 'row', + alignItems: 'center' + })} > - <Box> + <Box css={{ flexShrink: 0 }}> <Image - width={[30, 30, 40, 40]} + css={theme({ width: [30, 30, 40, 40] })} alt={`${data.name} logo`} src={data.logo} /> </Box> - <Box pl={3}> + <Box css={theme({ pl: 3 })}> <Link href={data.url}>{data.name}</Link> - <Text fontSize={1} color='gray7'> + <Text + css={theme({ + fontSize: 1, + color: 'gray7', + textOverflow: 'ellipsis', + overflow: 'hidden', + display: '-webkit-box', + '-webkit-line-clamp': '2', + '-webkit-box-orient': 'vertical' + })} + title={data.categories.join(', ')} + > {data.categories.join(', ')} </Text> </Box> @@ -91,12 +102,12 @@ const Wappalyzer = ({ data, ...props }) => ( ) const LighthouseReport = props => ( - <Flex flexDirection='column' alignItems='flex-start'> - <Subhead textAlign='left' fontSize={3}> + <Flex css={{ flexDirection: 'column', alignItems: 'flex-start' }}> + <Subhead css={theme({ textAlign: 'left', fontSize: 3 })}> Lighthouse report </Subhead> - <Box pt={3}> - <Text maxWidth={layout.normal}> + <Box css={theme({ pt: 3 })}> + <Text css={{ maxWidth: layout.normal }}> <Link href='https://github.com/GoogleChrome/lighthouse'> Lighthouse </Link>{' '} @@ -104,62 +115,77 @@ const LighthouseReport = props => ( pages. </Text> </Box> - <Flex justifyContent='center' pt={4} width='100%'> + <Flex css={theme({ justifyContent: 'center', pt: 4, width: '100%' })}> <Iframe {...props} /> </Flex> </Flex> ) -const TechnologyStack = ({ technologies, ...props }) => ( - <Flex as='section' flexDirection='column' alignItems='flex-start' {...props}> - <Subhead textAlign='left' fontSize={3}> +const TechnologyStack = ({ technologies }) => ( + <Flex + as='section' + css={{ flexDirection: 'column', alignItems: 'flex-start' }} + > + <Subhead css={theme({ textAlign: 'left', fontSize: 3 })}> Technology Stack </Subhead> - <Box pt={3}> - <Text maxWidth={layout.small}> + <Box css={theme({ pt: 3 })}> + <Text css={{ maxWidth: layout.small }}> Software detected under the target URL after analyzing source code, response headers, script variables and several other </Text> - <Text pt={3}> + <Text css={theme({ pt: 3 })}> Detected{' '} - <Text as='span' fontWeight='bold'> + <Text as='span' css={{ fontWeight: 'bold' }}> {technologies.length} </Text>{' '} technologies behind the site. </Text> </Box> <Flex - pt={4} - mx='auto' - justifyContent='center' - flexDirection='row' - flexWrap='wrap' - width={props.width} + css={theme({ + pt: 4, + mx: 'auto', + justifyContent: 'center', + flexDirection: 'row', + flexWrap: 'wrap' + })} > {technologies.map(data => ( <Wappalyzer key={data.name} data={data} /> ))} - {technologies.length % 2 === 1 && <Box m={2} width={256} />} + {technologies.length % 2 === 1 && ( + <Box css={theme({ m: 2, width: 256 })} /> + )} </Flex> </Flex> ) -const LighthousePlaceholder = props => { +const LighthousePlaceholder = ({ height, width }) => { return ( <Flex - border={3} - borderColor='black20' - alignItems='center' - flexDirection='column' - justifyContent='center' - {...props} + css={theme({ + border: 3, + borderColor: 'black20', + alignItems: 'center', + flexDirection: 'column', + justifyContent: 'center', + height, + width + })} > <Image - width={[3, 3, '80%', '80%']} + css={theme({ width: [3, 3, '80%', '80%'] })} alt='Paste your URL' src='https://cdn.microlink.io/logo/lighthouse.png' /> - <Text pt={[2, 2, 4, 4]} fontSize={[2, 2, 4, 4]} color='black40'> + <Text + css={theme({ + pt: [2, 2, 4, 4], + fontSize: [2, 2, 4, 4], + color: 'black40' + })} + > Paste your URL </Text> </Flex> @@ -206,14 +232,20 @@ const LiveDemo = React.memo(function LiveDemo ({ )}` return ( - <Container as='section' alignItems='center' pt={2} pb={[4, 4, 5, 5]}> - <Heading px={5} maxWidth={layout.large}> + <Container + as='section' + css={theme({ alignItems: 'center', pt: 2, pb: [4, 4, 5, 5] })} + > + <Heading css={theme({ px: 5, maxWidth: layout.large })}> Automate web performance </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: [layout.small, layout.small, layout.small, layout.small] + })} > Track site speed & website quality over time — Get performance insights powered by{' '} @@ -222,22 +254,27 @@ const LiveDemo = React.memo(function LiveDemo ({ </Link> . </Caption> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href='/docs/api/parameters/insights'> + <Flex css={theme({ pt: [3, 3, 4, 4], fontSize: [2, 2, 3, 3] })}> + <ArrowLink + css={theme({ pr: [2, 4, 4, 4] })} + href='/docs/api/parameters/insights' + > Get Started </ArrowLink> <ArrowLink href='https://github.com/microlinkhq/browserless'> See on GitHub </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex as='form' - pt={[3, 3, 4, 4]} - pb={4} - mx={[0, 0, 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + pt: [3, 3, 4, 4], + pb: 4, + mx: [0, 0, 'auto', 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'column', 'row', 'row'] + })} onSubmit={event => { event.preventDefault() const { url, ...opts } = values @@ -246,7 +283,10 @@ const LiveDemo = React.memo(function LiveDemo ({ > <Box> <Input - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', 128, 128] + })} iconComponent={ <InputIcon src={data?.logo?.url} @@ -260,13 +300,15 @@ const LiveDemo = React.memo(function LiveDemo ({ type='text' value={inputUrl} onChange={event => setInputUrl(event.target.value)} - width={['100%', '100%', 128, 128]} autoFocus /> </Box> - <Button mt={[3, 0, 0, 0]} ml={[0, 2, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Get it</Caps> + <Button + css={theme({ mt: [3, 0, 0, 0], ml: [0, 2, 2, 2] })} + loading={isLoading} + > + <Caps css={theme({ fontSize: 1 })}>Get it</Caps> </Button> </Flex> </Flex> @@ -276,13 +318,18 @@ const LiveDemo = React.memo(function LiveDemo ({ <Box as='section' id='technology-stack' - width={cardWidth} - flexDirection='column' + css={{ width: cardWidth, flexDirection: 'column' }} > - <Box pt={4}> + <Box css={theme({ pt: 4 })}> <TechnologyStack technologies={technologies} /> </Box> - <Box pt={[1, 1, 2, 2]} width={[256, 256, 528, 528]} mx='auto'> + <Box + css={theme({ + pt: [1, 1, 2, 2], + width: [256, 256, 528, 528], + mx: 'auto' + })} + > <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -298,16 +345,23 @@ const LiveDemo = React.memo(function LiveDemo ({ text: Tooltip.TEXT.COPIED.HTML }) }} - width='100%' - color='black60' + css={theme({ + width: '100%', + color: 'black60', + cursor: 'copy' + })} value={snippetTechnologiesText} /> </Tooltip> </Box> </Box> - <Box as='section' id='lighthouse-report' width={cardWidth} pt={5}> + <Box + as='section' + id='lighthouse-report' + css={theme({ width: cardWidth, pt: 5 })} + > <LighthouseReport width={528} src={reportUrl} /> - <Box pt={[2, 2, 3, 3]} mx='auto'> + <Box css={theme({ pt: [2, 2, 3, 3], mx: 'auto' })}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -315,7 +369,6 @@ const LiveDemo = React.memo(function LiveDemo ({ } > <Input - width='100%' readOnly onClick={event => { event.target.select() @@ -324,8 +377,11 @@ const LiveDemo = React.memo(function LiveDemo ({ text: Tooltip.TEXT.COPIED.HTML }) }} - style={{ cursor: 'copy' }} - color='black60' + css={theme({ + width: '100%', + color: 'black60', + cursor: 'copy' + })} value={snippetInsightsText} /> </Tooltip> @@ -341,79 +397,104 @@ const LiveDemo = React.memo(function LiveDemo ({ ) }) -const Timings = props => { +const Timings = () => { const healthcheck = useHealthcheck() const blockOne = ( - <Flex flexDirection='column' justifyContent='center' alignItems='center'> - <Subhead fontSize={[3, 4, 6, 6]} color='white'> - Measure at scale - </Subhead> - <Subhead fontSize={[3, 4, 6, 6]} color='white60'> - without compromises + <Flex + css={{ + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }} + > + <Subhead css={theme({ fontSize: [3, 4, 6, 6], color: 'white' })}> + Measure at scale{' '} + <span css={theme({ color: 'white60', display: 'block' })}> + without compromises + </span> </Subhead> </Flex> ) const blockTwo = ( <Flex - pt={[4, 4, 5, 5]} - justifyContent={['space-around', 'space-around', 'center', 'center']} - alignItems='baseline' - px={[4, 4, 4, 0]} - width='100%' - maxWidth={layout.normal} + css={theme({ + pt: [4, 4, 5, 5], + justifyContent: ['space-around', 'space-around', 'center', 'center'], + alignItems: 'baseline', + px: [4, 4, 4, 0], + width: '100%', + maxWidth: layout.normal + })} style={{ fontVariantNumeric: 'tabular-nums' }} > <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > {trimMs(healthcheck.insights.p95_pretty)} <Caption - as='div' - ml={2} - color='white' - display='inline' - fontWeight='bold' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > secs </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['P95', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} </Caption> </Flex> <Hide breakpoints={[1, 2, 3]}> - <Box px={3} /> + <Box css={theme({ px: 3 })} /> </Hide> <Hide breakpoints={[0]}> <Flex - display='inline-flex' - px={[2, 2, 2, 5]} - alignItems='center' - justifyContent='center' - flexDirection='column' + css={theme({ + display: 'inline-flex', + px: [2, 2, 2, 5], + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + })} > - <Subhead as='div' color='white' fontWeight='bold'> + <Subhead + forwardedAs='div' + css={theme({ color: 'white', fontWeight: 'bold' })} + > <Average value={healthcheck.insights.avg_pretty} /> </Subhead> - <Caption as='div' color='white60'> + <Caption forwardedAs='div' css={theme({ color: 'white60' })}> {['average', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -421,31 +502,40 @@ const Timings = props => { </Flex> </Hide> <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > 99.9 <Caption - as='div' - ml={2} - color='white' - fontWeight='bold' - display='inline' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} > % </Caption> </Subhead> - <Caption as='div' color='white60' mr={3} pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['SLA', 'Guaranteed'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -456,33 +546,55 @@ const Timings = props => { return ( <Block - as='section' + forwardedAs='section' id='timings' - px={4} - width='100%' flexDirection='column' blockOne={blockOne} blockTwo={blockTwo} - {...props} + css={theme({ + pb: [5, 5, 6, 6], + px: 4, + width: '100%', + borderTop: `${borders[1]} ${colors.white20}`, + borderBottom: `${borders[1]} ${colors.white20}`, + // https://www.gradientmagic.com/collection/radialstripes + backgroundImage: `radial-gradient( + circle at top right, + rgb(36, 9, 119) 0%, + rgb(36, 9, 119) 48%, + rgb(72, 7, 149) 48%, + rgb(72, 7, 149) 53%, + rgb(109, 5, 178) 53%, + rgb(109, 5, 178) 56%, + rgb(145, 2, 208) 56%, + rgb(145, 2, 208) 69%, + rgb(181, 0, 237) 69%, + rgb(181, 0, 237) 100% + )` + })} /> ) } -const Resume = props => ( +const Resume = () => ( <Container as='section' id='resume' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} - {...props} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large], + pb: [5, 5, 6, 6] + })} > - <Subhead px={[3, 3, 4, 4]} variant='gradient'> + <Subhead css={theme({ px: [3, 3, 4, 4] })} variant='gradient'> Global performance insights on click </Subhead> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 4, 0]} - maxWidth={[layout.small, layout.small, layout.normal, layout.normal]} + css={theme({ + pt: [3, 3, 4, 4], + px: [4, 4, 4, 0], + maxWidth: [layout.small, layout.small, layout.normal, layout.normal] + })} > <b>Microlink insights</b> provides first-class support for web performance monitoring, easy to integrate with any existing stack or cloud in just a @@ -492,26 +604,37 @@ const Resume = props => ( <Block blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Audit on-demand' src='https://cdn.microlink.io/illustrations/popularity.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Audit on-demand </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Enable <Link href='/docs/api/parameters/insights'>insights</Link>{' '} query parameter at{' '} <Link href='/docs/api/getting-started/overview'>Microlink API</Link>{' '} for getting a{' '} - <Link - icon - href='https://developers.google.com/web/tools/lighthouse' - > + <Link href='https://developers.google.com/web/tools/lighthouse'> Lighthouse </Link>{' '} report and technologies detected over the target URL. @@ -523,11 +646,23 @@ const Resume = props => ( <Block flexDirection='row-reverse' blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} textAlign='left' fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Run on the edge </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Never get worried about infrastructure again. Just hit{' '} <Link href='/docs/api/getting-started/overview'>Microlink API</Link>{' '} and we will run a cloud-based browsers for you. @@ -536,8 +671,10 @@ const Resume = props => ( } blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Run on the edge' src='https://cdn.microlink.io/illustrations/networking.svg' /> @@ -545,27 +682,37 @@ const Resume = props => ( /> <Block - pb={Container.defaultProps.pt} blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Simple integration' src='https://cdn.microlink.io/illustrations/abstract-6.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]} textAlign='left'> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Simple integration </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Connect it with{' '} <Link href='https://lighthouse.microlink.io'>Lighthouse</Link> or{' '} - <Link - icon - href='https://github.com/GoogleChrome/lighthouse-ci/blob/master/docs/server.md' - > + <Link href='https://github.com/GoogleChrome/lighthouse-ci/blob/master/docs/server.md'> Lighthouse CI </Link>{' '} for unleashing all the power without compromise. @@ -576,23 +723,31 @@ const Resume = props => ( </Container> ) -const ProductInformation = props => { +const ProductInformation = () => { const healthcheck = useHealthcheck() return ( <Faq - as='section' + forwardedAs='section' id='information' title='Product Information' caption='All the details you need to know about the product.' - pb={Container.defaultProps.pt} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} questions={[ { question: 'What is it?', answer: ( <> <div> - <Text as='span' color='black' fontWeight='bold'> + <Text + as='span' + css={theme({ color: 'black', fontWeight: 'bold' })} + > Microlink insights </Text>{' '} gives you web performance metrics in a simple way using{' '} @@ -619,10 +774,7 @@ const ProductInformation = props => { </div> <div> For getting the report, we run{' '} - <Link - icon - href='https://developers.google.com/web/tools/lighthouse' - > + <Link href='https://developers.google.com/web/tools/lighthouse'> Lighthouse </Link>{' '} in our cloud browser servers, giving you the report obtained @@ -666,16 +818,13 @@ const ProductInformation = props => { <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link> . </div> </> ) } ]} - {...props} /> ) } @@ -709,43 +858,23 @@ const InsightsPage = () => { onSubmit={doFetch} query={query} /> - <Timings - pb={Container.defaultProps.pt} - css={` - /* https://www.gradientmagic.com/collection/radialstripes */ - background-image: radial-gradient( - circle at top right, - rgb(36, 9, 119) 0%, - rgb(36, 9, 119) 48%, - rgb(72, 7, 149) 48%, - rgb(72, 7, 149) 53%, - rgb(109, 5, 178) 53%, - rgb(109, 5, 178) 56%, - rgb(145, 2, 208) 56%, - rgb(145, 2, 208) 69%, - rgb(181, 0, 237) 69%, - rgb(181, 0, 237) 100% - ); - `} - borderTop={`${borders[1]} ${colors.white20}`} - borderBottom={`${borders[1]} ${colors.white20}`} - /> + <Timings /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - You call the API, - </Subhead> - <Subhead - color='rgb(181, 0, 237)' - width='100%' - textAlign='left' - titleize={false} + <Subhead css={{ width: '100%', textAlign: 'left' }}> + You call the API,{' '} + <span + css={{ + display: 'block', + color: 'rgb(181, 0, 237)', + width: '100%', + textAlign: 'left' + }} > we handle the rest. - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -758,11 +887,7 @@ const InsightsPage = () => { features={features} /> <Resume /> - <ProductInformation - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - /> + <ProductInformation /> </> ) }} diff --git a/src/pages/logo.js b/src/pages/logo.js index ba4b651d6..aeb8cdc16 100644 --- a/src/pages/logo.js +++ b/src/pages/logo.js @@ -1,5 +1,5 @@ import { cdnUrl, issueUrl, noop, trimMs } from 'helpers' -import { toPx, borders, layout, colors } from 'theme' +import { toPx, borders, layout, colors, theme } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -114,7 +114,7 @@ const LogoPreview = ({ toClipboard = noop, logo, style, ...props }) => { alt={`logo preview for ${Math.round(style.width)}px`} style={style} src={logo.url === DEFAULT_DATA.logo.url ? logoUri : logo.url} - m={logo.url === DEFAULT_DATA.logo.url ? '2rem' : 0} + css={{ margin: logo.url === DEFAULT_DATA.logo.url ? '2rem' : 0 }} /> </LogoBox> ) @@ -136,17 +136,17 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ const colors = isLoading ? Array.from({ length: 6 }, () => '#fff') : [ - ...new Set( - [] - .concat( - logo.palette, - logo.background_color, - logo.color, - logo.alternative_color - ) - .filter(Boolean) - ) - ] + ...new Set( + [] + .concat( + logo.palette, + logo.background_color, + logo.color, + logo.alternative_color + ) + .filter(Boolean) + ) + ] const LogoComponent = isLoading ? LogoEmpty @@ -157,15 +157,17 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ return ( <> <Hide breakpoints={[1, 2, 3]}> - <Flex justifyContent='center' pb={4}> + <Flex css={theme({ justifyContent: 'center', pb: 4 })}> <LogoComponent logo={logo} style={IMAGE_PREVIEW_STYLE[0]} /> </Flex> <Flex - flexWrap='wrap' - justifyContent='center' - alignItems='center' - maxWidth={IMAGE_PREVIEW_STYLE[0].width * 2} - pb={4} + css={theme({ + flexWrap: 'wrap', + justifyContent: 'center', + alignItems: 'center', + maxWidth: IMAGE_PREVIEW_STYLE[0].width * 2, + pb: 4 + })} > <Choose> <Choose.When condition={colors.length > 0}> @@ -173,12 +175,13 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ return ( <Box key={`${color}_${index}`} - m={1} - height={toPx(LOGO_SIZE / 3)} - title={color} - width={toPx((LOGO_SIZE * 3 * 1) / colors.length)} - border={1} - borderColor='black10' + css={theme({ + m: 1, + height: toPx(LOGO_SIZE / 3), + width: toPx((LOGO_SIZE * 3 * 1) / colors.length), + border: 1, + borderColor: 'black10' + })} style={{ background: color }} /> ) @@ -195,7 +198,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ </Hide> <Hide breakpoints={[0]}> <> - <Flex pb={4}> + <Flex css={theme({ pb: 4, gap: 3 })}> {IMAGE_PREVIEW_STYLE.map((imagePreviewStyle, index) => { return ( <Tooltip @@ -206,8 +209,6 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ } > <LogoComponent - ml={index === 0 ? 0 : 3} - index={index} toClipboard={toClipboard} logo={logo} style={{ ...imagePreviewStyle, cursor: 'pointer' }} @@ -216,7 +217,13 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ ) })} </Flex> - <Flex justifyContent='center' alignItems='center' pb={4}> + <Flex + css={theme({ + justifyContent: 'center', + alignItems: 'center', + pb: 4 + })} + > <Choose> <Choose.When condition={colors.length > 0}> {colors.map((color, index) => { @@ -232,20 +239,26 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ {Tooltip.TEXT.COPY.COLOR(color)} </Tooltip.Content> } + css={theme({ + ml: index !== 0 ? 1 : 0, + cursor: 'default' + })} > <Box - ml={index !== 0 ? 1 : 0} - height={toPx(LOGO_SIZE / 3)} + css={theme({ + height: toPx(LOGO_SIZE / 3), + width: toPx((LOGO_SIZE * 3 * 1) / colors.length), + border: 1, + borderColor: 'black10' + })} title={color} - width={toPx((LOGO_SIZE * 3 * 1) / colors.length)} - border={1} - borderColor='black10' style={{ cursor: 'pointer', background: color }} onClick={() => toClipboard({ copy: color, text: Tooltip.TEXT.COPIED.COLOR(color) - })} + }) + } /> </Tooltip> ) @@ -285,34 +298,45 @@ const LiveDemo = React.memo(function LiveDemo ({ const snippetText = `curl -sL ${embedUrl}` return ( - <Container as='section' alignItems='center' pt={2} pb={[4, 4, 5, 5]}> - <Heading px={[4, 5, 5, 5]} maxWidth={layout.large}> + <Container + as='section' + css={theme({ alignItems: 'center', pt: 2, pb: [4, 4, 5, 5] })} + > + <Heading css={theme({ px: [4, 5, 5, 5], maxWidth: layout.large })}> Hey, oh, logos! </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: [layout.small, layout.small, layout.small, layout.small] + })} > Easily get and embed logos from any website{' '} <LineBreak breakpoints={[1, 2, 3]} /> with our simple, reliable API. </Caption> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href='/docs/api/parameters/meta'> + <Flex css={theme({ pt: [3, 3, 4, 4], fontSize: [2, 2, 3, 3] })}> + <ArrowLink + css={theme({ pr: [2, 4, 4, 4] })} + href='/docs/api/parameters/meta' + > Get Started </ArrowLink> <ArrowLink href='https://github.com/microlinkhq/metascraper'> See on GitHub </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex as='form' - pt={[3, 3, 4, 4]} - pb={4} - mx={[0, 0, 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + pt: [3, 3, 4, 4], + pb: 4, + mx: [0, 0, 'auto', 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'column', 'row', 'row'] + })} onSubmit={event => { event.preventDefault() const url = prependHttp(inputUrl) @@ -321,7 +345,10 @@ const LiveDemo = React.memo(function LiveDemo ({ > <Box> <Input - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', 128, 128] + })} iconComponent={ <InputIcon src={data.logo?.url} @@ -337,24 +364,26 @@ const LiveDemo = React.memo(function LiveDemo ({ type='text' value={inputUrl} onChange={event => setInputUrl(event.target.value)} - width={['100%', '100%', 128, 128]} autoFocus /> </Box> - <Button mt={[3, 0, 0, 0]} ml={[0, 2, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Get it</Caps> + <Button + css={theme({ mt: [3, 0, 0, 0], ml: [0, 2, 2, 2] })} + loading={isLoading} + > + <Caps css={theme({ fontSize: 1 })}>Get it</Caps> </Button> </Flex> </Flex> - <Flex flexDirection='column' alignItems='center'> + <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> <PreviewResponsive isLoading={isLoading} toClipboard={toClipboard} data={data} /> - <Box px={4} width='100%'> + <Box css={theme({ px: 4, width: '100%' })}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -370,9 +399,11 @@ const LiveDemo = React.memo(function LiveDemo ({ text: Tooltip.TEXT.COPIED.HTML }) }} - style={{ cursor: 'copy' }} - width='100%' - color='black60' + css={theme({ + width: '100%', + color: 'black60', + cursor: 'copy' + })} value={snippetText} /> </Tooltip> @@ -383,78 +414,103 @@ const LiveDemo = React.memo(function LiveDemo ({ ) }) -const Timings = props => { +const Timings = () => { const healthcheck = useHealthcheck() const blockOne = ( - <Flex flexDirection='column' justifyContent='center' alignItems='center'> - <Subhead fontSize={[3, 4, 6, 6]} color='white'> - Ready to use. - </Subhead> - <Subhead fontSize={[3, 4, 6, 6]} px={[4, 0, 0, 0]} color='white60'> - Fast. Easy. Reliable. + <Flex + css={{ + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }} + > + <Subhead css={theme({ fontSize: [3, 4, 6, 6], color: 'white' })}> + Ready to use.{' '} + <span css={theme({ display: 'block', color: 'white60' })}> + Fast. Easy. Reliable. + </span> </Subhead> </Flex> ) const blockTwo = ( <Flex - pt={[4, 4, 5, 5]} - justifyContent='center' - alignItems='baseline' - width='100%' - maxWidth={layout.normal} + css={theme({ + pt: [4, 4, 5, 5], + justifyContent: 'center', + alignItems: 'baseline', + width: '100%', + maxWidth: layout.normal + })} style={{ fontVariantNumeric: 'tabular-nums' }} > <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > {trimMs(healthcheck.meta.p95_pretty)} <Caption - as='div' - ml={2} - color='white' - display='inline' - fontWeight='bold' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > secs </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['P95', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} </Caption> </Flex> <Hide breakpoints={[1, 2, 3]}> - <Box px={3} /> + <Box css={theme({ px: 3 })} /> </Hide> <Hide breakpoints={[0]}> <Flex - display='inline-flex' - px={[2, 2, 2, 5]} - alignItems='center' - justifyContent='center' - flexDirection='column' + css={theme({ + display: 'inline-flex', + px: [2, 2, 2, 5], + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + })} > - <Subhead as='div' color='white' fontWeight='bold'> + <Subhead + forwardedAs='div' + css={theme({ color: 'white', fontWeight: 'bold' })} + > <Average value={healthcheck.meta.avg_pretty} /> </Subhead> - <Caption as='div' color='white60'> + <Caption forwardedAs='div' css={theme({ color: 'white60' })}> {['average', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -462,31 +518,40 @@ const Timings = props => { </Flex> </Hide> <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > 99.9 <Caption - as='div' - ml={2} - color='white' - fontWeight='bold' - display='inline' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} > % </Caption> </Subhead> - <Caption as='div' color='white60' mr={3} pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['SLA', 'Guaranteed'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -498,31 +563,77 @@ const Timings = props => { return ( <Block id='timings' - px={4} - width='100%' + forwardedAs='section' flexDirection='column' + css={theme({ + px: 4, + pb: [5, 5, 6, 6], + width: '100%', + // https://www.gradientmagic.com/collection/radialstripes + backgroundImage: ` + radial-gradient( + circle at 69% 86%, + rgba(165, 165, 165, 0.06) 0%, + rgba(165, 165, 165, 0.06) 25%, + rgba(193, 193, 193, 0.06) 25%, + rgba(193, 193, 193, 0.06) 50%, + rgba(221, 221, 221, 0.06) 50%, + rgba(221, 221, 221, 0.06) 75%, + rgba(249, 249, 249, 0.06) 75%, + rgba(249, 249, 249, 0.06) 100% + ), + radial-gradient( + circle at 49% 76%, + rgba(129, 129, 129, 0.06) 0%, + rgba(129, 129, 129, 0.06) 25%, + rgba(164, 164, 164, 0.06) 25%, + rgba(164, 164, 164, 0.06) 50%, + rgba(200, 200, 200, 0.06) 50%, + rgba(200, 200, 200, 0.06) 75%, + rgba(235, 235, 235, 0.06) 75%, + rgba(235, 235, 235, 0.06) 100% + ), + radial-gradient( + circle at 22% 64%, + rgba(173, 173, 173, 0.06) 0%, + rgba(173, 173, 173, 0.06) 25%, + rgba(119, 119, 119, 0.06) 25%, + rgba(119, 119, 119, 0.06) 50%, + rgba(64, 64, 64, 0.06) 50%, + rgba(64, 64, 64, 0.06) 75%, + rgba(10, 10, 10, 0.06) 75%, + rgba(10, 10, 10, 0.06) 100% + ), + linear-gradient(307deg, #d306aa, #030070); + `, + borderTop: `${borders[1]} ${colors.white20}`, + borderBottom: `${borders[1]} ${colors.white20}` + })} blockOne={blockOne} blockTwo={blockTwo} - {...props} /> ) } -const Resume = props => ( +const Resume = () => ( <Container as='section' id='resume' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} - {...props} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large], + pb: [5, 5, 6, 6] + })} > - <Subhead px={[3, 3, 0, 0]} variant='gradient'> + <Subhead css={theme({ px: [3, 3, 0, 0] })} variant='gradient'> Logo for the web </Subhead> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 4, 0]} - maxWidth={[layout.small, layout.small, layout.normal, layout.normal]} + css={theme({ + pt: [3, 3, 4, 4], + px: [4, 4, 4, 0], + maxWidth: [layout.small, layout.small, layout.normal, layout.normal] + })} > <b>Microlink logo</b> brings logo detection from any web, including file extension, dimensions, size, and colors. It has been designed to be @@ -531,18 +642,32 @@ const Resume = props => ( <Block blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Always fresh' src='https://cdn.microlink.io/illustrations/genius-idea.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Always fresh </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Consecutive requests will be cached on the edge, respecting{' '} <Link href='/docs/api/parameters/ttl'>ttl</Link>. Consuming cached responses doesn’t affect your plan. @@ -553,11 +678,23 @@ const Resume = props => ( <Block flexDirection='row-reverse' blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} textAlign='left' fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Colors detection </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Enable <Link href='/docs/api/parameters/palette'>palette</Link> to detect dominant colors as part of the logo data properties. </Text> @@ -565,29 +702,44 @@ const Resume = props => ( } blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Colors detection' src='https://cdn.microlink.io/illustrations/workshop.svg' /> } /> <Block - pb={Container.defaultProps.pt} blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Contextual information' src='https://cdn.microlink.io/illustrations/robots.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]} textAlign='left'> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Contextual information </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Whenever is possible data is expanded to bring you more, like file extension, dimensions, size, duration, etc. </Text> @@ -597,23 +749,31 @@ const Resume = props => ( </Container> ) -const ProductInformation = props => { +const ProductInformation = () => { const healthcheck = useHealthcheck() return ( <Faq - as='section' + forwardedAs='section' id='information' title='Product Information' caption='All the details you need to know about the product.' - pb={Container.defaultProps.pt} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} questions={[ { question: 'What is it?', answer: ( <> <div> - <Text as='span' color='black' fontWeight='bold'> + <Text + as='span' + css={theme({ color: 'black', fontWeight: 'bold' })} + > Microlink logo </Text>{' '} is one of features shipped by{' '} @@ -682,16 +842,13 @@ const ProductInformation = props => { <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link> . </div> </> ) } ]} - {...props} /> ) } @@ -725,64 +882,23 @@ const LogoPage = () => { onSubmit={doFetch} query={query} /> - <Timings - pb={Container.defaultProps.pt} - css={` - /* https://www.gradientmagic.com/collection/radialstripes */ - background-image: radial-gradient( - circle at 69% 86%, - rgba(165, 165, 165, 0.06) 0%, - rgba(165, 165, 165, 0.06) 25%, - rgba(193, 193, 193, 0.06) 25%, - rgba(193, 193, 193, 0.06) 50%, - rgba(221, 221, 221, 0.06) 50%, - rgba(221, 221, 221, 0.06) 75%, - rgba(249, 249, 249, 0.06) 75%, - rgba(249, 249, 249, 0.06) 100% - ), - radial-gradient( - circle at 49% 76%, - rgba(129, 129, 129, 0.06) 0%, - rgba(129, 129, 129, 0.06) 25%, - rgba(164, 164, 164, 0.06) 25%, - rgba(164, 164, 164, 0.06) 50%, - rgba(200, 200, 200, 0.06) 50%, - rgba(200, 200, 200, 0.06) 75%, - rgba(235, 235, 235, 0.06) 75%, - rgba(235, 235, 235, 0.06) 100% - ), - radial-gradient( - circle at 22% 64%, - rgba(173, 173, 173, 0.06) 0%, - rgba(173, 173, 173, 0.06) 25%, - rgba(119, 119, 119, 0.06) 25%, - rgba(119, 119, 119, 0.06) 50%, - rgba(64, 64, 64, 0.06) 50%, - rgba(64, 64, 64, 0.06) 75%, - rgba(10, 10, 10, 0.06) 75%, - rgba(10, 10, 10, 0.06) 100% - ), - linear-gradient(307deg, #d306aa, #030070); - `} - borderTop={`${borders[1]} ${colors.white20}`} - borderBottom={`${borders[1]} ${colors.white20}`} - /> + <Timings /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - Effortless API, - </Subhead> - <Subhead - color='#d306aa' - width='100%' - textAlign='left' - titleize={false} + <Subhead css={{ width: '100%', textAlign: 'left' }}> + Effortless API,{' '} + <span + css={{ + display: 'block', + color: '#d306aa', + width: '100%', + textAlign: 'left' + }} > ready to be used. - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -795,11 +911,7 @@ const LogoPage = () => { features={features} /> <Resume /> - <ProductInformation - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - /> + <ProductInformation /> </> ) }} diff --git a/src/pages/meta.js b/src/pages/meta.js index 5a3aff8e6..50953c043 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -1,4 +1,4 @@ -import { layout, breakpoints, transition, colors, borders } from 'theme' +import { layout, breakpoints, transition, colors, borders, theme } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -113,10 +113,12 @@ const JSONProperty = ({ property, data, ...props }) => { const type = children !== null ? 'yes' : 'no' return ( <List.Item - width='100px' - color={type === 'no' ? 'gray' : undefined} + css={theme({ + width: '100px', + color: type === 'no' ? 'gray' : undefined, + fontSize: 1 + })} type={type} - fontSize={1} {...props} > {property} @@ -164,24 +166,32 @@ const LiveDemo = React.memo(function LiveDemo ({ const snippetText = `curl -sL ${embedUrl}` return ( - <Container alignItems='center' pt={2} pb={[4, 4, 5, 5]}> - <Heading px={[4, 5, 5, 5]} maxWidth={layout.large}> + <Container + as='section' + css={theme({ alignItems: 'center', pt: 2, pb: [4, 4, 5, 5] })} + > + <Heading css={theme({ px: [4, 5, 5, 5], maxWidth: layout.large })}> Get unified metadata </Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - px={4} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: layout.small + })} > Structured and normalized data <LineBreak breakpoints={[0, 1]} /> from{' '} <LineBreak breakpoints={[2, 3]} /> Open Graph, Microdata, RDFa, Twitter Cards, JSON-LD, HTML, and more. </Caption> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href='/docs/api/parameters/meta'> + <Flex css={theme({ pt: [3, 3, 4, 4], fontSize: [2, 2, 3, 3] })}> + <ArrowLink + css={theme({ pr: [2, 4, 4, 4] })} + href='/docs/api/parameters/meta' + > Get Started </ArrowLink> <ArrowLink href='https://github.com/microlinkhq/sdk'> @@ -189,14 +199,16 @@ const LiveDemo = React.memo(function LiveDemo ({ </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex as='form' - pt={[3, 3, 4, 4]} - pb={4} - mx={[0, 0, 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + pt: [3, 3, 4, 4], + pb: 4, + mx: [0, 0, 'auto', 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'column', 'row', 'row'] + })} onSubmit={event => { event.preventDefault() const url = prependHttp(inputUrl) @@ -206,7 +218,10 @@ const LiveDemo = React.memo(function LiveDemo ({ <Box> <Input id='meta-demo-url' - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', 128, 128] + })} iconComponent={ <InputIcon src={data?.logo?.url} @@ -219,25 +234,29 @@ const LiveDemo = React.memo(function LiveDemo ({ suggestions={SUGGESTIONS} value={inputUrl} onChange={event => setInputUrl(event.target.value)} - width={['100%', '100%', 128, 128]} autoFocus /> </Box> - <Button mt={[3, 0, 0, 0]} ml={[0, 2, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Get it</Caps> + <Button + css={theme({ mt: [3, 0, 0, 0], ml: [0, 2, 2, 2] })} + loading={isLoading} + > + <Caps css={theme({ fontSize: 1 })}>Get it</Caps> </Button> </Flex> </Flex> <Flex - mx='auto' - flexDirection={['column', 'column', 'row', 'row']} - justifyContent='center' - alignItems='center' - maxWidth={layout.large} + css={theme({ + mx: 'auto', + flexDirection: ['column', 'column', 'row', 'row'], + justifyContent: 'center', + alignItems: 'center', + maxWidth: layout.large + })} > <Hide breakpoints={[0, 1]}> - <List pr={4} pl={0}> + <List css={theme({ pr: 4, pl: 0 })}> {JsonKeysFirstChunk.map(children => ( <JSONProperty key={children} @@ -247,16 +266,14 @@ const LiveDemo = React.memo(function LiveDemo ({ ))} </List> </Hide> - <Flex flexDirection='column' alignItems='center'> + <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> <CodeEditor - pb={4} - width={cardWidth} - height={cardHeight} + css={theme({ pb: 4, width: cardWidth, height: cardHeight })} language='json' > {JSON.stringify(jsonData, null, 2)} </CodeEditor> - <Box pt={4} px={4} width={cardWidth}> + <Box css={theme({ pt: 4, px: 4, width: cardWidth })}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -272,16 +289,14 @@ const LiveDemo = React.memo(function LiveDemo ({ text: Tooltip.TEXT.COPIED.HTML }) }} - style={{ cursor: 'copy' }} - width='100%' - color='black60' + css={theme({ cursor: 'copy', width: '100%', color: 'black60' })} value={snippetText} /> </Tooltip> </Box> </Flex> <Hide breakpoints={[0, 1]}> - <List pl={4}> + <List css={theme({ pl: 4 })}> {JsonKeysSecondChunk.map(children => ( <JSONProperty key={children} @@ -293,14 +308,16 @@ const LiveDemo = React.memo(function LiveDemo ({ </Hide> <Hide breakpoints={[2, 3]}> <List - justifyContent='center' - flexDirection={['row', 'row', 'column', 'column']} - flexWrap={['wrap', 'wrap', undefined, undefined]} - maxWidth={[layout.small, layout.small, undefined, undefined]} - pt={4} - m={0} - pr={[4, 4, 4, 4]} - pl={[4, 4, 0, 0]} + css={theme({ + justifyContent: 'center', + flexDirection: ['row', 'row', 'column', 'column'], + flexWrap: ['wrap', 'wrap', undefined, undefined], + maxWidth: [layout.small, layout.small, undefined, undefined], + pt: 4, + m: 0, + pr: [4, 4, 4, 4], + pl: [4, 4, 0, 0] + })} > {JSON_KEYS.map(children => ( <JSONProperty key={children} property={children} data={data} /> @@ -317,62 +334,72 @@ const Timings = () => { const healthcheck = useHealthcheck() return ( - <AnimatedBox> + <AnimatedBox as='section'> <Block - bg={COLOR} id='timings' - px={4} flexDirection='column' - pb={Container.defaultProps.pt} + css={theme({ + bg: COLOR, + px: 4, + pb: [5, 5, 6, 6] + })} blockOne={ - <Box> - <Subhead fontSize={[3, 4, 6, 6]} color='white'> - On a built-in reliable, - </Subhead> - <Subhead fontSize={[3, 4, 6, 6]} color='white60'> - high performance API. - </Subhead> - </Box> + <Subhead css={theme({ fontSize: [3, 4, 6, 6], color: 'white' })}> + On a built-in reliable,{' '} + <span css={theme({ display: 'block', color: 'white60' })}> + High performance API. + </span> + </Subhead> } blockTwo={ <Flex - pt={[4, 4, 5, 5]} - justifyContent='center' - alignItems='baseline' - width='100%' - maxWidth={layout.normal} + css={theme({ + pt: [4, 4, 5, 5], + justifyContent: 'center', + alignItems: 'baseline', + width: '100%', + maxWidth: layout.normal + })} style={{ fontVariantNumeric: 'tabular-nums' }} > <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > {trimMs(healthcheck.meta.p95_pretty)} <Caption - as='div' - ml={2} - color='white' - display='inline' - fontWeight='bold' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > secs </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption + forwardedAs='div' + css={theme({ color: 'white60', pt: 2 })} + > {['P95', 'response time'].map(children => ( <Caps key={children} - fontWeight='bold' - fontSize={[0, 2, 2, 2]} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} > {children} </Caps> @@ -380,25 +407,32 @@ const Timings = () => { </Caption> </Flex> <Hide breakpoints={[1, 2, 3]}> - <Box px={3} /> + <Box css={theme({ px: 3 })} /> </Hide> <Hide breakpoints={[0]}> <Flex - display='inline-flex' - px={[2, 2, 2, 5]} - alignItems='center' - justifyContent='center' - flexDirection='column' + css={theme({ + display: 'inline-flex', + px: [2, 2, 2, 5], + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + })} > - <Subhead as='div' color='white' fontWeight='bold'> + <Subhead + forwardedAs='div' + css={theme({ color: 'white', fontWeight: 'bold' })} + > <Average value={healthcheck.meta.avg_pretty} /> </Subhead> - <Caption as='div' color='white60'> + <Caption forwardedAs='div' css={theme({ color: 'white60' })}> {['average', 'response time'].map(children => ( <Caps key={children} - fontWeight='bold' - fontSize={[0, 2, 2, 2]} + css={theme({ + fontWeight: 'bold', + fontSize: [0, 2, 2, 2] + })} > {children} </Caps> @@ -407,34 +441,42 @@ const Timings = () => { </Flex> </Hide> <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > 99.9 <Caption - as='div' - ml={2} - color='white' - fontWeight='bold' - display='inline' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} > % </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption + forwardedAs='div' + css={theme({ color: 'white60', pt: 2 })} + > {['SLA', 'Guaranteed'].map(children => ( <Caps key={children} - fontWeight='bold' - fontSize={[0, 2, 2, 2]} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} > {children} </Caps> @@ -450,21 +492,25 @@ const Timings = () => { ) } -const Resume = props => ( +const Resume = () => ( <Container as='section' id='resume' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} - {...props} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large], + pb: [5, 5, 6, 6] + })} > - <Subhead px={[3, 3, 0, 0]} variant='gradient'> + <Subhead css={theme({ px: [3, 3, 0, 0] })} variant='gradient'> Turns websites into data </Subhead> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 4, 0]} - maxWidth={[layout.small, layout.small, layout.normal, layout.normal]} + css={theme({ + pt: [3, 3, 4, 4], + px: [4, 4, 4, 0], + maxWidth: [layout.small, layout.small, layout.normal, layout.normal] + })} > <b>Microlink meta</b> extracts structured data from any website. Enter a URL, receive information. Get relevant information from any link & easily @@ -474,18 +520,32 @@ const Resume = props => ( <Block blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Unified metadata' src='https://cdn.microlink.io/illustrations/abstract-delivery.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Unified metadata </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Get normalized data from multiple sources using Open Graph, Microdata, RDFa, Twitter Cards, JSON-LD, HTML, and more. </Text> @@ -494,14 +554,25 @@ const Resume = props => ( /> <Block - pt={Container.defaultProps.pt} flexDirection='row-reverse' blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} textAlign='left' fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Contextual information </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Whenever is possible data is expanded to bring you more, like file extension, dimensions, size, duration, etc. </Text> @@ -509,7 +580,10 @@ const Resume = props => ( } blockOne={ <Image - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Contextual information' src='https://cdn.microlink.io/illustrations/robots.svg' /> @@ -517,21 +591,34 @@ const Resume = props => ( /> <Block - pb={Container.defaultProps.pt} blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Easily consumable' src='https://cdn.microlink.io/illustrations/abstract-page-is-under-construction.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]} textAlign='left'> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Easily consumable </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Turn any link into a rich media and easily add it to your UI using{' '} <Link href='/sdk'>Microlink SDK</Link>, with{' '} <Link href='/docs/api/parameters/iframe/#providers-supported'> @@ -545,20 +632,28 @@ const Resume = props => ( </Container> ) -const ProductInformation = props => ( +const ProductInformation = () => ( <Faq - as='section' + forwardedAs='section' id='information' title='Product Information' caption='All the details you need to know about the product.' - pb={Container.defaultProps.pt} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} questions={[ { question: 'What is it?', answer: ( <> <div> - <Text as='span' color='black' fontWeight='bold'> + <Text + as='span' + css={theme({ color: 'black', fontWeight: 'bold' })} + > Microlink meta </Text>{' '} is a data extraction service that take a URL as input, giving you @@ -626,16 +721,12 @@ const ProductInformation = props => ( <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> - . + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link>. </div> </> ) } ]} - {...props} /> ) @@ -673,21 +764,21 @@ const MetaPage = () => { /> <Timings /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - Great power, - </Subhead> - <Subhead - color={COLOR} - width='100%' - textAlign='left' - titleize={false} + <Subhead css={{ width: '100%', textAlign: 'left' }}> + Great power,{' '} + <span + css={{ + display: 'block', + color: COLOR, + width: '100%', + textAlign: 'left' + }} > less responsibility. - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -701,11 +792,7 @@ const MetaPage = () => { features={features} /> <Resume /> - <ProductInformation - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - /> + <ProductInformation /> </> ) }} diff --git a/src/pages/pdf.js b/src/pages/pdf.js index b1679d3e2..c28e27682 100644 --- a/src/pages/pdf.js +++ b/src/pages/pdf.js @@ -1,5 +1,5 @@ import { Minimize as MinimizeIcon, Book as BookIcon } from 'react-feather' -import { borders, breakpoints, layout, colors } from 'theme' +import { borders, breakpoints, layout, colors, theme } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -61,23 +61,32 @@ const SUGGESTIONS = [ const getEmbedUrl = url => getApiUrl(url, { pdf: true, embed: 'pdf.url' })[0] -const PDFPlaceholder = props => { +const PDFPlaceholder = ({ height, width }) => { return ( <Flex - border={3} - borderColor='black20' - alignItems='center' - flexDirection='column' - justifyContent='center' - {...props} + css={theme({ + border: 3, + borderColor: 'black20', + alignItems: 'center', + flexDirection: 'column', + justifyContent: 'center', + height, + width + })} > <Image - width={[3, 3, '60%', '60%']} + css={theme({ width: [3, 3, '60%', '60%'] })} style={{ opacity: 0.3, filter: 'grayscale(100%)' }} alt='Paste your URL' src='https://cdn.microlink.io/illustrations/abstract-no-messages.svg' /> - <Text pt={[2, 2, 4, 4]} fontSize={[2, 2, 4, 4]} color='black40'> + <Text + css={theme({ + pt: [2, 2, 4, 4], + fontSize: [2, 2, 4, 4], + color: 'black40' + })} + > Paste your URL </Text> </Flex> @@ -117,43 +126,57 @@ const LiveDemo = React.memo(function LiveDemo ({ const snippetText = `curl -sL ${embedUrl}` return ( - <Container as='section' alignItems='center' pt={2} pb={[4, 4, 5, 5]}> - <Heading px={[4, 5, 5, 5]} maxWidth={layout.large}> + <Container + as='section' + css={theme({ alignItems: 'center', pt: 2, pb: [4, 4, 5, 5] })} + > + <Heading css={theme({ px: [4, 5, 5, 5], maxWidth: layout.large })}> PDF made simple </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: layout.small + })} > Simplify your workflow, use less to get — Turn websites into PDF, in an easy way. </Caption> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href='/docs/api/parameters/pdf'> + <Flex css={theme({ pt: [3, 3, 4, 4], fontSize: [2, 2, 3, 3] })}> + <ArrowLink + css={theme({ pr: [2, 4, 4, 4] })} + href='/docs/api/parameters/pdf' + > Get Started </ArrowLink> <ArrowLink href='https://github.com/microlinkhq/browserless'> See on GitHub </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex as='form' - pt={[3, 3, 4, 4]} - pb={4} - mx={[0, 0, 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + pt: [3, 3, 4, 4], + pb: 4, + mx: [0, 0, 'auto', 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'column', 'row', 'row'] + })} onSubmit={event => { event.preventDefault() const { url, ...opts } = values return onSubmit(url, opts) }} > - <Box mb={[3, 3, 0, 0]}> + <Box css={theme({ mb: [3, 3, 0, 0] })}> <Input - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '102px', '102px'] + })} iconComponent={ <InputIcon src={data?.logo?.url} @@ -169,18 +192,19 @@ const LiveDemo = React.memo(function LiveDemo ({ type='text' value={inputUrl} onChange={event => setInputUrl(event.target.value)} - width={['100%', '100%', '102px', '102px']} autoFocus /> </Box> - <Box ml={[0, 0, 2, 2]} mb={[3, 3, 0, 0]}> + <Box css={theme({ ml: [0, 0, 2, 2], mb: [3, 3, 0, 0] })}> <Input placeholder='Margin' id='pdf-demo-margin' type='text' - fontSize={2} - width={['100%', '100%', '82px', '82px']} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '82px', '82px'] + })} value={inputMargin} onChange={event => setinputMargin(event.target.value)} iconComponent={ @@ -194,13 +218,15 @@ const LiveDemo = React.memo(function LiveDemo ({ /> </Box> - <Box ml={[0, 0, 2, 2]} mb={[3, 3, 0, 0]}> + <Box css={theme({ ml: [0, 0, 2, 2], mb: [3, 3, 0, 0] })}> <Input placeholder='Format' id='pdf-demo-format' type='text' - fontSize={2} - width={['100%', '100%', '84px', '84px']} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '84px', '84px'] + })} value={inputFormat} onChange={event => setinputFormat(event.target.value)} iconComponent={<BookIcon color={colors.black50} width='16px' />} @@ -219,21 +245,20 @@ const LiveDemo = React.memo(function LiveDemo ({ /> </Box> - <Button ml={[0, 0, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Get it</Caps> + <Button css={theme({ ml: [0, 0, 2, 2] })} loading={isLoading}> + <Caps css={theme({ fontSize: 1 })}>Get it</Caps> </Button> </Flex> </Flex> <Choose> <Choose.When condition={!!dataPdfUrl}> - <Flex flexDirection='column' alignItems='center'> + <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> <Iframe - pb={4} width={cardWidth} height={cardHeight} src={`https://docs.google.com/viewer?url=${dataPdfUrl}&embedded=true`} /> - <Box px={4} width={cardWidth}> + <Box css={theme({ mt: 4, px: 4, width: cardWidth })}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -250,8 +275,7 @@ const LiveDemo = React.memo(function LiveDemo ({ }) }} style={{ cursor: 'copy' }} - width='100%' - color='black60' + css={theme({ width: '100%', color: 'black60' })} value={snippetText} /> </Tooltip> @@ -267,79 +291,104 @@ const LiveDemo = React.memo(function LiveDemo ({ ) }) -const Timings = props => { +const Timings = () => { const healthcheck = useHealthcheck() const blockOne = ( - <Flex flexDirection='column' justifyContent='center' alignItems='center'> - <Subhead fontSize={[3, 4, 6, 6]} color='white'> - Speed as feature - </Subhead> - <Subhead fontSize={[3, 4, 6, 6]} color='white60'> - Performance matters + <Flex + css={{ + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }} + > + <Subhead css={theme({ fontSize: [3, 4, 6, 6], color: 'white' })}> + Speed as feature{' '} + <span css={theme({ display: 'block', color: 'white60' })}> + Performance matters + </span> </Subhead> </Flex> ) const blockTwo = ( <Flex - pt={[4, 4, 5, 5]} - justifyContent={['space-around', 'space-around', 'center', 'center']} - alignItems='baseline' - px={[4, 4, 4, 0]} - width='100%' - maxWidth={layout.normal} + css={theme({ + pt: [4, 4, 5, 5], + px: [4, 4, 4, 0], + justifyContent: ['space-around', 'space-around', 'center', 'center'], + alignItems: 'baseline', + width: '100%', + maxWidth: layout.normal + })} style={{ fontVariantNumeric: 'tabular-nums' }} > <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > {trimMs(healthcheck.pdf.p95_pretty)} <Caption - as='div' - ml={2} - color='white' - display='inline' - fontWeight='bold' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > secs </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['P95', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} </Caption> </Flex> <Hide breakpoints={[1, 2, 3]}> - <Box px={3} /> + <Box css={theme({ px: 3 })} /> </Hide> <Hide breakpoints={[0]}> <Flex - display='inline-flex' - px={[2, 2, 2, 5]} - alignItems='center' - justifyContent='center' - flexDirection='column' + css={theme({ + display: 'inline-flex', + px: [2, 2, 2, 5], + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + })} > - <Subhead as='div' color='white' fontWeight='bold'> + <Subhead + forwardedAs='div' + css={theme({ color: 'white', fontWeight: 'bold' })} + > <Average value={healthcheck.pdf.avg_pretty} /> </Subhead> - <Caption as='div' color='white60'> + <Caption forwardedAs='div' css={theme({ color: 'white60' })}> {['average', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -347,31 +396,40 @@ const Timings = props => { </Flex> </Hide> <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > 99.9 <Caption - as='div' - ml={2} - color='white' - fontWeight='bold' - display='inline' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} > % </Caption> </Subhead> - <Caption as='div' color='white60' mr={3} pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['SLA', 'Guaranteed'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -382,33 +440,53 @@ const Timings = props => { return ( <Block - as='section' + forwardedAs='section' id='timings' - px={4} - width='100%' flexDirection='column' + css={theme({ + px: 4, + pb: [5, 5, 6, 6], + width: '100%', + // https://www.gradientmagic.com/collection/radialstripes + backgroundImage: `radial-gradient( + circle at top right, + rgb(62, 41, 84) 0%, + rgb(62, 41, 84) 50%, + rgb(108, 28, 108) 50%, + rgb(108, 28, 108) 60%, + rgb(155, 14, 131) 60%, + rgb(155, 14, 131) 63%, + rgb(201, 1, 155) 63%, + rgb(201, 1, 155) 100% + )`, + borderTop: `${borders[1]} ${colors.white20}`, + borderBottom: `${borders[1]} ${colors.white20}` + })} blockOne={blockOne} blockTwo={blockTwo} - {...props} /> ) } -const Resume = props => ( +const Resume = () => ( <Container as='section' id='resume' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} - {...props} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large], + pb: [5, 5, 6, 6] + })} > - <Subhead px={[3, 3, 6, 6]} variant='gradient'> + <Subhead css={theme({ px: [3, 3, 6, 6] })} variant='gradient'> Generate PDFs from any website </Subhead> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 4, 0]} - maxWidth={[layout.small, layout.small, layout.normal, layout.normal]} + css={theme({ + pt: [3, 3, 4, 4], + px: [4, 4, 4, 0], + maxWidth: [layout.small, layout.small, layout.normal, layout.normal] + })} > <b>Microlink PDF</b> provides a set of powerful features without the headaches of running your own infrastructure, giving you great power, less @@ -418,18 +496,32 @@ const Resume = props => ( <Block blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Always fresh' src='https://cdn.microlink.io/illustrations/genius-idea.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Always fresh </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Consecutive requests will be cached on the edge, respecting{' '} <Link href='/docs/api/parameters/ttl'>ttl</Link>. Consuming cached responses doesn’t affect your plan. @@ -441,11 +533,23 @@ const Resume = props => ( <Block flexDirection='row-reverse' blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} textAlign='left' fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Fully adaptable </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Such as set the paper{' '} <Link href='/docs/api/parameters/pdf/format'>format</Link>, establish a{' '} @@ -459,8 +563,10 @@ const Resume = props => ( } blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Browse automation' src='https://cdn.microlink.io/illustrations/abstract-2.svg' /> @@ -468,21 +574,34 @@ const Resume = props => ( /> <Block - pb={Container.defaultProps.pt} blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Overlay composition' src='https://cdn.microlink.io/illustrations/abstract-page-is-under-construction.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]} textAlign='left'> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Embed directly </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Create PDFs on-demand and{' '} <Link href='/docs/api/parameters/embed'>embed</Link> them directly in your HTML markup, without being worried about code or @@ -494,23 +613,31 @@ const Resume = props => ( </Container> ) -const ProductInformation = props => { +const ProductInformation = () => { const healthcheck = useHealthcheck() return ( <Faq - as='section' + forwardedAs='section' id='information' title='Product Information' caption='All the details you need to know about the product.' - pb={Container.defaultProps.pt} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} questions={[ { question: 'What is it?', answer: ( <> <div> - <Text as='span' color='black' fontWeight='bold'> + <Text + as='span' + css={theme({ color: 'black', fontWeight: 'bold' })} + > Microlink PDF </Text>{' '} is a simple way to generate a PDF from any website using{' '} @@ -578,16 +705,13 @@ const ProductInformation = props => { <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link> . </div> </> ) } ]} - {...props} /> ) } @@ -622,41 +746,23 @@ const PdfPage = () => { onSubmit={doFetch} query={query} /> - <Timings - pb={Container.defaultProps.pt} - css={` - /* https://www.gradientmagic.com/collection/radialstripes */ - background-image: radial-gradient( - circle at top right, - rgb(62, 41, 84) 0%, - rgb(62, 41, 84) 50%, - rgb(108, 28, 108) 50%, - rgb(108, 28, 108) 60%, - rgb(155, 14, 131) 60%, - rgb(155, 14, 131) 63%, - rgb(201, 1, 155) 63%, - rgb(201, 1, 155) 100% - ); - `} - borderTop={`${borders[1]} ${colors.white20}`} - borderBottom={`${borders[1]} ${colors.white20}`} - /> + <Timings /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - You call the API, - </Subhead> - <Subhead - color='#e000ac' - width='100%' - textAlign='left' - titleize={false} + <Subhead css={{ width: '100%', textAlign: 'left' }}> + You call the API,{' '} + <span + css={{ + display: 'block', + color: '#e000ac', + width: '100%', + textAlign: 'left' + }} > we handle the rest. - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -669,11 +775,7 @@ const PdfPage = () => { features={features} /> <Resume /> - <ProductInformation - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - /> + <ProductInformation /> </> ) }} diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index a61d0e64b..66d9f9f2d 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -1,6 +1,6 @@ import { Compass as CompassIcon, Image as ImageIcon } from 'react-feather' import React, { createElement, useMemo, useState } from 'react' -import { borders, breakpoints, layout, colors } from 'theme' +import { borders, breakpoints, layout, colors, theme } from 'theme' import { useTransition, animated } from '@react-spring/web' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -59,12 +59,16 @@ const SMALL_BREAKPOINT = Number(breakpoints[0].replace('px', '')) const ColorPreview = ({ color }) => ( <Box - border={1} - borderColor='black10' - borderRadius={1} - width='14px' - height='14px' - style={{ top: '-2px', position: 'relative', background: color }} + css={theme({ + border: 1, + borderColor: 'black10', + borderRadius: 1, + width: '14px', + height: '14px', + top: '-2px', + position: 'relative' + })} + style={{ background: color }} /> ) @@ -115,7 +119,7 @@ const fromCache = (variations, opts) => { const getEmbedUrl = ({ url, ...opts }) => getApiUrl(url, { ...opts, screenshot: true, embed: 'screenshot.url' })[0] -const DemoSlider = props => { +const DemoSlider = ({ height, width }) => { const [index, setIndex] = useState(0) const next = index => ++index % SUGGESTIONS.length @@ -131,8 +135,8 @@ const DemoSlider = props => { }) return ( - <Box pt={2}> - <Flex style={{ position: 'relative' }} {...props}> + <Box css={theme({ pt: 2 })}> + <Flex css={{ position: 'relative', height, width }}> {transitions((style, index) => { const url = SUGGESTIONS[index].cdnUrl const src = url @@ -151,15 +155,23 @@ const DemoSlider = props => { ) } -const Screenshot = ({ data, cardWidth, cardHeight, ...props }) => { +const Screenshot = ({ data, cardWidth, cardHeight }) => { const imageUrl = get(data, 'screenshot.url') return ( <Link px={3} href={imageUrl} icon={false}> <Image alt={`Microlink screenshot for ${data.url}`} - pl={0} - pr={0} + css={theme({ + my: 4, + pl: 0, + pr: 0, + height: cardHeight, + width: cardWidth, + border: 1, + borderColor: 'black05', + borderRadius: 3 + })} key={imageUrl} src={imageUrl} height={cardHeight} @@ -168,12 +180,9 @@ const Screenshot = ({ data, cardWidth, cardHeight, ...props }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - }} - border={1} - borderColor='black05' - borderRadius={3} - {...props} + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + } + } /> </Link> ) @@ -216,43 +225,54 @@ const LiveDemo = React.memo(function LiveDemo ({ : createElement(ImageIcon, { color: colors.black50, size: '16px' }) return ( - <Container as='section' alignItems='center' pt={2} pb={0}> - <Heading px={[4, 5, 5, 5]} maxWidth={layout.large}> + <Container as='section' css={theme({ alignItems: 'center', pt: 2 })}> + <Heading css={theme({ px: [4, 5, 5, 5], maxWidth: layout.large })}> Easy peasy screenshots </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: layout.small + })} > Say goodbye to complexity. <LineBreak /> Turn websites into screenshots. </Caption> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href='/docs/api/parameters/screenshot'> + <Flex css={theme({ pt: [3, 3, 4, 4], fontSize: [2, 2, 3, 3] })}> + <ArrowLink + css={theme({ pr: [2, 4, 4, 4] })} + href='/docs/api/parameters/screenshot' + > Get Started </ArrowLink> <ArrowLink href='https://github.com/microlinkhq/browserless'> See on GitHub </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex as='form' - pt={[3, 3, 4, 4]} - mx={[0, 0, 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'column', 'row', 'row']} + css={theme({ + pt: [3, 3, 4, 4], + mx: [0, 0, 'auto', 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'column', 'row', 'row'] + })} onSubmit={event => { event.preventDefault() const { url, ...opts } = values return onSubmit(url, opts) }} > - <Box mb={[3, 3, 0, 0]}> + <Box css={theme({ mb: [3, 3, 0, 0] })}> <Input - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '102px', '102px'] + })} iconComponent={ <InputIcon src={data?.logo?.url} @@ -268,18 +288,19 @@ const LiveDemo = React.memo(function LiveDemo ({ type='text' value={inputUrl} onChange={event => setInputUrl(event.target.value)} - width={['100%', '100%', '102px', '102px']} autoFocus /> </Box> - <Box ml={[0, 0, 2, 2]} mb={[3, 3, 0, 0]}> + <Box css={theme({ ml: [0, 0, 2, 2], mb: [3, 3, 0, 0] })}> <Input placeholder='Overlay' id='screenshot-demo-overlay' type='text' - fontSize={2} - width={['100%', '100%', '88px', '88px']} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '88px', '88px'] + })} value={inputOverlay} onChange={event => setInputOverlay(event.target.value)} iconComponent={ @@ -289,13 +310,15 @@ const LiveDemo = React.memo(function LiveDemo ({ /> </Box> - <Box ml={[0, 0, 2, 2]} mb={[3, 3, 0, 0]}> + <Box css={theme({ ml: [0, 0, 2, 2], mb: [3, 3, 0, 0] })}> <Input placeholder='Background' id='screenshot-demo-background' type='text' - fontSize={2} - width={['100%', '100%', '128px', '128px']} + css={theme({ + fontSize: 2, + width: ['100%', '100%', '128px', '128px'] + })} value={inputBg} onChange={event => setInputBg(event.target.value)} iconComponent={backgroundIconComponent} @@ -312,23 +335,27 @@ const LiveDemo = React.memo(function LiveDemo ({ /> </Box> - <Button ml={[0, 0, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Take it</Caps> + <Button css={theme({ ml: [0, 0, 2, 2] })} loading={isLoading}> + <Caps css={theme({ fontSize: 1 })}>Take it</Caps> </Button> </Flex> </Flex> <Choose> <Choose.When condition={!!data}> - <Flex flexDirection='column' alignItems='center' pb={[4, 4, 5, 5]}> + <Flex + css={theme({ + flexDirection: 'column', + alignItems: 'center', + pb: [4, 4, 5, 5] + })} + > <Screenshot - my={4} cardWidth={cardWidth} cardHeight={cardHeight} data={data} - query={values} /> - <Box px={4} width={cardWidth / 1.5}> + <Box css={theme({ px: 4 })} style={{ width: cardWidth / 1.5 }}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ @@ -345,8 +372,7 @@ const LiveDemo = React.memo(function LiveDemo ({ }) }} style={{ cursor: 'copy' }} - width='100%' - color='black60' + css={theme({ width: '100%', color: 'black60' })} value={snippetText} /> </Tooltip> @@ -362,78 +388,103 @@ const LiveDemo = React.memo(function LiveDemo ({ ) }) -const Timings = props => { +const Timings = () => { const healthcheck = useHealthcheck() const blockOne = ( - <Flex flexDirection='column' justifyContent='center' alignItems='center'> - <Subhead fontSize={[3, 4, 6, 6]} color='white'> - Send the URL - </Subhead> - <Subhead fontSize={[3, 4, 6, 6]} color='white60'> - We do the rest + <Flex + css={{ + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }} + > + <Subhead css={theme({ fontSize: [3, 4, 6, 6], color: 'white' })}> + Send the URL{' '} + <span css={theme({ display: 'block', color: 'white60' })}> + We do the rest + </span> </Subhead> </Flex> ) const blockTwo = ( <Flex - pt={[4, 4, 5, 5]} - justifyContent='center' - alignItems='baseline' - width='100%' - maxWidth={layout.normal} + css={theme({ + pt: [4, 4, 5, 5], + justifyContent: 'center', + alignItems: 'baseline', + width: '100%', + maxWidth: layout.normal + })} style={{ fontVariantNumeric: 'tabular-nums' }} > <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > {trimMs(healthcheck.screenshot.p95_pretty)} <Caption - as='div' - ml={2} - color='white' - display='inline' - fontWeight='bold' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} titleize={false} > secs </Caption> </Subhead> - <Caption as='div' color='white60' pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['P95', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} </Caption> </Flex> <Hide breakpoints={[1, 2, 3]}> - <Box px={3} /> + <Box css={theme({ px: 3 })} /> </Hide> <Hide breakpoints={[0]}> <Flex - display='inline-flex' - px={[2, 2, 2, 5]} - alignItems='center' - justifyContent='center' - flexDirection='column' + css={theme({ + display: 'inline-flex', + px: [2, 2, 2, 5], + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + })} > - <Subhead as='div' color='white' fontWeight='bold'> + <Subhead + forwardedAs='div' + css={theme({ color: 'white', fontWeight: 'bold' })} + > <Average value={healthcheck.screenshot.avg_pretty} /> </Subhead> - <Caption as='div' color='white60'> + <Caption forwardedAs='div' css={theme({ color: 'white60' })}> {['average', 'response time'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -441,31 +492,40 @@ const Timings = props => { </Flex> </Hide> <Flex - display='inline-flex' - alignItems='center' - justifyContent='center' - flexDirection='column' + css={{ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column' + }} > <Subhead - as='div' - fontSize={[3, 4, 4, 4]} - color='white' - fontWeight='bold' + forwardedAs='div' + css={theme({ + fontSize: [3, 4, 4, 4], + color: 'white', + fontWeight: 'bold' + })} > 99.9 <Caption - as='div' - ml={2} - color='white' - fontWeight='bold' - display='inline' + forwardedAs='div' + css={theme({ + ml: 2, + color: 'white', + display: 'inline', + fontWeight: 'bold' + })} > % </Caption> </Subhead> - <Caption as='div' color='white60' mr={3} pt={2}> + <Caption forwardedAs='div' css={theme({ color: 'white60', pt: 2 })}> {['SLA', 'Guaranteed'].map(children => ( - <Caps key={children} fontWeight='bold' fontSize={[0, 2, 2, 2]}> + <Caps + key={children} + css={theme({ fontWeight: 'bold', fontSize: [0, 2, 2, 2] })} + > {children} </Caps> ))} @@ -476,32 +536,56 @@ const Timings = props => { return ( <Block + forwardedAs='section' id='timings' - px={4} flexDirection='column' + css={theme({ + px: 4, + pb: [5, 5, 6, 6], + width: '100%', + // https://www.gradientmagic.com/collection/radialstripes + backgroundImage: `radial-gradient( + circle at center right, + #850ba7 0%, + #850ba7 48%, + #a31b91 48%, + #a31b91 52%, + #c12a78 52%, + #c12a78 65%, + #df3a61 65%, + #df3a61 79%, + #fd494a 79%, + #fd494a 100% + )`, + borderTop: `${borders[1]} ${colors.white20}`, + borderBottom: `${borders[1]} ${colors.white20}` + })} blockOne={blockOne} blockTwo={blockTwo} - {...props} /> ) } -const Resume = props => ( +const Resume = () => ( <Container as='section' id='resume' - alignItems='center' - maxWidth={[layout.normal, layout.normal, layout.large, layout.large]} - {...props} + css={theme({ + alignItems: 'center', + maxWidth: [layout.normal, layout.normal, layout.large, layout.large], + pb: [5, 5, 6, 6] + })} > <Subhead variant='gradient'> The fastest way for <LineBreak breakpoints={[1, 2]} /> taking screenshots </Subhead> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 4, 0]} - maxWidth={[layout.small, layout.small, layout.normal, layout.normal]} + css={theme({ + pt: [3, 3, 4, 4], + px: [4, 4, 4, 0], + maxWidth: [layout.small, layout.small, layout.normal, layout.normal] + })} > <b>Microlink screenshot</b> provides a set of powerful features without the headaches of running your own infrastructure, giving you great power, @@ -511,18 +595,32 @@ const Resume = props => ( <Block blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Always fresh' src='https://cdn.microlink.io/illustrations/genius-idea.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Always fresh </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Consecutive requests will be cached on the edge, respecting{' '} <Link href='/docs/api/parameters/ttl'>ttl</Link>. Consuming cached responses doesn’t affect your plan. @@ -534,11 +632,23 @@ const Resume = props => ( <Block flexDirection='row-reverse' blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} textAlign='left' fontSize={[3, 3, 4, 4]}> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Browse automation </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Such as <Link href='/docs/api/parameters/device'>device</Link>{' '} emulation, <Link href='/docs/api/parameters/styles'>styles</Link>,{' '} <Link href='/docs/api/parameters/javascript'>javascript</Link> or{' '} @@ -555,8 +665,10 @@ const Resume = props => ( } blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Browse automation' src='https://cdn.microlink.io/illustrations/robots.svg' /> @@ -564,21 +676,34 @@ const Resume = props => ( /> <Block - pb={Container.defaultProps.pt} blockOne={ <Image - px={[4, 0, 0, 0]} - width={['100%', 6, 7, 8]} + css={theme({ + px: [4, 0, 0, 0], + width: ['100%', 6, 7, 8] + })} alt='Overlay composition' src='https://cdn.microlink.io/illustrations/abstract-page-is-under-construction.svg' /> } blockTwo={ - <Flex px={[4, 0, 0, 0]} flexDirection='column' alignItems='baseline'> - <Subhead pt={[4, 4, 4, 0]} fontSize={[3, 3, 4, 4]} textAlign='left'> + <Flex + css={theme({ + px: [4, 0, 0, 0], + flexDirection: 'column', + alignItems: 'baseline' + })} + > + <Subhead + css={theme({ + pt: [4, 4, 4, 0], + fontSize: [3, 3, 4, 4], + textAlign: 'left' + })} + > Overlay composition </Subhead> - <Text pt={[3, 3, 4, 4]} maxWidth={8}> + <Text css={theme({ pt: [3, 3, 4, 4], maxWidth: 8 })}> Create truly{' '} <Link href='/docs/api/parameters/screenshot/overlay'>overlay</Link>{' '} compositions, setting up the background, browser window, color @@ -590,23 +715,31 @@ const Resume = props => ( </Container> ) -const ProductInformation = props => { +const ProductInformation = () => { const healthcheck = useHealthcheck() return ( <Faq - as='section' + forwardedAs='section' id='information' title='Product Information' caption='All the details you need to know about the product.' - pb={Container.defaultProps.pt} + css={theme({ + pb: [5, 5, 6, 6], + bg: 'pinky', + borderTop: `${borders[1]} ${colors.pinkest}`, + borderBottom: `${borders[1]} ${colors.pinkest}` + })} questions={[ { question: 'What is it?', answer: ( <> <div> - <Text as='span' color='black' fontWeight='bold'> + <Text + as='span' + css={theme({ color: 'black', fontWeight: 'bold' })} + > Microlink screenshot </Text>{' '} is an easy way for taking an screenshot of any website in a @@ -678,16 +811,13 @@ const ProductInformation = props => { <> <div> We’re always available at{' '} - <Link display='inline' href='mailto:hello@microlink.io'> - hello@microlink.io - </Link> + <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link> . </div> </> ) } ]} - {...props} /> ) } @@ -721,43 +851,23 @@ const ScreenshotPage = () => { onSubmit={doFetch} query={query} /> - <Timings - pb={Container.defaultProps.pt} - css={` - /* https://www.gradientmagic.com/collection/radialstripes */ - background-image: radial-gradient( - circle at center right, - #850ba7 0%, - #850ba7 48%, - #a31b91 48%, - #a31b91 52%, - #c12a78 52%, - #c12a78 65%, - #df3a61 65%, - #df3a61 79%, - #fd494a 79%, - #fd494a 100% - ); - `} - borderTop={`${borders[1]} ${colors.white20}`} - borderBottom={`${borders[1]} ${colors.white20}`} - /> + <Timings /> <Features - px={4} + css={theme({ px: 4 })} title={ - <> - <Subhead width='100%' textAlign='left'> - High performance, - </Subhead> - <Subhead - color='#fd494a' - width='100%' - textAlign='left' - titleize={false} + <Subhead css={{ width: '100%', textAlign: 'left' }}> + High performance,{' '} + <span + css={{ + display: 'block', + color: '#fd494a', + width: '100%', + textAlign: 'left' + }} > with no compromises. - </Subhead> - </> + </span> + </Subhead> } caption={ <> @@ -770,11 +880,7 @@ const ScreenshotPage = () => { features={features} /> <Resume /> - <ProductInformation - bg='pinky' - borderTop={`${borders[1]} ${colors.pinkest}`} - borderBottom={`${borders[1]} ${colors.pinkest}`} - /> + <ProductInformation /> </> ) }} diff --git a/src/pages/sdk.js b/src/pages/sdk.js index 8273f8116..cb10a254e 100644 --- a/src/pages/sdk.js +++ b/src/pages/sdk.js @@ -1,5 +1,5 @@ import { useQueryState, useWindowSize } from 'components/hook' -import { layout, breakpoints, transition } from 'theme' +import { layout, breakpoints, transition, theme, toPx } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { cdnUrl, mqlCode } from 'helpers' @@ -130,42 +130,51 @@ const LiveDemo = React.memo(function LiveDemo ({ ].filter(Boolean) return ( - <Container as='section' alignItems='center' pt={2}> - <Heading px={5} titleize={false} maxWidth={layout.large}> + <Container as='section' css={theme({ alignItems: 'center', pt: 2 })}> + <Heading css={theme({ px: 5, maxWidth: layout.large })} titleize={false}> Embed any content </Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + px: 4, + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > - Create beauty link previews — Turn your content into embeddable rich + Create beautiful link previews — Turn your content into embeddable rich media. </Caption> <Flex - alignItems={['center', undefined, undefined, undefined]} - flexDirection={['column', 'row', 'row', 'row']} - pt={[3, 3, 4, 4]} + css={theme({ + alignItems: ['center', null], + flexDirection: ['column', 'row'], + pt: [3, 3, 4, 4], + fontSize: [2, 2, 3, 3], + gap: [3, 4] + })} > - <ArrowLink pr={[0, 4, 4, 4]} href='/docs/sdk/getting-started/overview/'> + <ArrowLink href='/docs/sdk/getting-started/overview/'> Get Started </ArrowLink> - <ArrowLink pt={[3, 0, 0, 0]} href='https://github.com/microlinkhq/sdk'> + <ArrowLink href='https://github.com/microlinkhq/sdk'> See on GitHub </ArrowLink> </Flex> - <Flex justifyContent='center' alignItems='center'> + <Flex css={{ justifyContent: 'center', alignItems: 'center' }}> <Flex - pt={[3, 3, 4, 4]} - pb={[3, 3, 4, 4]} as='form' - mx={[0, 'auto', 'auto', 'auto']} - justifyContent='center' - flexDirection={['column', 'row', 'row', 'row']} + css={theme({ + py: [3, 3, 4, 4], + mx: [0, 'auto'], + justifyContent: 'center', + flexDirection: ['column', 'row', 'row', 'row'], + gap: [3, 2] + })} onSubmit={event => { event.preventDefault() const url = prependHttp(inputUrl) @@ -175,7 +184,10 @@ const LiveDemo = React.memo(function LiveDemo ({ <Box> <Input id='sdk-demo-url' - fontSize={2} + css={theme({ + fontSize: 2, + width: ['100%', '100%', 128, 128] + })} iconComponent={ <InputIcon src={data?.logo?.url} @@ -191,26 +203,29 @@ const LiveDemo = React.memo(function LiveDemo ({ const url = event.target.value setInputUrl(url) }} - width={['100%', '100%', 128, 128]} autoFocus /> </Box> - <Button mt={[3, 0, 0, 0]} ml={[0, 2, 2, 2]} loading={isLoading}> - <Caps fontSize={1}>Embed it</Caps> + <Button loading={isLoading}> + <Caps css={theme({ fontSize: 1 })}>Embed it</Caps> </Button> </Flex> </Flex> <Flex - alignItems='center' - justifyContent='center' - flexDirection='column' - mx='auto' + css={theme({ + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column', + mx: 'auto' + })} > <HeroCard - width={cardWidth} - height={cardHeight} - border={type === 'code' ? 'none' : 1} + css={theme({ + width: cardWidth, + height: cardHeight, + border: type === 'code' ? 'none' : 1 + })} > <Choose> <Choose.When condition={type === 'render'}> @@ -225,8 +240,8 @@ const LiveDemo = React.memo(function LiveDemo ({ </Choose.When> <Choose.When condition={type === 'code'}> <MultiCodeEditor - width='100%' - interactive={{ minHeight: runkitHeight }} + css={{ width: '100%' }} + interactive={{ minHeight: toPx(runkitHeight) }} languages={mqlCode( data.url, { @@ -244,14 +259,16 @@ const LiveDemo = React.memo(function LiveDemo ({ </Choose> </HeroCard> <Flex - width='100%' - pl='15px' - pr='7px' - alignItems={['center', undefined, undefined, undefined]} - justifyContent='space-between' - flexDirection={['column', 'row', 'row', 'row']} + css={theme({ + width: '100%', + pl: '15px', + pr: '7px', + alignItems: ['center', undefined, undefined, undefined], + justifyContent: 'space-between', + flexDirection: ['column', 'row', 'row', 'row'] + })} > - <Box pt={[3, 4, 4, 4]}> + <Box css={theme({ pt: [3, 4] })}> {MODES.map(children => ( <Card.Option key={children} @@ -262,7 +279,7 @@ const LiveDemo = React.memo(function LiveDemo ({ </Card.Option> ))} </Box> - <Box pt={[3, 4, 4, 4]}> + <Box css={theme({ pt: [3, 4] })}> {TYPES.map(children => ( <Card.Option key={children} @@ -284,41 +301,49 @@ const Integrations = () => { <Container as='section' id='integrations' - flexDirection='column' - justifyContent='center' - alignItems='center' - pt={5} + css={theme({ + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + pt: 5 + })} > - <Subhead width='100%'>Built for developers</Subhead> + <Subhead css={{ width: '100%' }}>Built for developers</Subhead> - <Flex pt={5} justifyContent='center' flexWrap='wrap'> + <Flex + css={theme({ + pt: 5, + justifyContent: 'center', + flexWrap: 'wrap', + gap: 4 + })} + > {INTEGRATIONS.map(({ url, logo }) => { const LogoComponent = Icons[logo] return ( <Card key={logo} - flexDirection='column' - justifyContent='center' + css={{ flexDirection: 'column', justifyContent: 'center' }} ratio={[0.45, 0.45, 0.45, 0.45]} - mb={4} - mr={4} > <Link href={url}> - <Flex justifyContent='center'> + <Flex css={{ justifyContent: 'center' }}> <LogoComponent width='40px' /> </Flex> <Flex - pt={4} - width='100%' - justifyContent='center' - flexDirection='column' - alignItems='center' + css={theme({ + pt: 4, + width: '100%', + justifyContent: 'center', + flexDirection: 'column', + alignItems: 'center' + })} > - <Text color='black' fontWeight='bold'> + <Text css={theme({ color: 'black', fontWeight: 'bold' })}> Microlink SDK </Text> - <Text color='black'>for {logo}</Text> + <Text css={theme({ color: 'black' })}>for {logo}</Text> </Flex> </Link> </Card> @@ -326,15 +351,11 @@ const Integrations = () => { })} </Flex> - <Flex - alignItems={['center', undefined, undefined, undefined]} - flexDirection={['column', 'row', 'row', 'row']} - pt={[3, 3, 4, 4]} - > + <Box css={theme({ fontSize: [2, 2, 3], pt: [3, 3, 4] })}> <ArrowLink href='/docs/sdk/getting-started/overview/'> See more integrations </ArrowLink> - </Flex> + </Box> </Container> ) } From 939b1e1c3ec747a34ffbbde4f60ac87ea2451041 Mon Sep 17 00:00:00 2001 From: Brad Adams <hi@breadadams.com> Date: Wed, 15 May 2024 21:11:40 +0200 Subject: [PATCH 10/57] migrate styled-system (company pages) (#1713) * fix: toolbar * fix: `Select` story * feat: update `patterns` components * fix: `PricingTable` styles * fix: `Footer` bottom padding * feat: update `home` * fix: `home` features title text-align * feat: update `markdown` components * feat: cleanup home + Mitigate all warnings about props being passed to dom * feat: migrate `formats` page * feat: migrate `insights` page * feat: migrate `logo` page * feat: migrate `meta` page * fix: invalid bg color * feat: migrate `pdf` page * feat: migrate `screenshot` page * feat: migrate `sdk` page * feat: migrate `blog` listing page * feat: migrate `blog` detail page * feat: migrate `newsletter` page * feat: migrate `oss` page --------- Co-authored-by: Kiko Beats <josefrancisco.verdu@gmail.com> --- src/components/markdown/index.js | 2 - .../patterns/DotsBackground/DotsBackground.js | 13 +-- src/pages/blog/index.js | 94 +++++++++++-------- src/pages/newsletter.js | 37 +++++--- src/pages/oss.js | 78 ++++++++------- src/templates/page.js | 38 +++++--- 6 files changed, 150 insertions(+), 112 deletions(-) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index 9d2af4abd..72ba65498 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -73,8 +73,6 @@ export const H1 = withTitle( lineHeight: [1, 2], textAlign: 'left', mx: 'auto', - mt: 5, - mb: 4 })} `) ) diff --git a/src/components/patterns/DotsBackground/DotsBackground.js b/src/components/patterns/DotsBackground/DotsBackground.js index badadf6fa..4f8dc9923 100644 --- a/src/components/patterns/DotsBackground/DotsBackground.js +++ b/src/components/patterns/DotsBackground/DotsBackground.js @@ -20,16 +20,11 @@ const animateStyle = css` animation-direction: reverse; ` -const Dots = styled(Box).withConfig({ +const DotsBackground = styled(Box).withConfig({ shouldForwardProp: prop => !['animate'].includes(prop) })` - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; + position: relative; min-height: 100vh; - z-index: -1; &:before { content: ''; @@ -46,9 +41,9 @@ const Dots = styled(Box).withConfig({ } ` -Dots.defaultProps = { +DotsBackground.defaultProps = { theme: 'light', animate: true } -export default Dots +export default DotsBackground diff --git a/src/pages/blog/index.js b/src/pages/blog/index.js index 697857d12..3d9b2a6f8 100644 --- a/src/pages/blog/index.js +++ b/src/pages/blog/index.js @@ -1,30 +1,31 @@ -import { textGradient, layout, borders, transition } from 'theme' +import { textGradient, layout, transition, theme } from 'theme' import { Meta, Heading, Link, Flex } from 'components/elements' import { Layout, Caption } from 'components/patterns' import { PostTitle } from 'components/pages/blog' -import styled, { css } from 'styled-components' +import styled from 'styled-components' import { useBlogIndex } from 'components/hook' import { cdnUrl, formatDate } from 'helpers' import { H1 } from 'components/markdown' import TimeAgo from 'react-timeago' -import is from 'styled-is' import React from 'react' -const borderStyle = css` - ${is('borderTop')` - border-top: ${borders[1]} ${({ theme }) => theme.colors.black05}; - `}; - ${is('borderBottom')` - border-bottom: ${borders[1]} ${({ theme }) => theme.colors.black05}; - `}; -` - const CustomFlex = styled(Flex)` - ${borderStyle}; - transition: background-color ${transition.medium}; - &:hover { - background-color: ${({ theme }) => theme.colors.gray0}; - } + ${({ $isLastPost }) => + theme({ + py: 4, + flexDirection: 'column', + alignItems: 'center', + border: 0, + borderColor: 'black05', + borderStyle: 'solid', + borderTopWidth: 1, + borderBottomWidth: $isLastPost ? 1 : 0, + transition: `background-color ${transition.medium}`, + + _hover: { + bg: 'gray0' + } + })} ` const CustomLink = styled(Link)` @@ -43,28 +44,31 @@ const CustomLink = styled(Link)` const BlogPost = ({ title, date, slug, isLastPost }) => { return ( - <CustomLink href={slug} width='100%'> - <CustomFlex - py={4} - alignItems='center' - flexDirection='column' - borderTop - borderBottom={isLastPost} - > + <CustomLink href={slug} css={{ width: '100%' }}> + <CustomFlex $isLastPost={isLastPost}> <H1 - as='h3' - mt={0} - key={title} + forwardedAs='h3' + css={theme({ + mt: 0, + px: 5, + textAlign: 'center', + maxWidth: [ + layout.small, + layout.normal, + layout.normal, + layout.normal + ] + })} titleize={false} - px={5} slug={false} - textAlign='center' - maxWidth={[layout.small, layout.normal, layout.normal, layout.normal]} > <PostTitle>{title}</PostTitle> </H1> - <Caption as='h4' color='black60' textAlign={['center', 'inherit']}> + <Caption + forwardedAs='h4' + css={theme({ color: 'black60', textAlign: ['center', 'inherit'] })} + > {formatDate(date)} (<TimeAgo date={date} />) </Caption> </CustomFlex> @@ -84,22 +88,30 @@ const PageBlog = () => { return ( <Layout> - <Flex pt={2} justifyContent='center'> - <Flex flexDirection='column' align-items='center'> - <Heading maxWidth={layout.large}>Blog</Heading> + <Flex css={theme({ pt: 2, justifyContent: 'center' })}> + <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> + <Heading css={{ maxWidth: layout.large }}>Blog</Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - mb={['-16px', '-16px', '-32px', '-32px']} - px={[4, 4, 0, 0]} + forwardedAs='h2' + css={theme({ + pt: [3, 3, 4, 4], + mb: ['-16px', '-16px', '-32px', '-32px'], + px: [4, 4, 0, 0], + maxWidth: layout.small + })} titleize={false} - maxWidth={layout.small} > Engineering details through Microlink. </Caption> </Flex> </Flex> - <Flex pt={[4, 4, 5, 5]} flexDirection='column' alignItems='center'> + <Flex + css={theme({ + pt: [4, 4, 5, 5], + flexDirection: 'column', + alignItems: 'center' + })} + > {posts.map((post, index) => ( <BlogPost key={post.title} diff --git a/src/pages/newsletter.js b/src/pages/newsletter.js index 23de7135b..1f48e47cd 100644 --- a/src/pages/newsletter.js +++ b/src/pages/newsletter.js @@ -1,5 +1,5 @@ import { Caption, Layout } from 'components/patterns' -import { layout, colors } from 'theme' +import { layout, colors, theme } from 'theme' import { Mail } from 'react-feather' import React from 'react' @@ -19,24 +19,36 @@ export const Head = () => ( const NewsletterPage = () => ( <Layout> - <Container pt={2} justifyContent='center' alignItems='center'> + <Container + css={theme({ pt: 2, justifyContent: 'center', alignItems: 'center' })} + > <Heading>Newsletter</Heading> <Caption - pt={[3, 3, 4, 4]} - px={4} + css={theme({ + pt: [3, null, 4], + px: 4, + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > Early access & updates on new releases. </Caption> - <Flex alignItems='center' justifyContent='center' pt={[0, 0, 4, 4]}> + <Flex + css={theme({ + alignItems: 'center', + justifyContent: 'center', + pt: [0, null, 4] + })} + > <Flex - alignItems={['center', 'center', 'center', 'inherit']} - flexDirection='column' + css={theme({ + alignItems: ['center', null, null, 'inherit'], + flexDirection: 'column' + })} > - <Flex pt={3}> + <Flex css={theme({ pt: 3 })}> <form action='https://microlink.us17.list-manage.com/subscribe/post?u=13504896341022a643b87c538&id=0d0978d452' method='post' @@ -46,8 +58,7 @@ const NewsletterPage = () => ( type='email' name='EMAIL' placeholder='you@domain.com' - width='8rem' - fontSize={0} + css={theme({ width: '8rem', fontSize: 0 })} iconComponent={<Mail color={colors.black40} size={16} />} required /> @@ -55,9 +66,9 @@ const NewsletterPage = () => ( <Button data-event-location='Footer' data-event-name='Be Notified' - ml={2} + css={theme({ ml: 2 })} > - <Caps fontSize={0}>Be Notified</Caps> + <Caps css={theme({ fontSize: 0 })}>Be Notified</Caps> </Button> </Flex> </form> diff --git a/src/pages/oss.js b/src/pages/oss.js index a72016918..e993312d4 100644 --- a/src/pages/oss.js +++ b/src/pages/oss.js @@ -3,7 +3,7 @@ import { Meta, Heading, Link, Text, Flex, Box } from 'components/elements' import { Caption, DotsBackground, Layout } from 'components/patterns' import { cdnUrl, formatNumber } from 'helpers' import { useOss } from 'components/hook' -import { layout } from 'theme' +import { layout, theme } from 'theme' import React from 'react' export const Head = () => ( @@ -17,67 +17,81 @@ export const Head = () => ( const OssPage = () => { const repositories = useOss() return ( - <DotsBackground alignItems='center' justifyContent='center'> + <DotsBackground> <Layout footer={{ bg: 'transparent' }}> <Flex - pt={2} - px={3} - width='100%' - flexDirection='column' - justifyContent='center' - alignItems='center' + css={theme({ + pt: 2, + px: 3, + width: '100%', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + })} > - <Heading titleize={false} maxWidth={layout.large}> + <Heading titleize={false} css={{ maxWidth: layout.large }}> Open Source Software </Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - px={4} + forwardedAs='h2' + css={theme({ + pt: [3, null, 4], + px: 4, + maxWidth: layout.small + })} titleize={false} - maxWidth={layout.small} > It’s our great privilege to build our products using open source software (OSS) and we want to give the same effort back. </Caption> <Flex - pt={[3, 3, 4, 4]} - px={[2, 2, 4, 4]} - width='100%' - maxWidth={layout.normal} - flexDirection='column' + css={theme({ + pt: [3, null, 4], + px: [2, null, 4], + width: '100%', + maxWidth: layout.normal, + flexDirection: 'column' + })} > {repositories.map( ({ name, description, stars, issues, url }, index) => ( <Box key={name} - mb={index !== repositories.length - 1 ? 3 : 0} - borderBottom={1} - borderColor='black05' + css={theme({ + mb: index !== repositories.length - 1 ? 3 : 0, + borderBottom: 1, + borderColor: 'black05' + })} > - <Link color='black' href={url} icon={false}> + <Link css={theme({ color: 'black' })} href={url} icon={false}> <Text as='h3' - fontWeight='bold' - mr={3} - display='inline-block' - width='240px' + css={theme({ + fontWeight: 'bold', + mr: 3, + display: 'inline-block', + width: '240px' + })} > {name} </Text> - <Flex color='black' style={{ float: 'right' }}> - <Flex alignItems='center' mr={3}> - <Text mr={1}>{formatNumber(stars)}</Text> + <Flex css={theme({ color: 'black', float: 'right' })}> + <Flex css={theme({ alignItems: 'center', mr: 3 })}> + <Text css={theme({ mr: 1 })}> + {formatNumber(stars)} + </Text> <StarIcon width='16px' /> </Flex> - <Flex alignItems='center'> - <Text mr={1}>{issues}</Text> + <Flex css={{ alignItems: 'center' }}> + <Text css={theme({ mr: 1 })}>{issues}</Text> <IssueIcon width='16px' /> </Flex> </Flex> - <Text color='black60' mt={2} mb={2} width='80%'> + <Text + css={theme({ color: 'black60', my: 2, width: '80%' })} + > {description} </Text> </Link> diff --git a/src/templates/page.js b/src/templates/page.js index c7d6c32f6..139c76937 100644 --- a/src/templates/page.js +++ b/src/templates/page.js @@ -2,41 +2,49 @@ import { Choose, Flex, Heading, Text, Box } from 'components/elements' import { PostFooter, PostTitle } from 'components/pages/blog' import { Caption, Layout } from 'components/patterns' import Markdown, { H1 } from 'components/markdown' -import { textGradient, layout } from 'theme' +import { textGradient, layout, theme } from 'theme' import { formatDate } from 'helpers' import TimeAgo from 'react-timeago' import React from 'react' const PageTemplate = ({ isBlogPage, date, meta, content }) => ( <Layout {...meta}> - <Box px={3}> + <Box css={theme({ px: 3 })}> <Text as='header' - textAlign='center' - maxWidth={isBlogPage ? layout.normal : 'none'} - ml='auto' - mr='auto' + css={theme({ + textAlign: 'center', + maxWidth: isBlogPage ? layout.normal : 'none', + mx: 'auto' + })} > <Flex - flexDirection='column' - alignItems='center' - justifyContent='center' + css={{ + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center' + }} > <Choose> <Choose.When condition={isBlogPage}> - <H1 textAlign='center' mt={0} css={textGradient}> + <H1 css={{ ...textGradient, textAlign: 'center', marginTop: 0 }}> <PostTitle>{meta.title}</PostTitle> </H1> <Caption - as='h2' - color='black60' - textAlign={['center', 'inherit']} + forwardedAs='h2' + css={theme({ + color: 'black60', + textAlign: ['center', 'inherit'] + })} > {formatDate(date)} (<TimeAgo date={date} />) </Caption> </Choose.When> <Choose.Otherwise> - <Heading mt={0} titleize={false} maxWidth={layout.large}> + <Heading + css={{ marginTop: 0, maxWidth: layout.large }} + titleize={false} + > <PostTitle>{meta.title}</PostTitle> </Heading> </Choose.Otherwise> @@ -44,7 +52,7 @@ const PageTemplate = ({ isBlogPage, date, meta, content }) => ( </Flex> </Text> - <Box pt={[3, 3, 4, 4]}> + <Box css={theme({ pt: [3, null, 4] })}> <Markdown>{content}</Markdown> </Box> From abcf0d75d7781424a9f964d320d0261cd20daea8 Mon Sep 17 00:00:00 2001 From: Brad Adams <hi@breadadams.com> Date: Wed, 15 May 2024 21:33:42 +0200 Subject: [PATCH 11/57] migrate styled-system (developers pages) (#1714) * fix: toolbar * fix: `Select` story * feat: update `patterns` components * fix: `PricingTable` styles * fix: `Footer` bottom padding * feat: update `home` * fix: `home` features title text-align * feat: update `markdown` components * feat: cleanup home + Mitigate all warnings about props being passed to dom * feat: migrate `formats` page * feat: migrate `insights` page * feat: migrate `logo` page * feat: migrate `meta` page * fix: invalid bg color * feat: migrate `pdf` page * feat: migrate `screenshot` page * feat: migrate `sdk` page * feat: migrate `blog` listing page * feat: migrate `blog` detail page * feat: migrate `newsletter` page * feat: migrate `oss` page * feat: migrate `changelog` page * feat: migrate `community` page * feat: migrate `recipe` pages * fix: misc. css fixes * feat: migrate `user-agents` page * feat: migrate `docs` template * fix: syntax --------- Co-authored-by: Kiko Beats <josefrancisco.verdu@gmail.com> --- .../MultiCodeEditor/MultiCodeEditor.js | 7 +- src/components/elements/Toggle/Toggle.js | 4 +- src/components/markdown/index.js | 4 +- .../patterns/DemoLinks/DemoLinks.js | 2 +- src/pages/changelog.js | 26 ++-- src/pages/community.js | 28 +++- src/pages/oss.js | 2 +- src/pages/recipes.js | 136 ++++++++++-------- src/pages/user-agents.js | 55 ++++--- src/templates/doc/index.js | 41 +++--- src/templates/recipe.js | 82 +++++------ 11 files changed, 218 insertions(+), 169 deletions(-) diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js index 2d4891824..4b96d1021 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js @@ -41,12 +41,7 @@ const ActionComponent = ({ <Box css={{ width: '100%' }}> <SelectLanguage isDark={isDark} - css={theme({ - py: '2px', - mx: 'auto', - width: '4.8rem', - mb: 2 - })} + css={theme({ py: '2px' })} value={language} onClick={setLanguage} > diff --git a/src/components/elements/Toggle/Toggle.js b/src/components/elements/Toggle/Toggle.js index 004b3112f..32aa66bb1 100644 --- a/src/components/elements/Toggle/Toggle.js +++ b/src/components/elements/Toggle/Toggle.js @@ -13,7 +13,7 @@ const ButtonToggle = styled(Button)` px: 0, borderRadius: 0, _hover: { - cursor: props => (props.active ? 'auto' : 'pointer'), + cursor: props => (props.$active ? 'auto' : 'pointer'), boxShadow: 'none' } })} @@ -46,7 +46,7 @@ function Toggle ({ onChange, children, defaultValue, ...props }) { px: 3 })} > - <ButtonToggle active={isActive} onClick={setAsActive(value)}> + <ButtonToggle $active={isActive} onClick={setAsActive(value)}> <Caps css={theme({ fontWeight: !isActive ? 'normal' : 'bold', diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index 72ba65498..ba5a8ddaf 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -72,7 +72,9 @@ export const H1 = withTitle( fontSize: `calc(${fontSizes[5]} * 0.75)`, lineHeight: [1, 2], textAlign: 'left', - mx: 'auto', + mt: 5, + mb: 4, + mx: 'auto' })} `) ) diff --git a/src/components/patterns/DemoLinks/DemoLinks.js b/src/components/patterns/DemoLinks/DemoLinks.js index c4a514306..f3d0b4c4e 100644 --- a/src/components/patterns/DemoLinks/DemoLinks.js +++ b/src/components/patterns/DemoLinks/DemoLinks.js @@ -50,7 +50,7 @@ const DemoLinks = ({ children, chunkSize, onClick }) => { return ( <BackgroundSliderContainer as='section' - css={theme({ p: 0, maxWidth: '100%' })} + css={theme({ py: 0, px: 0, maxWidth: '100%' })} > {chunk(links, chunkSize).map((chunkBrands, chunkIndex) => { const isEven = chunkIndex % 2 === 0 diff --git a/src/pages/changelog.js b/src/pages/changelog.js index a67a11b87..864f55e10 100644 --- a/src/pages/changelog.js +++ b/src/pages/changelog.js @@ -3,7 +3,7 @@ import { Caption, Layout } from 'components/patterns' import Markdown, { H1 } from 'components/markdown' import { useChangelog } from 'components/hook' import { cdnUrl } from 'helpers' -import { layout } from 'theme' +import { layout, theme } from 'theme' import React from 'react' export const Head = () => ( @@ -18,20 +18,28 @@ const ChangelogPage = () => { return ( <Layout> - <Container pt={[2, 2, 3, 3]} justifyContent='center' alignItems='center'> - <Heading maxWidth={layout.large}>Changelog</Heading> + <Container + css={theme({ + pt: [2, null, 3], + justifyContent: 'center', + alignItems: 'center' + })} + > + <Heading css={{ maxWidth: layout.large }}>Changelog</Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - mb={['-16px', '-16px', '-32px', '-32px']} - px={[4, 4, 0, 0]} + forwardedAs='h2' + css={theme({ + pt: [3, null, 4], + mb: ['-16px', null, '-32px'], + px: [4, null, 0], + maxWidth: layout.small + })} titleize={false} - maxWidth={layout.small} > We’re constantly improving the platform. See here notable changes in our lineup of products & improvements over the time. </Caption> - <Box pt={[3, 3, 4, 4]}> + <Box css={theme({ pt: [3, null, 4] })}> {changelog.map(({ date, notes }) => { return ( <Box key={date}> diff --git a/src/pages/community.js b/src/pages/community.js index 4342c5bc6..cc9373ca7 100644 --- a/src/pages/community.js +++ b/src/pages/community.js @@ -1,7 +1,7 @@ import { Meta, Heading, Container, Flex } from 'components/elements' import { Caption, Layout, Chat } from 'components/patterns' import { cdnUrl } from 'helpers' -import { layout } from 'theme' +import { layout, theme } from 'theme' import React from 'react' export const Head = () => ( @@ -13,21 +13,35 @@ export const Head = () => ( const CommunityPage = () => ( <Layout> - <Container pt={[2, 2, 3, 3]} justifyContent='center' alignItems='center'> + <Container + css={theme({ + pt: [2, null, 3], + justifyContent: 'center', + alignItems: 'center' + })} + > <Heading>Community</Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - px={4} + forwardedAs='h2' + css={theme({ + pt: [3, null, 4], + px: 4, + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > Direct support via chat with guaranteed response from exclusive top-tier engineers. </Caption> - <Flex alignItems='center' justifyContent='center' pt={[0, 0, 4, 4]}> + <Flex + css={theme({ + alignItems: 'center', + justifyContent: 'center', + pt: [0, null, 4] + })} + > <Chat /> </Flex> </Container> diff --git a/src/pages/oss.js b/src/pages/oss.js index e993312d4..3b521bd14 100644 --- a/src/pages/oss.js +++ b/src/pages/oss.js @@ -18,7 +18,7 @@ const OssPage = () => { const repositories = useOss() return ( <DotsBackground> - <Layout footer={{ bg: 'transparent' }}> + <Layout footer={{ style: { background: 'transparent' } }}> <Flex css={theme({ pt: 2, diff --git a/src/pages/recipes.js b/src/pages/recipes.js index 8eb5ae8c5..f68518e7a 100644 --- a/src/pages/recipes.js +++ b/src/pages/recipes.js @@ -1,9 +1,8 @@ import { DotsBackground, Layout, Caption } from 'components/patterns' -import { colors, space, layout, toPx, toRaw, fontSizes } from 'theme' +import { colors, space, layout, toPx, toRaw, fontSizes, theme } from 'theme' import { cdnUrl, issueUrl, formatNumber } from 'helpers' import React, { useState, useEffect } from 'react' import kebabCase from 'lodash/kebabCase' -import styled from 'styled-components' import { Eye } from 'react-feather' import { getDomain } from 'tldts' @@ -14,7 +13,6 @@ import { Button, Caps, Card, - Container, Flex, Heading, Link, @@ -34,13 +32,6 @@ const width = [...Array(4).keys()].map(() => CARD_WIDTH) const maxWidth = width.map(w => toPx(toRaw(space[3]) * 4 + w * CARDS_PER_ROW)) -const CustomLink = styled(Link)` - color: inherit; - :hover:not([disabled]) { - color: inherit; - } -` - export const Head = () => ( <Meta description='Just start with code. Instant integration, automating any site in a few lines.' @@ -49,7 +40,7 @@ export const Head = () => ( ) const RecipesPage = () => { - const [counters, setCounters] = useState(null) + const [counters, setCounters] = useState() const isLoaded = counters !== null useEffect(() => { @@ -61,46 +52,48 @@ const RecipesPage = () => { }, []) return ( - <DotsBackground alignItems='center' justifyContent='center'> - <Layout footer={{ bg: 'transparent' }}> + <DotsBackground> + <Layout footer={{ style: { background: 'transparent' } }}> <Flex - width='100%' - flexDirection='column' - justifyContent='center' - alignItems='center' - pt={2} - px={3} + css={theme({ + width: '100%', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + pt: 2, + px: 3 + })} > <Flex - flexDirection='column' - alignItems='center' - justifyContent='center' + css={{ + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center' + }} > - <Heading titleize={false} maxWidth={layout.large}> + <Heading titleize={false} css={{ maxWidth: layout.large }}> Recipes </Heading> <Caption - as='h2' - pt={[3, 3, 4, 4]} - pb={[3, 3, 4, 4]} - px={[4, 4, 0, 0]} + forwardedAs='h2' + css={theme({ + py: [3, null, 4], + px: [4, null, 0], + maxWidth: layout.small + })} titleize={false} - maxWidth={[ - layout.small, - layout.small, - layout.small, - layout.small - ]} > Just start with code — Instant integration, automating any site in a few lines. </Caption> </Flex> <Flex - pt={[3, 3, 4, 4]} - maxWidth={maxWidth} - justifyContent='center' - flexWrap='wrap' + css={theme({ + pt: [3, null, 4], + maxWidth, + justifyContent: 'center', + flexWrap: 'wrap' + })} > {recipes.map(([recipeName, meta], index) => { const count = isLoaded && counters[index] @@ -114,64 +107,81 @@ const RecipesPage = () => { return ( <Card key={recipeName} - flexDirection='column' - p={3} - width={width} - height='inherit' - mb={3} - mr={[0, 3, 3, 3]} + css={theme({ + flexDirection: 'column', + p: 3, + width, + height: 'inherit', + mb: 3, + mr: [0, 3], + color: 'black', + _hover: { + color: 'black' + } + })} > - <CustomLink href={`/recipes/${kebabCase(recipeName)}`}> - <Flex alignItems='center'> - <Box pr={2}> + <Link + css={theme({ + color: 'inherit', + _hover: { color: 'inherit' } + })} + href={`/recipes/${kebabCase(recipeName)}`} + > + <Flex css={{ alignItems: 'center' }}> + <Box css={theme({ pr: 2 })}> <Logo isProvider={isProvider} domain={domain} {...meta} /> </Box> - <Text fontSize={1} fontWeight='bold'> + <Text css={theme({ fontSize: 1, fontWeight: 'bold' })}> {meta.name} </Text> </Flex> <Flex> <Text - mt={3} - fontSize={0} - css={` - min-height: 56px; - `} + css={theme({ + mt: 3, + fontSize: 0, + minHeight: '56px' + })} > {description} </Text> </Flex> <Flex - alignItems='center' + css={{ alignItems: 'center' }} style={{ visibility: isLoaded ? 'inherit' : 'hidden' }} > <Eye size={fontSizes[0]} color={colors.black50} /> - <Text pl={1} color={colors.black50} fontSize={0}> + <Text + css={theme({ pl: 1, color: 'black50', fontSize: 0 })} + > {formatNumber(count)} </Text> </Flex> - </CustomLink> + </Link> </Card> ) })} </Flex> <Flex - pt={Container.defaultProps.pt} - justifyContent='space-between' - alignItems='center' - flexDirection={['column', 'column', 'row', 'row']} - width='100%' - maxWidth={layout.large} + css={theme({ + pt: [5, null, 6], + justifyContent: 'space-between', + alignItems: 'center', + flexDirection: ['column', null, 'row'], + width: '100%', + maxWidth: layout.large + })} > <Subhead>Miss something?</Subhead> - <Box pt={[4, 4, 0, 0]}> + <Box css={theme({ pt: [4, null, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') + } > <Caps>Request an Integration</Caps> </Button> diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index 3b6bfba8f..9baed3eb5 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -1,7 +1,7 @@ import { ArrowLink, Caption, Layout } from 'components/patterns' import Markdown from 'components/markdown' import React, { useState } from 'react' -import { layout } from 'theme' +import { layout, theme } from 'theme' import { Toggle, Container, Flex, Heading, Meta } from 'components/elements' @@ -30,44 +30,57 @@ const UserAgentsPage = () => { return ( <Layout> - <Container pt={2} pb={3} justifyContent='center' alignItems='center'> - <Heading px={5} maxWidth={layout.large}> + <Container + css={theme({ + pt: 2, + pb: 3, + justifyContent: 'center', + alignItems: 'center' + })} + > + <Heading css={theme({ px: 5, maxWidth: layout.large })}> User Agents </Heading> <Caption - pt={[3, 3, 4, 4]} - px={['48px', 4, 4, 4]} + forwardedAs='h2' + css={theme({ + pt: [3, null, 4], + px: ['48px', 4], + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > Most common `user-agent` used on Internet. </Caption> <Flex - py={[3, 3, 4, 4]} - flexDirection='column' - justifyContent='center' - alignItems='center' + css={theme({ + py: [3, null, 4], + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + })} > <Toggle - alignItems='center' - justifyContent='center' + css={theme({ alignItems: 'center', justifyContent: 'center' })} defaultValue='User Agent' onChange={value => - setType(value === 'User Agent' ? 'user' : 'crawler')} + setType(value === 'User Agent' ? 'user' : 'crawler') + } > {['User Agent', 'Crawler Agent']} </Toggle> - <Flex pt={[3, 3, 4, 4]}> - <ArrowLink pr={[2, 4, 4, 4]} href={downloadUrl}> - Download - </ArrowLink> + <Flex + css={theme({ + pt: [3, null, 4], + gap: [2, 4], + fontSize: [2, null, 3] + })} + > + <ArrowLink href={downloadUrl}>Download</ArrowLink> <ArrowLink href={githubUrl}>See on GitHub</ArrowLink> </Flex> </Flex> - <Flex - flexDirection='column' - maxWidth={['95vw', '95vw', undefined, undefined]} - > + <Flex css={theme({ flexDirection: 'column', maxWidth: '95vw' })}> <Markdown>{content}</Markdown> </Flex> </Container> diff --git a/src/templates/doc/index.js b/src/templates/doc/index.js index eb4aef021..4366800d3 100644 --- a/src/templates/doc/index.js +++ b/src/templates/doc/index.js @@ -1,7 +1,7 @@ import { getActiveRouteName } from 'components/patterns/Aside/constants' import Markdown, { H1, ProBadge } from 'components/markdown' import { Layout, Aside } from 'components/patterns' -import { fontSizes, colors, layout } from 'theme' +import { fontSizes, layout, theme } from 'theme' import { formatDate } from 'helpers' import React from 'react' @@ -13,44 +13,51 @@ const DocTemplate = ({ meta, content, githubUrl, ...props }) => { return ( <Layout footer={false}> <Container - pt={[0, 0, 0, 4]} - ml={[3, 3, 3, 'auto']} - mr={[3, 3, 3, 'auto']} - px={0} - maxWidth={layout.large} + css={theme({ + pt: [0, null, null, 4], + mx: [3, null, null, 'auto'], + px: 0, + maxWidth: layout.large + })} > <Aside activeRouteName={activeRouteName}> <Choose> <Choose.When condition={!!meta.title}> <Text as='header'> <H1 - mt={[0, 0, 0, `calc(-1 * ${fontSizes[2]})`]} + css={theme({ + mt: [0, null, null, `calc(-1 * ${fontSizes[2]})`], + mb: 1 + })} variant={null} - mb={1} slug={false} > <span>{meta.title}</span> - {meta.isPro && <ProBadge top='12px' ml={2} />} + {meta.isPro && ( + <ProBadge css={theme({ top: '12px', ml: 2 })} /> + )} </H1> </Text> </Choose.When> <Choose.Otherwise> - <Box mt={4} /> + <Box css={theme({ mt: 4 })} /> </Choose.Otherwise> </Choose> <Markdown>{content}</Markdown> <Flex as='footer' - borderTop={1} - borderColor={colors.black05} - justifyContent='space-between' - my={4} - pt={4} + css={theme({ + borderTop: 1, + borderColor: 'black05', + justifyContent: 'space-between', + my: 4, + pt: 4 + })} > - <Text color='gray' fontSize={0}> + <Text css={theme({ color: 'gray', fontSize: 0 })}> Last Edited on {formatDate(meta.date)} </Text> - <Link href={githubUrl} fontSize={0}> + <Link href={githubUrl} css={theme({ fontSize: 0 })}> Edit on GitHub </Link> </Flex> diff --git a/src/templates/recipe.js b/src/templates/recipe.js index fbad30b89..0118bd30b 100644 --- a/src/templates/recipe.js +++ b/src/templates/recipe.js @@ -1,7 +1,7 @@ import { Caption, DotsBackground, ArrowLink, Layout } from 'components/patterns' import { Meta, Text, Box, CodeEditor, Flex, Heading } from 'components/elements' import React, { useState, useEffect } from 'react' -import { fontSizes, colors, layout } from 'theme' +import { fontSizes, colors, layout, theme } from 'theme' import { Logo } from 'components/pages/recipes' import { cdnUrl, formatNumber } from 'helpers' import { Eye } from 'react-feather' @@ -15,7 +15,7 @@ const Description = recipe => { children.push(str.trim()) } else { children.push( - <Box key={domain} ml={2} mr={1}> + <Box key={domain} css={theme({ ml: 2, mr: 1 })}> <Logo {...recipe} /> </Box> ) @@ -54,59 +54,60 @@ const RecipeTemplate = ({ pageContext: recipe }) => { }/${recipe.slug}.js` return ( - <DotsBackground alignItems='center' justifyContent='center'> - <Layout footer={{ bg: 'transparent' }}> + <DotsBackground> + <Layout footer={{ style: { background: 'transparent' } }}> <Flex - px={3} - pt={[2, 2, 3, 3]} - width='100%' - flexDirection='column' - justifyContent='center' - alignItems='center' + css={theme({ + px: 3, + pt: [2, null, 3], + width: '100%', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + })} > - <Heading fontSize={4} pt={[3, 3, 4, 4]} titleize={false}> + <Heading + css={theme({ fontSize: 4, pt: [3, null, 4] })} + titleize={false} + > <Name {...recipe} /> </Heading> <Caption - as='h2' + forwardedAs='h2' titleize={false} - pt={[3, 3, 3, 3]} - px={[4, 4, 0, 0]} - maxWidth={[ - layout.small, - layout.small, - layout.normal, - layout.normal - ]} - style={{ + css={theme({ + pt: 3, + px: [4, null, 0], + maxWidth: [layout.small, null, layout.normal], display: 'flex', alignItems: 'center' - }} + })} > <Description {...recipe} /> </Caption> {isLoaded && ( - <Flex pt={[2, 2, 2, 2]} alignItems='center'> + <Flex css={theme({ pt: 2, alignItems: 'center' })}> <Eye size={fontSizes[2]} color={colors.black50} /> - <Text pl={2} color={colors.black50}> + <Text css={theme({ pl: 2, color: 'black50' })}> {formatNumber(count)} </Text> </Flex> )} <Flex - pt={4} - width='100%' - flexDirection='column' - justifyContent='center' - alignItems='center' + css={theme({ + pt: 4, + width: '100%', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + })} > <CodeEditor title={`${recipe.key}.js`} - width='100%' - maxWidth={layout.small} + css={{ width: '100%', maxWidth: layout.small }} interactive > {recipe.code} @@ -114,19 +115,18 @@ const RecipeTemplate = ({ pageContext: recipe }) => { </Flex> <Flex - alignItems={['center', undefined, undefined, undefined]} - flexDirection={['column', 'row', 'row', 'row']} - pt={[3, 3, 4, 4]} + css={theme({ + alignItems: 'center', + flexDirection: ['column', 'row'], + pt: [3, null, 4], + fontSize: [2, null, 3], + gap: [3, 4] + })} > - <ArrowLink - pr={[0, 4, 4, 4]} - href='/docs/mql/getting-started/overview' - > + <ArrowLink href='/docs/mql/getting-started/overview'> Read docs </ArrowLink> - <ArrowLink pt={[3, 0, 0, 0]} href={gitHubUrl}> - Edit on GitHub - </ArrowLink> + <ArrowLink href={gitHubUrl}>Edit on GitHub</ArrowLink> </Flex> </Flex> </Layout> From bd39d4c7796932cd8df1545085e6ddcfed353ca4 Mon Sep 17 00:00:00 2001 From: Brad Adams <hi@breadadams.com> Date: Thu, 16 May 2024 00:09:30 +0200 Subject: [PATCH 12/57] migrate styled-system (other pages) (#1715) * fix: toolbar * fix: `Select` story * feat: update `patterns` components * fix: `PricingTable` styles * fix: `Footer` bottom padding * feat: update `home` * fix: `home` features title text-align * feat: update `markdown` components * feat: cleanup home + Mitigate all warnings about props being passed to dom * feat: migrate `formats` page * feat: migrate `insights` page * feat: migrate `logo` page * feat: migrate `meta` page * fix: invalid bg color * feat: migrate `pdf` page * feat: migrate `screenshot` page * feat: migrate `sdk` page * feat: migrate `blog` listing page * feat: migrate `blog` detail page * feat: migrate `newsletter` page * feat: migrate `oss` page * feat: migrate `changelog` page * feat: migrate `community` page * feat: migrate `recipe` pages * fix: misc. css fixes * feat: migrate `user-agents` page * feat: migrate `docs` template * feat: migrate `payment` pages * feat: migrate `status` page * feat: migrate `enterprise` page * fix: minor `Container` improvements * fix: use undefined instead of null --------- Co-authored-by: Kiko Beats <josefrancisco.verdu@gmail.com> --- src/components/elements/Container.js | 13 ++---- src/components/elements/PriceMonthly.js | 3 +- src/components/patterns/Block/Block.js | 2 +- src/components/patterns/Layout.js | 11 +---- src/pages/enterprise.js | 40 ++++++++++------ src/pages/insights.js | 2 +- src/pages/payment/index.js | 19 +++++--- src/pages/payment/update.js | 39 +++++++++++----- src/pages/recipes.js | 2 +- src/pages/status.js | 62 ++++++++++++------------- 10 files changed, 103 insertions(+), 90 deletions(-) diff --git a/src/components/elements/Container.js b/src/components/elements/Container.js index 2d7ce17de..b2ae1daa2 100644 --- a/src/components/elements/Container.js +++ b/src/components/elements/Container.js @@ -3,20 +3,13 @@ import { theme } from 'theme' import Flex from './Flex' -const Container = styled(Flex).withConfig({ - shouldForwardProp: prop => !['px'].includes(prop) -})` +const Container = styled(Flex)` ${theme({ flexDirection: 'column', mx: 'auto', - pt: [5, 5, 6, 6], - px: [3, 3, 0, 0] + pt: [5, null, 6], + px: [3, null, 0] })} ` -Container.defaultProps = { - // TODO: can we remove this? - px: [3, 3, 0, 0] -} - export default Container diff --git a/src/components/elements/PriceMonthly.js b/src/components/elements/PriceMonthly.js index ac3bcfd6a..46883d32c 100644 --- a/src/components/elements/PriceMonthly.js +++ b/src/components/elements/PriceMonthly.js @@ -8,8 +8,7 @@ import Label, { labelStyle } from './Label' const Price = styled(Label)` font-weight: bold; - // TODO: it could be [1, 2] - ${theme({ fontSize: [1, 2, 2, 2] })} + ${theme({ fontSize: [1, 2] })} &::before { content: '€'; diff --git a/src/components/patterns/Block/Block.js b/src/components/patterns/Block/Block.js index f95f2277d..1a342b818 100644 --- a/src/components/patterns/Block/Block.js +++ b/src/components/patterns/Block/Block.js @@ -18,7 +18,7 @@ const Block = ({ <Flex css={theme({ justifyContent: 'center', - flexDirection: ['column', 'column', 'column', flexDirection], + flexDirection: ['column', null, null, flexDirection], alignItems: 'center', mx: 'auto', width diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index 3abc3f313..41f57a17a 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -28,10 +28,6 @@ const Layout = ({ onClick, style, theme, - display, - justifyContent, - alignItems, - flexDirection, component = Box, ...props }) => { @@ -65,11 +61,8 @@ const Layout = ({ component, { as: 'main', - justifyContent, - alignItems, - display, - flexDirection, - style: { flex: 1, paddingTop: toolbarHeight } + style: { flex: 1, paddingTop: toolbarHeight }, + ...props }, children )} diff --git a/src/pages/enterprise.js b/src/pages/enterprise.js index 33c1309e9..d61d7347f 100644 --- a/src/pages/enterprise.js +++ b/src/pages/enterprise.js @@ -1,5 +1,5 @@ import { DotsBackground, Caption, Layout } from 'components/patterns' -import { transition, space, gradient, layout } from 'theme' +import { transition, space, gradient, layout, theme as themeProp } from 'theme' import Markdown from 'components/markdown' import { useTheme } from 'components/hook' import styled from 'styled-components' @@ -62,28 +62,35 @@ const EnterprisePage = () => { return ( <DotsBackground theme={theme}> - <Layout theme={theme} footer={{ bg: 'transparent' }}> + <Layout theme={theme} footer={{ style: { background: 'transparent' } }}> <Container - pt={[2, 2, 3, 3]} - justifyContent='center' - alignItems='center' + css={themeProp({ + pt: [2, null, 3], + justifyContent: 'center', + alignItems: 'center' + })} > - <Subhead color={primary}>Microlink for</Subhead> + <Subhead css={{ color: primary }}>Microlink for</Subhead> <Heading>Enterprise</Heading> <Caption - color={primary} - pt={[3, 3, 4, 4]} - px={4} + css={themeProp({ + color: primary, + pt: [3, null, 4], + px: 4, + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > Unleash the maximum performance. Hardware, with the software baked in. </Caption> <Box - pt={[3, 3, 4, 4]} - color={secondary} css={` + ${themeProp({ + pt: [3, null, 4], + color: secondary + })} + b { color: white; } @@ -91,16 +98,19 @@ const EnterprisePage = () => { > <Markdown>{content}</Markdown> </Box> - <Box pt={[2, 2, 3, 3]} color={secondary}> + <Box css={themeProp({ pt: [2, null, 3], color: secondary })}> <GradientButton onClick={() => window.open( 'mailto:hello@microlink.io?subject=Microlink%20Enterprise&body=Hello%2C%20I%20want%20to%20upgrade%20my%20customer%20plan%20to%20Microlink%20Enterprise.%0D%0A%0D%0ACan%20you%20tell%20me%20more%20about%20the%20details%3F%0D%0A%0D%0AThank%20you!%0D%0A', '_blank', 'noopener noreferrer' - )} + ) + } > - <Caps bg='black' px={3} py={2} color={primary}> + <Caps + css={themeProp({ bg: 'black', px: 3, py: 2, color: primary })} + > Get in touch </Caps> </GradientButton> diff --git a/src/pages/insights.js b/src/pages/insights.js index 49cfa6944..267a786dd 100644 --- a/src/pages/insights.js +++ b/src/pages/insights.js @@ -68,7 +68,7 @@ const Wappalyzer = ({ data }) => ( borderColor: 'black10', width: 256, height: 96, - m: [1, 1, 2, 2], + m: [1, null, 2], p: 3, flexDirection: 'row', alignItems: 'center' diff --git a/src/pages/payment/index.js b/src/pages/payment/index.js index 811bf8ffb..39b3ea5ad 100644 --- a/src/pages/payment/index.js +++ b/src/pages/payment/index.js @@ -2,7 +2,7 @@ import { Caption, Layout } from 'components/patterns' import React, { useState, useEffect } from 'react' import { useQueryState } from 'components/hook' import { encode } from 'helpers' -import { layout } from 'theme' +import { layout, theme } from 'theme' import { Confetti, @@ -45,7 +45,7 @@ const getCaption = paymentState => { <> Payment not processed.{' '} <Link - pt={2} + css={theme({ pt: 2 })} href={`mailto:hello@microlink.io?${encode(ERROR_MAIL_OPTS)}`} > Contact us @@ -65,16 +65,21 @@ const PaymentPage = () => { return ( <Layout> - <Container alignItems='center' pt={2}> + <Container css={theme({ alignItems: 'center', pt: 2 })}> {paymentState === PAYMENT_STATE.success && <Confetti />} - <Heading px={5} titleize={false} maxWidth={layout.large}> + <Heading + css={theme({ px: 5, maxWidth: layout.large })} + titleize={false} + > {getTitle(paymentState)} </Heading> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 0, 0]} + css={theme({ + pt: [3, null, 4], + px: [4, null, 0], + maxWidth: layout.small + })} titleize={false} - maxWidth={[layout.small, layout.small, layout.small, layout.small]} > {getCaption(paymentState)} </Caption> diff --git a/src/pages/payment/update.js b/src/pages/payment/update.js index d6163f18d..8ab3019af 100644 --- a/src/pages/payment/update.js +++ b/src/pages/payment/update.js @@ -1,7 +1,15 @@ /* global fetch */ import { useFingerprint, useSiteMetadata, useQueryState } from 'components/hook' -import { colors, fonts, fontWeights, layout, radii, transition } from 'theme' +import { + colors, + fonts, + fontWeights, + layout, + radii, + transition, + theme +} from 'theme' import { Caption, Layout } from 'components/patterns' import { loadStripe } from '@stripe/stripe-js/pure' import React, { useEffect, useState } from 'react' @@ -69,7 +77,10 @@ const getCaption = paymentState => { return ( <> Payment not updated.{' '} - <Link href={`mailto:hello@microlink.io?${encode(ERROR_MAIL_OPTS)}`}> + <Link + css={theme({ pt: 2 })} + href={`mailto:hello@microlink.io?${encode(ERROR_MAIL_OPTS)}`} + > Contact us </Link> . @@ -133,11 +144,10 @@ const CheckoutForm = ({ /> <Button loading={!stripe || paymentState === PAYMENT_STATE.processing} - mt={3} + css={theme({ mt: 3, width: '100%' })} type='submit' - width='100%' > - <Caps fontSize={1}>Update Card</Caps> + <Caps css={theme({ fontSize: 1 })}>Update Card</Caps> </Button> </form> ) @@ -187,21 +197,28 @@ const PaymentUpdatePage = () => { return ( <Layout> - <Container pt={2} justifyContent='center' alignItems='center'> + <Container + css={theme({ alignItems: 'center', justifyContent: 'center', pt: 2 })} + > {paymentState === PAYMENT_STATE.success && <Confetti />} - <Heading px={5} titleize={false} maxWidth={layout.large}> + <Heading + css={theme({ px: 5, maxWidth: layout.large })} + titleize={false} + > {getTitle(isLoading ? PAYMENT_STATE.redirected : paymentState)} </Heading> <Caption - pt={[3, 3, 4, 4]} - px={[4, 4, 0, 0]} + css={theme({ + pt: [3, null, 4], + px: [4, null, 0], + maxWidth: layout.small + })} titleize={false} - maxWidth={layout.small} > {getCaption(isLoading ? PAYMENT_STATE.redirected : paymentState)} </Caption> {!isLoading && !query.status && ( - <Box pt={[3, 3, 4, 4]} width={7}> + <Box css={theme({ pt: [3, null, 4], width: 7 })}> <Elements stripe={stripePromise} options={{ diff --git a/src/pages/recipes.js b/src/pages/recipes.js index f68518e7a..ddc23c7b2 100644 --- a/src/pages/recipes.js +++ b/src/pages/recipes.js @@ -41,7 +41,7 @@ export const Head = () => ( const RecipesPage = () => { const [counters, setCounters] = useState() - const isLoaded = counters !== null + const isLoaded = counters !== undefined useEffect(() => { window diff --git a/src/pages/status.js b/src/pages/status.js index f8fa681ac..a657212f7 100644 --- a/src/pages/status.js +++ b/src/pages/status.js @@ -2,33 +2,25 @@ import { ClusterMonitor, Layout } from 'components/patterns' import { useTheme, useQueryState } from 'components/hook' import { cdnUrl } from 'helpers' import React from 'react' +import { theme as themeProp } from 'theme' -import { - Box, - Choose, - Container, - DotSpinner, - Flex, - Meta, - Text -} from 'components/elements' +import { Box, Choose, DotSpinner, Flex, Meta, Text } from 'components/elements' const THEMES = { light: { color: 'black', bg: 'white' }, dark: { color: 'white', bg: 'black' } } -const Monospace = ({ style, ...props }) => ( +const Monospace = props => ( <Text - fontFamily='monospace' - textAlign='center' - maxWidth={['95vw', '95vw', '100%', '100%']} - style={{ + css={themeProp({ + fontFamily: 'monospace', + textAlign: 'center', + maxWidth: ['95vw', '95vw', '100%', '100%'], whiteSpace: 'pre', overflowY: 'scroll', - margin: 'auto', - ...style - }} + m: 'auto' + })} {...props} /> ) @@ -56,36 +48,40 @@ const StatusPage = () => { theme={theme} style={{ background: bg }} component={Flex} - justifyContent='center' - alignItems='center' - maxWidth='100%' + css={{ justifyContent: 'center', alignItems: 'center' }} > - <Box id='status' px={Container.defaultProps.px}> + <Box id='status' css={themeProp({ px: [3, null, 0] })}> <Choose> <Choose.When condition={isLoading}> <Flex - justifyContent='center' - alignItems='center' - flexDirection={['column', 'column', 'row', 'row']} + css={themeProp({ + justifyContent: 'center', + alignItems: 'center', + flexDirection: ['column', null, 'row'] + })} > <Text - fontWeight='regular' - fontFamily='mono' - lineHeight={0} - fontSize={[4, 4, 4, 7]} - pt={[2, 2, 3, 3]} - color={color} + css={themeProp({ + fontWeight: 'regular', + fontFamily: 'mono', + lineHeight: 0, + fontSize: [4, null, null, 7], + pt: [2, null, 3], + color + })} > Loading <DotSpinner /> </Text> </Flex> </Choose.When> <Choose.Otherwise> - <Monospace color={color}> + <Monospace css={themeProp({ color })}> $ watch curl -sL {endpoint} </Monospace> - <Monospace color={color}>{`\n${resume}`}</Monospace> - <Monospace color={color} fontSize={[0, 0, 1, 1]}> + <Monospace + css={themeProp({ color })} + >{`\n${resume}`}</Monospace> + <Monospace css={themeProp({ color, fontSize: [0, null, 1] })}> {`\n${info}`} </Monospace> </Choose.Otherwise> From 59d28e7d9c19ee7a56fa137d537819966d0a414d Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 16 May 2024 19:25:12 +0200 Subject: [PATCH 13/57] fix: linter --- src/components/elements/Terminal/Terminal.js | 12 +++++----- src/components/patterns/Chat/Chat.js | 3 +-- src/pages/enterprise.js | 3 +-- src/pages/formats.js | 3 +-- src/pages/logo.js | 25 ++++++++++---------- src/pages/recipes.js | 3 +-- src/pages/screenshot.js | 5 ++-- src/pages/status.js | 3 ++- src/pages/user-agents.js | 3 +-- 9 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/components/elements/Terminal/Terminal.js b/src/components/elements/Terminal/Terminal.js index 4d990b822..be047c8cf 100644 --- a/src/components/elements/Terminal/Terminal.js +++ b/src/components/elements/Terminal/Terminal.js @@ -84,9 +84,9 @@ const TerminalButtonRed = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(1), - animationDuration - } + animationDelay: animationDelay(1), + animationDuration + } : undefined } {...props} @@ -112,9 +112,9 @@ const TerminalButtonGreen = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(3), - animationDuration - } + animationDelay: animationDelay(3), + animationDuration + } : undefined } {...props} diff --git a/src/components/patterns/Chat/Chat.js b/src/components/patterns/Chat/Chat.js index 02667b425..93d96778a 100644 --- a/src/components/patterns/Chat/Chat.js +++ b/src/components/patterns/Chat/Chat.js @@ -12,8 +12,7 @@ const Chat = () => { 'https://join.slack.com/t/microlinkhq/shared_invite/zt-3oe805om-HzexWW5yQNcF6cJs3dFM_A', '_blank', 'noopener noreferrer' - ) - } + )} > <Caps css={theme({ px: 3, py: 2 })}>Join in the community</Caps> </Button> diff --git a/src/pages/enterprise.js b/src/pages/enterprise.js index d61d7347f..794d613d3 100644 --- a/src/pages/enterprise.js +++ b/src/pages/enterprise.js @@ -105,8 +105,7 @@ const EnterprisePage = () => { 'mailto:hello@microlink.io?subject=Microlink%20Enterprise&body=Hello%2C%20I%20want%20to%20upgrade%20my%20customer%20plan%20to%20Microlink%20Enterprise.%0D%0A%0D%0ACan%20you%20tell%20me%20more%20about%20the%20details%3F%0D%0A%0D%0AThank%20you!%0D%0A', '_blank', 'noopener noreferrer' - ) - } + )} > <Caps css={themeProp({ bg: 'black', px: 3, py: 2, color: primary })} diff --git a/src/pages/formats.js b/src/pages/formats.js index b66064e68..e0acdeed2 100644 --- a/src/pages/formats.js +++ b/src/pages/formats.js @@ -240,8 +240,7 @@ const FormatsPage = () => { <Box css={theme({ p: [4, 4, 0, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') - } + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} > <Caps>Request a format</Caps> </Button> diff --git a/src/pages/logo.js b/src/pages/logo.js index aeb8cdc16..2d1286a38 100644 --- a/src/pages/logo.js +++ b/src/pages/logo.js @@ -136,17 +136,17 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ const colors = isLoading ? Array.from({ length: 6 }, () => '#fff') : [ - ...new Set( - [] - .concat( - logo.palette, - logo.background_color, - logo.color, - logo.alternative_color - ) - .filter(Boolean) - ) - ] + ...new Set( + [] + .concat( + logo.palette, + logo.background_color, + logo.color, + logo.alternative_color + ) + .filter(Boolean) + ) + ] const LogoComponent = isLoading ? LogoEmpty @@ -257,8 +257,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ toClipboard({ copy: color, text: Tooltip.TEXT.COPIED.COLOR(color) - }) - } + })} /> </Tooltip> ) diff --git a/src/pages/recipes.js b/src/pages/recipes.js index ddc23c7b2..4fb0ae9b9 100644 --- a/src/pages/recipes.js +++ b/src/pages/recipes.js @@ -180,8 +180,7 @@ const RecipesPage = () => { <Box css={theme({ pt: [4, null, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') - } + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} > <Caps>Request an Integration</Caps> </Button> diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 66d9f9f2d..80018a780 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -180,9 +180,8 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - } - } + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + }} /> </Link> ) diff --git a/src/pages/status.js b/src/pages/status.js index a657212f7..5dcbe0a25 100644 --- a/src/pages/status.js +++ b/src/pages/status.js @@ -80,7 +80,8 @@ const StatusPage = () => { </Monospace> <Monospace css={themeProp({ color })} - >{`\n${resume}`}</Monospace> + >{`\n${resume}`} + </Monospace> <Monospace css={themeProp({ color, fontSize: [0, null, 1] })}> {`\n${info}`} </Monospace> diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index 9baed3eb5..ff960ffd2 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -64,8 +64,7 @@ const UserAgentsPage = () => { css={theme({ alignItems: 'center', justifyContent: 'center' })} defaultValue='User Agent' onChange={value => - setType(value === 'User Agent' ? 'user' : 'crawler') - } + setType(value === 'User Agent' ? 'user' : 'crawler')} > {['User Agent', 'Crawler Agent']} </Toggle> From f7783bdde5a55de99911afc89b285d5b29014ab7 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 16 May 2024 20:34:46 +0200 Subject: [PATCH 14/57] refactor: remove comment --- scripts/fetch-data/providers/fetch-formats.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/fetch-data/providers/fetch-formats.js b/scripts/fetch-data/providers/fetch-formats.js index 7a38e9990..b840f965b 100644 --- a/scripts/fetch-data/providers/fetch-formats.js +++ b/scripts/fetch-data/providers/fetch-formats.js @@ -6,9 +6,6 @@ const { sortBy } = require('lodash') const { getType } = require('mime') const path = require('path') -/* We avoid cdn.microlink.io explicity since it - runs on top of CloudFlare and the compression - removes 'content-length' header */ const MICROLINK_CDN_URL = 'https://cdn.microlink.io/file-examples' const fileUrls = async () => From c46a173cb5e53ebf93fe023fcb73803d76ef07c2 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 16 May 2024 21:19:08 +0200 Subject: [PATCH 15/57] fix: detect language from title --- src/components/elements/CodeEditor/CodeEditor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index edb54033b..684630afc 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -74,12 +74,12 @@ const CodeEditor = ({ showLineNumbers, isDark, language: languageProp, - title, + title = '', ...props }) => { const className = getClassName(props) const highlightLines = getLines(className) - const language = toAlias(languageProp) + const language = toAlias(languageProp || title.split('.').pop()) const pretty = get(prettier, language, identity) const text = pretty(template(children)).trim() const id = `codeditor-${hash(children)}-${isDark ? 'dark' : 'light'}` From 292166c96d6791d61b297120bca5fb99c5229def Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 17 May 2024 19:18:56 +0200 Subject: [PATCH 16/57] fix: highlight lines --- .../elements/CodeEditor/CodeEditor.js | 36 +++++++++++-------- src/pages/styleguide.md | 6 ++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index 684630afc..51e845a5c 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -35,14 +35,9 @@ const toAlias = (lang = '') => { const generateHighlightLines = linesRange => { if (!linesRange) return - const [start, end] = linesRange const collection = end ? range(start, end + 1) : [start] - - return collection.map((line, index) => { - const isLast = index + 1 === collection.length - return `code > span:nth-child(${line})${!isLast ? ',' : ''}` - }) + return collection.map(line => `code > span:nth-child(${line})`) } const getClassName = ({ className, metastring = '' }) => @@ -51,15 +46,6 @@ const getClassName = ({ className, metastring = '' }) => const CustomSyntaxHighlighter = styled(SyntaxHighlighter)` ${hideScrollbar}; ${props => codeTheme[props.$isDark]}; - ${({ $highlightLines, $isDark }) => { - return ` - ${generateHighlightLines($highlightLines)} { - display: block; - background: ${cx($isDark ? 'white05' : 'black05')}; - border-radius: ${radii[2]}; - } - ` - }} ` const TerminalTextWrapper = styled('div')` @@ -89,6 +75,12 @@ const CodeEditor = ({ const [isLoaded, setIsLoaded] = useState(!isInteractive) + const highLightLinesSelector = generateHighlightLines(highlightLines) + const firstHighlightLine = highLightLinesSelector && highLightLinesSelector[0] + const lastHighlightLine = + highLightLinesSelector && + highLightLinesSelector[highLightLinesSelector.length - 1] + const TerminalComponent = ( <Terminal title={title} @@ -101,6 +93,20 @@ const CodeEditor = ({ > <TerminalTextWrapper> <CustomSyntaxHighlighter + css={` + ${String(highLightLinesSelector)} { + display: block; + background: ${cx(isDark ? 'white05' : 'black05')}; + } + ${String(firstHighlightLine)} { + border-top-left-radius: ${radii[2]}; + border-top-right-radius: ${radii[2]}; + } + ${String(lastHighlightLine)} { + border-bottom-left-radius: ${radii[2]}; + border-bottom-right-radius: ${radii[2]}; + } + `} useInlineStyles={false} $isDark={isDark} $highlightLines={highlightLines} diff --git a/src/pages/styleguide.md b/src/pages/styleguide.md index 24ced0b22..d401ec5c4 100644 --- a/src/pages/styleguide.md +++ b/src/pages/styleguide.md @@ -91,11 +91,11 @@ microlink('.link-previews') Months ago I created [Fink](http://xn--rn8h.ws/), a URL Shortener service that I called it *for masses*. -![](https://placekitten.com/450/300) +![](https://placehold.co/450x300) -![](https://placekitten.com/1000/740) +![](https://placehold.co/1000x740) -![](https://placekitten.com/1200/800) +![](https://placehold.co/1200x800) <Figcaption children='This text is the caption for the image.' /> From 3a6b4ddc3b57a2b1b635e90447bcf6a868546bca Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 17 May 2024 20:30:41 +0200 Subject: [PATCH 17/57] fix: tabs non selected style --- src/components/elements/MultiCodeEditor/MultiCodeEditor.js | 6 +----- src/components/elements/Tabs.js | 6 +++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js index 4b96d1021..c74afe8c9 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js @@ -12,10 +12,7 @@ import Box from '../Box' export const SelectLanguage = ({ isDark, value, onClick, ...props }) => ( <Tabs value={value} - onClick={event => { - const label = event.target.textContent - onClick(label) - }} + onClick={event => onClick(event.target.textContent)} {...props} /> ) @@ -90,7 +87,6 @@ const MultiCodeEditor = ({ document.addEventListener(LOCALSTORAGE_KEY, updateLanguageIndex) return () => document.removeEventListener(LOCALSTORAGE_KEY, updateLanguageIndex) - // eslint-disable-next-line }, []) return ( diff --git a/src/components/elements/Tabs.js b/src/components/elements/Tabs.js index b8e17b319..892346fd3 100644 --- a/src/components/elements/Tabs.js +++ b/src/components/elements/Tabs.js @@ -7,8 +7,8 @@ import Text from './Text' import Flex from './Flex' import Box from './Box' -const getColor = ({ isActive, isDark }) => { - const id = isDark ? 'white' : 'red' +const getColor = ({ $active: isActive, isDark }) => { + const id = isDark ? 'white' : 'black' return cx(isActive ? id : `${id}50`) } @@ -19,8 +19,8 @@ const StyledTab = styled(Box)` cursor: pointer; margin-right: 12px; ${theme({ pb: 2 })} + color: ${props => getColor(props)}; ${is('$active')` - color: ${props => getColor(props)}; border-bottom: 1px solid ${props => props.background}; `}; ` From 569419782e5f9eb146cba6bce425a733e73a48cb Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 17 May 2024 22:42:36 +0200 Subject: [PATCH 18/57] fix: get language from props --- src/components/elements/CodeEditor/CodeEditor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index 51e845a5c..a8bf684ee 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -65,7 +65,9 @@ const CodeEditor = ({ }) => { const className = getClassName(props) const highlightLines = getLines(className) - const language = toAlias(languageProp || title.split('.').pop()) + const language = toAlias( + getLanguage({ className, language: languageProp, title }) + ) const pretty = get(prettier, language, identity) const text = pretty(template(children)).trim() const id = `codeditor-${hash(children)}-${isDark ? 'dark' : 'light'}` From c9d089f68525ece9ed4ed2c996cc5d153f316834 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 18 May 2024 14:01:20 +0200 Subject: [PATCH 19/57] fix: json highlight syntax --- src/components/elements/CodeEditor/CodeEditor.js | 15 ++++++++++++--- src/components/elements/CodeEditor/theme.js | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index a8bf684ee..8dafd834a 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -45,7 +45,7 @@ const getClassName = ({ className, metastring = '' }) => const CustomSyntaxHighlighter = styled(SyntaxHighlighter)` ${hideScrollbar}; - ${props => codeTheme[props.$isDark]}; + ${props => codeTheme[props.$theme]}; ` const TerminalTextWrapper = styled('div')` @@ -54,6 +54,14 @@ const TerminalTextWrapper = styled('div')` font-size: 14px; ` +const getLanguage = ({ className, language, title }) => { + if (language) return language + if (title) return title.split('.').pop() + const languageFromClassName = className.split('-')[1] + if (languageFromClassName) return languageFromClassName.split('{')[0] + return 'js' +} + const CodeEditor = ({ children, interactive: runkitProps, @@ -63,6 +71,7 @@ const CodeEditor = ({ title = '', ...props }) => { + const themeKey = isDark ? 'dark' : 'light' const className = getClassName(props) const highlightLines = getLines(className) const language = toAlias( @@ -70,7 +79,7 @@ const CodeEditor = ({ ) const pretty = get(prettier, language, identity) const text = pretty(template(children)).trim() - const id = `codeditor-${hash(children)}-${isDark ? 'dark' : 'light'}` + const id = `codeditor-${hash(children)}-${themeKey}` const isInteractive = runkitProps !== false && Runkit.isSupported({ language, text }) @@ -110,7 +119,7 @@ const CodeEditor = ({ } `} useInlineStyles={false} - $isDark={isDark} + $theme={themeKey} $highlightLines={highlightLines} showLineNumbers={showLineNumbers} language={language} diff --git a/src/components/elements/CodeEditor/theme.js b/src/components/elements/CodeEditor/theme.js index 856463e09..b1070b3b5 100644 --- a/src/components/elements/CodeEditor/theme.js +++ b/src/components/elements/CodeEditor/theme.js @@ -51,8 +51,8 @@ const theme = { const codeTheme = { theme, - false: base(theme.light), - true: base(theme.dark) + dark: base(theme.dark), + light: base(theme.light) } export default codeTheme From 6a4d273b188fc3022b6f2c365f50809cfc74a3d2 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 18 May 2024 16:29:04 +0200 Subject: [PATCH 20/57] refactor: avoid defaultProps --- src/components/elements/Input/Input.js | 6 +----- src/components/patterns/Layout.js | 12 +++--------- src/components/patterns/PricingTable/PricingTable.js | 4 ---- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/components/elements/Input/Input.js b/src/components/elements/Input/Input.js index 689e93227..296d50f69 100644 --- a/src/components/elements/Input/Input.js +++ b/src/components/elements/Input/Input.js @@ -65,7 +65,7 @@ const Input = ({ isDark, ...props }) => { - const [isFocus, setFocus] = useState(props.autoFocus) + const [isFocus, setFocus] = useState(Boolean(props.autoFocus)) const list = useMemo(() => { if (!suggestions) return undefined @@ -110,8 +110,4 @@ const Input = ({ ) } -Input.defaultProps = { - autoFocus: false -} - export default Input diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index 41f57a17a..6878b2059 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -23,11 +23,11 @@ const TOOLBAR_HEIGHTS = [ ] const Layout = ({ - footer, + footer = true, children, - onClick, + onClick = noop, style, - theme, + theme = 'light', component = Box, ...props }) => { @@ -77,10 +77,4 @@ const Layout = ({ ) } -Layout.defaultProps = { - theme: 'light', - footer: true, - onClick: noop -} - export default Layout diff --git a/src/components/patterns/PricingTable/PricingTable.js b/src/components/patterns/PricingTable/PricingTable.js index 2a91411ec..598d747b0 100644 --- a/src/components/patterns/PricingTable/PricingTable.js +++ b/src/components/patterns/PricingTable/PricingTable.js @@ -114,10 +114,6 @@ const Check = ({ children, ...props }) => ( </Text> ) -Check.defaultProps = { - as: 'li' -} - export const createPricingTable = Checkout => { const PricingTable = ({ canonicalUrl, stripeKey, apiEndpoint, ...props }) => { const [plan, setPlan] = useState(DEFAULT_PLAN) From d782453ac8c8faf5998ccfda76eb0ad8c0ed8c30 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 18 May 2024 16:46:41 +0200 Subject: [PATCH 21/57] refactor: avoid defaultProps for styled-components --- src/components/elements/Heading.js | 8 ++------ src/components/elements/Subhead.js | 8 ++------ src/components/elements/Text.js | 4 ---- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/components/elements/Heading.js b/src/components/elements/Heading.js index 62d92dc85..7d0c23bd0 100644 --- a/src/components/elements/Heading.js +++ b/src/components/elements/Heading.js @@ -1,5 +1,6 @@ import styled from 'styled-components' import { theme } from 'theme' +import React from 'react' import Text from './Text' @@ -13,9 +14,4 @@ const Heading = styled(Text)( }) ) -Heading.defaultProps = { - as: 'h1', - variant: 'gradient' -} - -export default Heading +export default props => <Heading as='h1' variant='gradient' {...props} /> diff --git a/src/components/elements/Subhead.js b/src/components/elements/Subhead.js index 4dbff5d00..4c68de976 100644 --- a/src/components/elements/Subhead.js +++ b/src/components/elements/Subhead.js @@ -1,6 +1,7 @@ import styled from 'styled-components' import Heading from './Heading' import { theme } from 'theme' +import React from 'react' const Subhead = styled(Heading)( theme({ @@ -9,9 +10,4 @@ const Subhead = styled(Heading)( }) ) -Subhead.defaultProps = { - as: 'h2', - variant: null -} - -export default Subhead +export default props => <Subhead as='h2' variant={null} {...props} /> diff --git a/src/components/elements/Text.js b/src/components/elements/Text.js index 170eb6864..6f3cf3d17 100644 --- a/src/components/elements/Text.js +++ b/src/components/elements/Text.js @@ -18,8 +18,4 @@ const Text = styled(Box).withConfig({ }) ) -Text.defaultProps = { - as: 'div' -} - export default Text From 249239025760258471efccd5709060c041f4476f Mon Sep 17 00:00:00 2001 From: Brad Adams <hi@breadadams.com> Date: Wed, 22 May 2024 10:53:12 +0200 Subject: [PATCH 22/57] refactor: remove `defaultProps` (#1717) * refactor: initial `defaultProps` removal * refactor: more `defaultProps` removals * refactor: replace code-editor related defaultProps * refactor: replace `defaultProps` on markdown components --- .../BackgroundSlider/BackgroundSlider.js | 10 +- .../BackgroundSlider.stories.js | 11 - src/components/elements/Badge/Badge.js | 7 +- src/components/elements/Button/Button.js | 11 +- src/components/elements/Card/Card.js | 6 +- .../elements/CodeEditor/CodeEditor.js | 15 +- src/components/elements/Color/Color.js | 6 +- src/components/elements/Dot/Dot.js | 6 +- src/components/elements/Heading.js | 18 +- src/components/elements/Image/Image.js | 10 +- src/components/elements/Input/Input.js | 7 +- src/components/elements/Label.js | 7 +- src/components/elements/Link/base.js | 7 +- src/components/elements/Runkit/Runkit.js | 6 +- src/components/elements/Select/Select.js | 7 +- src/components/elements/Spinner.js | 25 +- src/components/elements/Subhead.js | 13 +- src/components/elements/Svg.js | 7 +- src/components/elements/Terminal/Terminal.js | 37 ++- src/components/elements/Toggle/Toggle.js | 6 +- src/components/elements/Toolbar.js | 4 - src/components/icons/Eleventy.js | 3 +- src/components/logos/index.js | 265 ++++-------------- src/components/markdown/index.js | 208 ++++++-------- src/components/patterns/Aside/AsideBase.js | 6 +- src/components/patterns/Aside/NavLink.js | 6 - src/components/patterns/Average/Average.js | 1 - src/components/patterns/Caption/Caption.js | 12 +- .../patterns/ClusterMonitor/ClusterMonitor.js | 9 +- .../patterns/DemoLinks/DemoLinks.js | 21 +- .../patterns/DotsBackground/DotsBackground.js | 10 +- src/components/patterns/Faq/Faq.js | 3 +- src/components/patterns/FetchProvider.js | 12 +- .../patterns/PricingTable/PricingTable.js | 3 +- .../patterns/Toolbar/ToolbarDesktop.js | 3 +- .../patterns/Toolbar/ToolbarMobile.js | 4 +- src/components/patterns/index.js | 6 +- src/pages/meta.js | 16 +- src/pages/sdk.js | 15 +- 39 files changed, 277 insertions(+), 552 deletions(-) diff --git a/src/components/elements/BackgroundSlider/BackgroundSlider.js b/src/components/elements/BackgroundSlider/BackgroundSlider.js index c4f9814bc..44f3b8076 100644 --- a/src/components/elements/BackgroundSlider/BackgroundSlider.js +++ b/src/components/elements/BackgroundSlider/BackgroundSlider.js @@ -20,7 +20,11 @@ const SliderContainerChildren = styled('div')` display: inline-block; ` -const BackgroundSlider = ({ animationDirection, duration, children }) => ( +const BackgroundSlider = ({ + animationDirection = 'normal', + duration, + children +}) => ( <SliderContainer> <SliderContainerWrapper animationDirection={animationDirection} @@ -32,10 +36,6 @@ const BackgroundSlider = ({ animationDirection, duration, children }) => ( </SliderContainer> ) -BackgroundSlider.defaultProps = { - animationDirection: 'normal' -} - const BackgroundSliderContainer = styled(Box)` &:hover { div { diff --git a/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js b/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js index dc066c396..460431b5f 100644 --- a/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js +++ b/src/components/elements/BackgroundSlider/BackgroundSlider.stories.js @@ -7,22 +7,11 @@ import { Story } from 'story' import React from 'react' import { - Flex, Box, BackgroundSlider, BackgroundSliderContainer } from 'components/elements' -const NoWrap = styled(Flex)` - white-space: nowrap; - overflow: hidden; -` - -NoWrap.defaultProps = { - justifyContent: 'center', - alignItems: 'center' -} - const LogoWrap = styled(Box)` cursor: pointer; opacity: 0.25; diff --git a/src/components/elements/Badge/Badge.js b/src/components/elements/Badge/Badge.js index eadbf33d8..0dc1ac747 100644 --- a/src/components/elements/Badge/Badge.js +++ b/src/components/elements/Badge/Badge.js @@ -1,9 +1,10 @@ import styled from 'styled-components' import { theme } from 'theme' +import React from 'react' import Text from '../Text' -const Badge = styled(Text)` +const StyledBadge = styled(Text)` padding: 2px 12px; text-transform: uppercase; position: relative; @@ -21,8 +22,6 @@ const Badge = styled(Text)` })} ` -Badge.defaultProps = { - as: 'span' -} +const Badge = props => <StyledBadge as='span' {...props} /> export default Badge diff --git a/src/components/elements/Button/Button.js b/src/components/elements/Button/Button.js index 19f8932fb..6682a4e9f 100644 --- a/src/components/elements/Button/Button.js +++ b/src/components/elements/Button/Button.js @@ -1,6 +1,7 @@ import { transition, theme as themeProp, colors, space, gradient } from 'theme' import styled from 'styled-components' import Box from '../Box' +import React, { forwardRef } from 'react' const getVariant = ({ theme, variant }) => { const { background = 'link', color = 'white' } = @@ -18,7 +19,7 @@ export const hoverStyle = ({ theme, variant }) => { } } -const Button = styled(Box).withConfig({ +const StyledButton = styled(Box).withConfig({ shouldForwardProp: prop => !['variant'].includes(prop) })` transition: background-color ${transition.medium}, color ${transition.medium}, @@ -73,8 +74,10 @@ const Button = styled(Box).withConfig({ }} ` -Button.defaultProps = { - as: 'button' -} +const Button = forwardRef((props, ref) => ( + <StyledButton as='button' ref={ref} {...props} /> +)) + +Button.displayName = 'Button' export default Button diff --git a/src/components/elements/Card/Card.js b/src/components/elements/Card/Card.js index cd4f8ed78..f3295f287 100644 --- a/src/components/elements/Card/Card.js +++ b/src/components/elements/Card/Card.js @@ -19,7 +19,7 @@ const CardBase = styled(Flex)` ` const Card = ({ - ratio, + ratio = [0.55, 0.75, 1, 1], width = ratio.map(n => toPx(BASE_WIDTH * n)), height = ratio.map(n => toPx(BASE_HEIGHT * n)), ...props @@ -39,10 +39,6 @@ const Card = ({ ) } -Card.defaultProps = { - ratio: [0.55, 0.75, 1, 1] -} - const CardOption = ({ children, value, ...props }) => ( <Text as='span' diff --git a/src/components/elements/CodeEditor/CodeEditor.js b/src/components/elements/CodeEditor/CodeEditor.js index 8dafd834a..c3d61d4f3 100644 --- a/src/components/elements/CodeEditor/CodeEditor.js +++ b/src/components/elements/CodeEditor/CodeEditor.js @@ -64,11 +64,12 @@ const getLanguage = ({ className, language, title }) => { const CodeEditor = ({ children, - interactive: runkitProps, - showLineNumbers, - isDark, + interactive: runkitProps = {}, + showLineNumbers = false, + isDark = false, language: languageProp, title = '', + blinkCursor = false, ...props }) => { const themeKey = isDark ? 'dark' : 'light' @@ -100,6 +101,7 @@ const CodeEditor = ({ text={text} loading={!isLoaded} css={theme({ width: TERMINAL_WIDTH })} + blinkCursor={blinkCursor} {...props} > <TerminalTextWrapper> @@ -151,13 +153,6 @@ const CodeEditor = ({ ) } -CodeEditor.defaultProps = { - blinkCursor: false, - interactive: {}, - showLineNumbers: false, - isDark: false -} - CodeEditor.width = TERMINAL_WIDTH CodeEditor.height = TERMINAL_HEIGHT diff --git a/src/components/elements/Color/Color.js b/src/components/elements/Color/Color.js index 97570a62f..01840ef9e 100644 --- a/src/components/elements/Color/Color.js +++ b/src/components/elements/Color/Color.js @@ -16,13 +16,9 @@ const Colored = styled(Text)( }) ) -Colored.defaultProps = { - as: 'span' -} - const Color = ({ children, ...props }) => ( <> - <Colored style={{ background: children }} {...props} /> + <Colored as='span' style={{ background: children }} {...props} /> {children} </> ) diff --git a/src/components/elements/Dot/Dot.js b/src/components/elements/Dot/Dot.js index d27ffdaaa..9497b4901 100644 --- a/src/components/elements/Dot/Dot.js +++ b/src/components/elements/Dot/Dot.js @@ -4,16 +4,14 @@ import React from 'react' import Text from '../Text' -const Dot = styled(Text)` +const StyledDot = styled(Text)` display: inline-block; width: 10px; height: 10px; border-radius: 5px; ` -Dot.defaultProps = { - as: 'span' -} +const Dot = props => <StyledDot as='span' {...props} /> const createDot = color => { const ColoredDot = props => ( diff --git a/src/components/elements/Heading.js b/src/components/elements/Heading.js index 7d0c23bd0..eae3a7626 100644 --- a/src/components/elements/Heading.js +++ b/src/components/elements/Heading.js @@ -4,14 +4,20 @@ import React from 'react' import Text from './Text' -const Heading = styled(Text)( +export const commonHeadingStyles = { + letterSpacing: 1, + lineHeight: 0, + textAlign: 'center', + fontWeight: 'bold' +} + +const StyledHeading = styled(Text)( theme({ - letterSpacing: 1, - lineHeight: 0, - textAlign: 'center', - fontWeight: 'bold', + ...commonHeadingStyles, fontSize: [4, 6, 7, 7] }) ) -export default props => <Heading as='h1' variant='gradient' {...props} /> +const Heading = props => <StyledHeading as='h1' variant='gradient' {...props} /> + +export default Heading diff --git a/src/components/elements/Image/Image.js b/src/components/elements/Image/Image.js index b5a9840af..098ff294f 100644 --- a/src/components/elements/Image/Image.js +++ b/src/components/elements/Image/Image.js @@ -1,5 +1,6 @@ import styled from 'styled-components' import { withLazy } from 'helpers/hoc' +import React from 'react' import { space, @@ -9,7 +10,7 @@ import { border } from '@techstack/styled-system' -const Image = styled('img')( +const StyledImage = styled('img')( { display: 'block', maxWidth: '100%' @@ -21,9 +22,8 @@ const Image = styled('img')( border ) -Image.defaultProps = { - decoding: 'async', - loading: 'lazy' -} +const Image = props => ( + <StyledImage decoding='async' loading='lazy' {...props} /> +) export default withLazy(Image) diff --git a/src/components/elements/Input/Input.js b/src/components/elements/Input/Input.js index 296d50f69..fe2a2276f 100644 --- a/src/components/elements/Input/Input.js +++ b/src/components/elements/Input/Input.js @@ -5,7 +5,7 @@ import styled, { css } from 'styled-components' import Text from '../Text' import Flex from '../Flex' -const InputBase = styled(Text)( +const StyledInputBase = styled(Text)( { lineHeight: 'inherit', background: 'transparent', @@ -28,10 +28,7 @@ const InputBase = styled(Text)( }) ) -InputBase.defaultProps = { - as: 'input', - type: 'text' -} +const InputBase = props => <StyledInputBase as='input' type='text' {...props} /> const focusStyle = css` outline: 0; diff --git a/src/components/elements/Label.js b/src/components/elements/Label.js index 97f231549..61c986439 100644 --- a/src/components/elements/Label.js +++ b/src/components/elements/Label.js @@ -1,6 +1,7 @@ import styled, { css } from 'styled-components' import { colors, fontWeights, theme } from 'theme' import is from 'styled-is' +import React from 'react' import Text from './Text' @@ -13,7 +14,7 @@ export const labelStyle = css` color: ${props => getColor(props)}; ` -const Label = styled(Text).withConfig({ +const StyledLabel = styled(Text).withConfig({ shouldForwardProp: prop => !['suffix'].includes(prop) })` ${theme({ fontSize: 1 })}; @@ -26,8 +27,6 @@ const Label = styled(Text).withConfig({ `}; ` -Label.defaultProps = { - as: 'label' -} +const Label = props => <StyledLabel as='label' {...props} /> export default Label diff --git a/src/components/elements/Link/base.js b/src/components/elements/Link/base.js index 7a77e6046..daaab51a6 100644 --- a/src/components/elements/Link/base.js +++ b/src/components/elements/Link/base.js @@ -1,5 +1,6 @@ import { colors, transition, lineHeights, theme } from 'theme' import styled, { css } from 'styled-components' +import React from 'react' import Text from '../Text' @@ -15,7 +16,7 @@ export const LinkBase = styled(Text)` ${style}; ` -const Link = styled(LinkBase)` +const StyledLink = styled(LinkBase)` ${theme({ color: 'link', fontSize: 'inherit', @@ -25,8 +26,6 @@ const Link = styled(LinkBase)` })} ` -Link.defaultProps = { - as: 'span' -} +const Link = props => <StyledLink as='span' {...props} /> export default Link diff --git a/src/components/elements/Runkit/Runkit.js b/src/components/elements/Runkit/Runkit.js index 39692fa2f..d79124ace 100644 --- a/src/components/elements/Runkit/Runkit.js +++ b/src/components/elements/Runkit/Runkit.js @@ -4,7 +4,7 @@ import { Script } from 'gatsby' const NODE_VERSION = '18' -const Runkit = ({ onLoad, placeholderComponent, isDark, ...opts }) => { +const Runkit = ({ onLoad, placeholderComponent, isDark = false, ...opts }) => { if (!placeholderComponent.props.id) { throw new Error('Runkit placeholder must to have an id.') } @@ -41,10 +41,6 @@ const Runkit = ({ onLoad, placeholderComponent, isDark, ...opts }) => { ) } -Runkit.defaultProps = { - isDark: false -} - Runkit.isSupported = ({ language, text }) => { const isSupported = language === 'js' && !text.includes('import') && !text.startsWith('{') diff --git a/src/components/elements/Select/Select.js b/src/components/elements/Select/Select.js index 2be751f12..33ac34d42 100644 --- a/src/components/elements/Select/Select.js +++ b/src/components/elements/Select/Select.js @@ -1,5 +1,6 @@ import styled from 'styled-components' import { theme, transition, fonts } from 'theme' +import React from 'react' import Box from '../Box' @@ -9,7 +10,7 @@ const arrow = encodeURI( const ARROW_SIZE = '7px' -const Select = styled(Box)( +const StyledSelect = styled(Box)( { background: 'transparent', color: 'inherit', @@ -47,8 +48,6 @@ const Select = styled(Box)( }) ) -Select.defaultProps = { - as: 'select' -} +const Select = props => <StyledSelect as='select' {...props} /> export default Select diff --git a/src/components/elements/Spinner.js b/src/components/elements/Spinner.js index 1996050c9..4b33e61ee 100644 --- a/src/components/elements/Spinner.js +++ b/src/components/elements/Spinner.js @@ -6,8 +6,20 @@ import { cx, colors } from 'theme' import Svg from './Svg' -const Spinner = props => ( - <StyledSpinner viewBox='0 0 50 50' {...props}> +const Spinner = ({ + color = colors.primary, + width = '64px', + height = '32px', + style = { padding: '4px' }, + ...props +}) => ( + <StyledSpinner + viewBox='0 0 50 50' + $color={color} + css={{ width, height }} + style={style} + {...props} + > <circle className='path' cx='25' @@ -24,17 +36,10 @@ const StyledSpinner = styled(Svg)` will-change: stroke-dasharray, stroke-dashoffset; .path { - stroke: ${props => cx(props.color)}; + stroke: ${props => cx(props.$color)}; stroke-linecap: round; animation: ${dash} 1.5s ease-in-out infinite; } ` -StyledSpinner.defaultProps = { - color: colors.primary, - width: '64px', - height: '32px', - style: { padding: '4px' } -} - export default Spinner diff --git a/src/components/elements/Subhead.js b/src/components/elements/Subhead.js index 4c68de976..9e397dd7c 100644 --- a/src/components/elements/Subhead.js +++ b/src/components/elements/Subhead.js @@ -1,13 +1,16 @@ import styled from 'styled-components' -import Heading from './Heading' +import { commonHeadingStyles } from './Heading' +import Text from './Text' import { theme } from 'theme' import React from 'react' -const Subhead = styled(Heading)( +const StyledSubhead = styled(Text)( theme({ - fontSize: [4, 4, 6, 6], - color: 'black' + ...commonHeadingStyles, + fontSize: [4, 4, 6, 6] }) ) -export default props => <Subhead as='h2' variant={null} {...props} /> +const Subhead = props => <StyledSubhead as='h2' {...props} /> + +export default Subhead diff --git a/src/components/elements/Svg.js b/src/components/elements/Svg.js index aade43177..99c917c17 100644 --- a/src/components/elements/Svg.js +++ b/src/components/elements/Svg.js @@ -1,15 +1,14 @@ import { compose, color, space, layout, system } from '@techstack/styled-system' import styled from 'styled-components' +import React from 'react' const transform = system({ prop: 'transform', cssProperty: 'transform' }) -const Svg = styled('svg')(compose(color, space, layout, transform)) +const StyledSvg = styled('svg')(compose(color, space, layout, transform)) -Svg.defaultProps = { - fill: 'currentColor' -} +const Svg = props => <StyledSvg fill='currentColor' {...props} /> export default Svg diff --git a/src/components/elements/Terminal/Terminal.js b/src/components/elements/Terminal/Terminal.js index be047c8cf..4b7032c9f 100644 --- a/src/components/elements/Terminal/Terminal.js +++ b/src/components/elements/Terminal/Terminal.js @@ -84,9 +84,9 @@ const TerminalButtonRed = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(1), - animationDuration - } + animationDelay: animationDelay(1), + animationDuration + } : undefined } {...props} @@ -112,9 +112,9 @@ const TerminalButtonGreen = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(3), - animationDuration - } + animationDelay: animationDelay(3), + animationDuration + } : undefined } {...props} @@ -200,17 +200,18 @@ const TerminalTextWrapper = styled('div')` ` const TerminalProvider = ({ - ActionComponent, + ActionComponent = CodeCopy, text, children, - loading, - isDark, + loading = false, + isDark = false, title, header, + width = TERMINAL_WIDTH, ...props }) => { return ( - <TerminalWindow $isDark={isDark} {...props}> + <TerminalWindow $isDark={isDark} css={theme({ width })} {...props}> <TerminalHeader $isDark={isDark} {...header}> <TerminalButton.Red loading={loading} /> <TerminalButton.Yellow loading={loading} /> @@ -223,7 +224,12 @@ const TerminalProvider = ({ ) } -const Terminal = ({ children, shellSymbol, blinkCursor, ...props }) => { +const Terminal = ({ + children, + shellSymbol = false, + blinkCursor = true, + ...props +}) => { const content = typeof children === 'string' ? fromString(children) : children const text = childrenTextAll(children) @@ -239,15 +245,6 @@ const Terminal = ({ children, shellSymbol, blinkCursor, ...props }) => { ) } -Terminal.defaultProps = { - ActionComponent: CodeCopy, - blinkCursor: true, - loading: false, - shellSymbol: false, - isDark: false, - width: TERMINAL_WIDTH -} - Terminal.width = TERMINAL_WIDTH Terminal.height = TERMINAL_HEIGHT diff --git a/src/components/elements/Toggle/Toggle.js b/src/components/elements/Toggle/Toggle.js index 32aa66bb1..928072006 100644 --- a/src/components/elements/Toggle/Toggle.js +++ b/src/components/elements/Toggle/Toggle.js @@ -19,7 +19,7 @@ const ButtonToggle = styled(Button)` })} ` -function Toggle ({ onChange, children, defaultValue, ...props }) { +function Toggle ({ onChange = noop, children, defaultValue, ...props }) { const [active, setActive] = useState(defaultValue || children[0]) return ( @@ -65,8 +65,4 @@ function Toggle ({ onChange, children, defaultValue, ...props }) { ) } -Toggle.defaultProps = { - onChange: noop -} - export default Toggle diff --git a/src/components/elements/Toolbar.js b/src/components/elements/Toolbar.js index e3a865952..fc1cfc1b5 100644 --- a/src/components/elements/Toolbar.js +++ b/src/components/elements/Toolbar.js @@ -22,10 +22,6 @@ const ToolbarBase = styled(Flex)` ${hideScrollbar}; ` -ToolbarBase.defaultProps = { - as: 'nav' -} - const secondaryProps = { justifyContent: 'center' } diff --git a/src/components/icons/Eleventy.js b/src/components/icons/Eleventy.js index 7ec63fba1..a5f9acd46 100644 --- a/src/components/icons/Eleventy.js +++ b/src/components/icons/Eleventy.js @@ -1,12 +1,13 @@ import React from 'react' import Svg from '../elements/Svg' +import { theme } from 'theme' export const Eleventy = props => ( <Svg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' viewBox='0 0 15694 21860' - bg='#292929' + css={theme({ bg: '#292929' })} {...props} > <path diff --git a/src/components/logos/index.js b/src/components/logos/index.js index 811a70b7f..ed9fcd950 100644 --- a/src/components/logos/index.js +++ b/src/components/logos/index.js @@ -12,7 +12,7 @@ const style = css` } ` -const FacebookBase = ({ ratio, ...props }) => ( +const FacebookBase = ({ ratio = 0.8, ...props }) => ( <Svg version='1.1' height={41.5 * ratio} @@ -29,16 +29,12 @@ const FacebookBase = ({ ratio, ...props }) => ( </Svg> ) -FacebookBase.defaultProps = { - ratio: 0.8 -} - export const Facebook = styled(FacebookBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#3b5998' } } })}; ` -const GitHubBase = ({ ratio, ...props }) => ( +const GitHubBase = ({ ratio = 0.8, ...props }) => ( <Svg height={73.5 * ratio} viewBox='0 0 2880 1024' @@ -55,16 +51,12 @@ const GitHubBase = ({ ratio, ...props }) => ( </Svg> ) -GitHubBase.defaultProps = { - ratio: 0.8 -} - export const GitHub = styled(GitHubBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#151013' } } })}; ` -const MediumBase = ({ ratio, ...props }) => ( +const MediumBase = ({ ratio = 0.8, ...props }) => ( <Svg height={40.8 * ratio} viewBox='0 0 380 75' @@ -80,16 +72,12 @@ const MediumBase = ({ ratio, ...props }) => ( </Svg> ) -MediumBase.defaultProps = { - ratio: 0.8 -} - export const Medium = styled(MediumBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#1c1b1a' } } })}; ` -const SoundCloudBase = ({ ratio, ...props }) => ( +const SoundCloudBase = ({ ratio = 0.6, ...props }) => ( <Svg height={118.5 * ratio} viewBox='28.432 71.063 194.75 111.365' {...props}> <path className='logo' @@ -98,16 +86,12 @@ const SoundCloudBase = ({ ratio, ...props }) => ( </Svg> ) -SoundCloudBase.defaultProps = { - ratio: 0.6 -} - export const SoundCloud = styled(SoundCloudBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#ff8800' } } })}; ` -const GizmodoBase = ({ ratio, ...props }) => ( +const GizmodoBase = ({ ratio = 0.8, ...props }) => ( <Svg viewBox='0 0 912.30664 130.90668' height={29.7 * ratio} @@ -124,16 +108,12 @@ const GizmodoBase = ({ ratio, ...props }) => ( </Svg> ) -GizmodoBase.defaultProps = { - ratio: 0.8 -} - export const Gizmodo = styled(GizmodoBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#100f0d' } } })}; ` -const TwitterBase = ({ ratio, ...props }) => ( +const TwitterBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' height={41.5 * ratio} @@ -147,16 +127,12 @@ const TwitterBase = ({ ratio, ...props }) => ( </Svg> ) -TwitterBase.defaultProps = { - ratio: 0.8 -} - export const Twitter = styled(TwitterBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#1da1f2' } } })}; ` -const YouTubeBase = ({ ratio, ...props }) => ( +const YouTubeBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' height={46.1 * ratio} @@ -175,16 +151,12 @@ const YouTubeBase = ({ ratio, ...props }) => ( </Svg> ) -YouTubeBase.defaultProps = { - ratio: 0.8 -} - export const YouTube = styled(YouTubeBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#ff0000' } } })}; ` -const InstagramBase = ({ ratio, ...props }) => ( +const InstagramBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' height={74 * ratio} @@ -199,16 +171,12 @@ const InstagramBase = ({ ratio, ...props }) => ( </Svg> ) -InstagramBase.defaultProps = { - ratio: 0.8 -} - export const Instagram = styled(InstagramBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#30618a' } } })}; ` -export const Wikipedia = ({ ratio, ...props }) => ( +export const Wikipedia = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' height={35.2 * ratio} @@ -220,11 +188,7 @@ export const Wikipedia = ({ ratio, ...props }) => ( </Svg> ) -Wikipedia.defaultProps = { - ratio: 0.8 -} - -export const Apple = ({ ratio, ...props }) => ( +export const Apple = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' xmlnsXlink='http://www.w3.org/1999/xlink' @@ -251,11 +215,7 @@ export const Apple = ({ ratio, ...props }) => ( </Svg> ) -Apple.defaultProps = { - ratio: 0.8 -} - -const AmazonBase = ({ ratio, ...props }) => ( +const AmazonBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 301.354' @@ -279,16 +239,12 @@ const AmazonBase = ({ ratio, ...props }) => ( </Svg> ) -AmazonBase.defaultProps = { - ratio: 0.8 -} - export const Amazon = styled(AmazonBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#f90' } } })}; ` -const YCombinatorBase = ({ ratio, ...props }) => ( +const YCombinatorBase = ({ ratio = 1, color = 'black', ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2233 448' @@ -296,14 +252,14 @@ const YCombinatorBase = ({ ratio, ...props }) => ( {...props} > <g fill='none'> - <path className='logo' fill={props.color} d='M0 0h447.78v448H0V0z' /> + <path className='logo' fill={color} d='M0 0h447.78v448H0V0z' /> <path fill='#fff' d='M447.78 0H2233v163.36c-16.52-2.96-33.38 4.03-45.05 15.59-3.66 3.62-7.11 7.48-11.25 10.57-.45-9.1-1.3-18.46-5.59-26.68-8.14 1.84-16.12 4.3-24.14 6.56.58 6.91 2.81 13.58 3.01 20.55 1.02 19.66.72 39.37.87 59.05.05 28.97-.08 57.95.06 86.92 8.94.2 17.89.2 26.83 0 .04-25.97-.01-51.94.03-77.92-.11-9.67.11-19.34.53-29.01.32-6.66-.54-14.2 3.89-19.79a58.84 58.84 0 0116.55-14.44c6.48-3.63 14.12-3.45 21.33-3.62 1.14-.28 3.17.2 3.65-1.28 3.4-8.02 5.66-16.49 9.28-24.43V448H447.78V0z' /> <path className='logo' - fill={props.color} + fill={color} d='M1232.13 92.63c7.19-1.72 14.44-4 21.9-3.91 4.13.19 4.75 5.05 5.12 8.24a705.06 705.06 0 011.56 45.04c.66 14.3.57 28.62.85 42.94 8.08-6.21 16-12.92 25.57-16.73 15.31-6.73 33.68-6.81 48.61 1 16.05 8.03 27.26 23.53 32.9 40.27 5.28 15.88 6.55 32.89 5.66 49.52-1.43 19.43-6.71 39.09-18.23 55.05-6.82 9.25-15.78 17.36-26.73 21.29-17.54 6.42-38.02 4.12-53.76-5.91-4.99-3.12-9.19-7.29-13.76-10.95-1.84 5.75-3.23 11.64-5.02 17.42-8.41.09-16.9.68-25.23-.69 3.36-13.45 3.44-27.38 3.81-41.16.62-48.35-.05-96.71-.25-145.06-1.07-18.78.5-37.77-3-56.36zm195.28 2.82a23.61 23.61 0 0116.35.83 26.03 26.03 0 0110.27 12.66c3.46 11.19-5.63 23.75-17.02 25.03-8.8.98-18.47-4.17-21.2-12.89-3.62-9.86 1.95-21.73 11.6-25.63zM633.73 115.7c12.79-8.56 27.7-15 43.29-15.2 15.87-.29 32.32.84 46.92 7.6 5.98 2.74 12.01 5.62 16.98 10.02-3.63 6.27-8.42 11.74-12.95 17.35-5.81-3.45-11.55-7.16-18-9.35-15.72-5.55-33.59-6.74-49.27-.42-13.12 4.99-23.84 15.18-30.57 27.39-4.65 8.6-8.54 17.73-10.48 27.36-1.73 9.4-2.28 18.97-2.43 28.51-.51 12.68-1.1 25.4-.33 38.07 2.23 17.61 8.34 35.34 20.35 48.73 10.52 12.1 26.06 19.2 41.88 20.79 8.33.46 16.84.57 24.98-1.54 9.9-2.17 18.67-7.37 27.82-11.47 5.34 5.3 9.98 11.26 14.34 17.38a193 193 0 01-21.12 10.25c-19.52 7.91-41.17 8.08-61.83 6.09-14.86-3.09-28.65-10.6-40.11-20.46-13.22-11.5-22.9-26.76-28.73-43.22-3.93-11.09-5.85-22.79-6.89-34.48-.41-8.69-1.38-17.41-.4-26.11.3-16.47 2.97-33.08 9.54-48.28 7.91-19.07 19.78-37.16 37.01-49.01z' /> <path @@ -311,7 +267,7 @@ const YCombinatorBase = ({ ratio, ...props }) => ( d='M133.02 111.64c1.97-.44 3.93-.94 5.96-1 9.62-.2 19.23.4 28.84.7 1.52-.24 2.05 1.17 2.61 2.27 14.65 30.02 29.09 60.16 43.88 90.12 3.18 6.22 6.03 12.62 9.63 18.62 3.03-4.92 5.49-10.17 8.16-15.29 16.61-31.99 32.32-64.45 48.67-96.57 10.82.33 21.75-.74 32.48 1.03-1.95 6.13-5.46 11.58-8.24 17.35-21.46 41.12-43.5 81.93-65.16 122.94a10.5 10.5 0 00-1.07 5.12c.04 29.31 0 58.63.02 87.94-10.45.01-20.9.07-31.35-.04.11-28.61-.03-57.22.07-85.83-.04-3.07.35-6.36-1.35-9.09-19.96-37.44-39.99-74.84-59.84-112.33-4.39-8.67-9.35-17.06-13.31-25.94z' /> <path - fill={props.color} + fill={color} className='logo' d='M1864.53 124.49c8.58-2.76 17.39-4.8 26.26-6.39-1.3 16.33-2.5 32.67-3.07 49.05 13.93.33 27.87.33 41.8.9a422.83 422.83 0 01-7.68 18.6c-11.73.04-23.47-.05-35.2.04-.04 15.11.13 30.21.13 45.32-.14 12 .71 23.98.52 35.99.32 13.6-.39 27.27 1.15 40.82.39 5.64 5.46 9.61 10.56 11.05 8.5 1.95 17.38 1.26 25.8-.8a33.24 33.24 0 013.02 15.69c-7.64 3.98-16.4 4.75-24.83 5.5-11.9.48-25.17-1.41-33.72-10.54-7.04-6.54-6.49-16.94-7.3-25.73-.86-19.31-.52-38.66-.62-57.99-.04-19.77.06-39.53-.05-59.3-7.43-.1-14.85-.03-22.26-.04-.28-6.46-.24-12.93-.04-19.39 7.29-.06 14.58.1 21.87-.11 1.11-14.23 1.36-28.56 3.66-42.67zm-1035.08 39.2c5.82-.74 11.7-.46 17.55-.41 6.93.23 14.04-.15 20.72 2.05 15.33 5.27 28.82 15.91 37.02 29.95 6.98 12.11 11.89 25.7 12.45 39.77.87 18.9 1.5 38.35-4.42 56.58-5.51 17.1-17.57 32.34-33.7 40.51-16.04 8.29-35.24 9.84-52.59 5.17-15.6-4.1-29.14-14.38-38.09-27.69-9.95-14.27-13.31-31.94-13.92-49.03-.4-16.53-.72-33.54 4.78-49.38 5.19-15.62 15.22-29.9 29.28-38.71 6.46-3.96 13.44-7.36 20.92-8.81zm133.92 5.25a190.96 190.96 0 0123.69-5.97 73.64 73.64 0 015.93 23.67c5.47-2.84 9.74-7.39 14.84-10.8 11.64-8.33 25.78-13.63 40.23-13.01 3.26.22 6.42 1.26 9.34 2.73 4.97 2.49 10.04 5.05 14.09 8.96 4.27 4.03 6.95 9.35 9.89 14.35 6.52-2.91 11.57-8.1 17.42-12.06 10.15-7.01 21.72-12.57 34.14-13.78 11.37-1.3 23.27 2.51 31.59 10.43 3.76 3.61 7.76 7.28 9.84 12.18 2.02 4.78 2.64 10 3.11 15.13 1.98 27.03.62 54.17 1.68 81.23 0 17.99.13 35.97.14 53.96-9 .13-17.99.19-26.98-.06.03-26.97.01-53.93.01-80.9-.08-17.34.33-34.71-1.09-52.01a20.44 20.44 0 00-8.31-13.88c-5.25-3.46-11.86-3.08-17.85-2.74-10.63 1-19.52 7.66-27.54 14.15-3.8 3.21-7.75 6.24-11.45 9.56-1.15.91-.79 2.56-.92 3.84.01 40.67.07 81.35-.03 122.03-8.95.15-17.91.19-26.85-.04.01-31.64.02-63.27-.01-94.91-.07-7.68.16-15.38-.47-23.04-.48-7.81.32-16.19-3.34-23.37-5.46-7.73-16.28-9.35-24.96-7.21-13.53 3.25-25.2 11.59-35.43 20.73-1.66 1.06-1.5 3.12-1.51 4.83.08 40.98-.03 81.97.05 122.95-7.85.24-15.71.26-23.55-.02-.74-41.95-.22-83.94-1.36-125.9-.24-9.52-.23-19.07-1.49-28.53-.76-4.21-2.14-8.28-2.85-12.5zm457.78-1.48c8.62-1.26 17.2-2.75 25.75-4.41 1.09 23.62.71 47.3.92 70.94.04 33.98.01 67.96.01 101.93-8.92.2-17.84.2-26.76.01-.28-48.64-.04-97.29-.12-145.93.05-7.51-.16-15.03.2-22.54zm264.47 14.12c17.91-9.87 37.54-18.42 58.38-18.27 7.32.05 14.73-.27 22.01.85 18.18 3.44 33.72 19.79 34.2 38.65.97 28.05-.2 56.13.09 84.19.21 8.34-.1 16.83 1.95 24.98 1.22 5.5 6.34 8.54 10.28 12.01-3.87 5.29-7.04 11.25-12.07 15.55-2.93 2.45-6.55-.21-9.02-2.01-6.52-4.83-10.95-11.85-14.55-19-5.78 3.15-10.21 8.17-15.84 11.56-9.81 6.22-21.38 9.92-33.04 9.75-10.46.24-21.18-1.5-30.6-6.17-15.3-8.08-23.8-25.7-23.36-42.65-.13-16.29 8.13-32.15 21.21-41.76 15.66-11.69 35.56-15.54 54.66-16.94 8.73-.77 17.51-.81 26.27-1.19.35-8.55-.3-17.11-1.52-25.57-1.03-7.19-4.46-14.55-11.06-18.16-7.91-4.17-17.26-4.27-25.91-3.02-16.32 1.99-31.64 8.96-44.92 18.47-3.54-5.05-7.3-9.98-10.31-15.36-1.47-2.69.91-4.81 3.15-5.91zm329.79-17.91a94.8 94.8 0 0131.3.87 65.56 65.56 0 0138.07 25.66c7.37 10.3 12.17 22.36 14.46 34.79a197.05 197.05 0 012.01 36c-.46 19.56-6.48 39.23-18.41 54.87-9.65 12.52-24.6 20.03-39.95 22.81-18.64 3.26-38.87-.04-54.46-11.12-13.68-9.74-22.4-24.98-27.13-40.83-2.56-7.99-3.01-16.42-3.61-24.72-.26-13.98-.53-28.13 2.3-41.9 3.87-15.61 11.57-30.62 23.52-41.59a57.41 57.41 0 0131.9-14.84zm131.56 5.73c8.02-2.26 16-4.72 24.14-6.56 4.29 8.22 5.14 17.58 5.59 26.68 4.14-3.09 7.59-6.95 11.25-10.57 11.67-11.56 28.53-18.55 45.05-15.59v2.07c-3.62 7.94-5.88 16.41-9.28 24.43-.48 1.48-2.51 1-3.65 1.28-7.21.17-14.85-.01-21.33 3.62a58.84 58.84 0 00-16.55 14.44c-4.43 5.59-3.57 13.13-3.89 19.79-.42 9.67-.64 19.34-.53 29.01-.04 25.98.01 51.95-.03 77.92-8.94.2-17.89.2-26.83 0-.14-28.97-.01-57.95-.06-86.92-.15-19.68.15-39.39-.87-59.05-.2-6.97-2.43-13.64-3.01-20.55zm-646.7.33c7.93-2.5 15.96-5.42 24.35-5.58a93.35 93.35 0 015.86 24.09c7.08-4.38 13.05-10.33 20.32-14.45 13.98-8.3 31.43-13.98 47.37-8.03 9.35 3.3 18.44 8.61 24.1 16.98 4.63 6.06 5.7 13.89 6.18 21.28 1.41 26.3.96 52.65 1.29 78.97-.02 17.64.34 35.27.39 52.9-8.95.26-17.91.23-26.86.02-.01-28.97-.58-57.94-.64-86.92-.39-16.12.46-32.33-1.49-48.37-2.42-7.69-9.86-14.12-18.12-14.33-6.1-.25-12.42-.48-18.24 1.67-12.8 4.77-24.33 12.4-34.76 21.14-.3 42.27-.02 84.56-.14 126.84-7.84.16-15.68.2-23.51-.05-.03-23.97-.63-47.93-.75-71.9-.22-24.67-.03-49.35-1.32-73.99-.27-6.95-2.55-13.54-4.03-20.27z' /> @@ -323,17 +279,12 @@ const YCombinatorBase = ({ ratio, ...props }) => ( </Svg> ) -YCombinatorBase.defaultProps = { - ratio: 1, - color: 'black' -} - export const YCombinator = styled(YCombinatorBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#fc6723' } } })}; ` -const VimeoBase = ({ ratio, ...props }) => ( +const VimeoBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' height={59.1 * ratio} @@ -363,11 +314,7 @@ const VimeoBase = ({ ratio, ...props }) => ( </Svg> ) -VimeoBase.defaultProps = { - ratio: 0.8 -} - -const FlickrBase = ({ ratio, ...props }) => ( +const FlickrBase = ({ ratio = 0.8, ...props }) => ( <Svg xmlns='http://www.w3.org/2000/svg' overflow='visible' @@ -387,10 +334,6 @@ const FlickrBase = ({ ratio, ...props }) => ( </Svg> ) -FlickrBase.defaultProps = { - ratio: 0.8 -} - export const Flickr = styled(FlickrBase)` ${style}; ${theme({ @@ -406,7 +349,7 @@ export const Vimeo = styled(VimeoBase)` ${theme({ _hover: { '.logo': { fill: '#1ab7ea' } } })}; ` -const RedditBase = ({ ratio, ...props }) => ( +const RedditBase = ({ ratio = 0.8, ...props }) => ( <Svg height={71.5 * ratio} viewBox='0 0 487 168' @@ -439,36 +382,24 @@ const RedditBase = ({ ratio, ...props }) => ( </Svg> ) -RedditBase.defaultProps = { - ratio: 0.8 -} - export const Reddit = styled(RedditBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#ff4500' } } })}; ` -export const NYTimes = ({ ratio, ...props }) => ( +export const NYTimes = ({ ratio = 0.8, ...props }) => ( <Svg height={27.3 * ratio} viewBox='0 0 49.072 6.46' {...props}> <path d='M3.683.662c0-.527-.495-.68-.908-.66v.082c.248.006.438.089.438.254 0 .114-.082.26-.33.26-.197 0-.578-.114-.883-.216C1.664.268 1.346.16 1.08.16c-.521 0-.915.388-.915.864 0 .387.292.527.413.578l.038-.064c-.076-.05-.152-.108-.152-.26 0-.115.101-.299.368-.299.241 0 .559.108.978.229.362.101.762.197.978.222v.825l-.407.337v.032l.407.356v1.136c-.21.121-.451.153-.66.153-.388 0-.756-.102-1.049-.426l1.093-.527V1.494l-1.34.597c.14-.356.419-.59.705-.762l-.02-.064C.725 1.481 0 2.211 0 3.113c0 1.08.876 1.88 1.873 1.88 1.08 0 1.766-.845 1.753-1.74l-.064-.006c-.158.343-.387.667-.685.838V2.98l.431-.343-.006-.038-.425-.343V1.43c.394 0 .806-.267.806-.769zM1.365 3.615l-.324.158c-.184-.24-.304-.565-.304-1.016 0-.184.019-.413.076-.571l.559-.248zm2.826.59l-.356.267.045.05.171-.12.597.546.8-.533-.038-.058-.21.134-.26-.26V2.4l.216-.158.457.368v1.62c0 1.01-.222 1.174-.679 1.34v.07c.756.031 1.435-.223 1.435-1.518v-1.74l.241-.191-.044-.057-.21.165-.654-.565-.762.571V.11h-.057l-.946.635v.058c.095.057.254.095.254.413zm4.877-.285l-.654.508-.68-.534v-.318l1.264-.844v-.038l-.629-.966-1.378.737v1.753l-.273.21.045.056.247-.196.902.654 1.207-.953zm-1.334-.44V2.173l.045-.032.584.921zM14.173.42a.748.748 0 0 0-.05-.248h-.064c-.083.223-.185.343-.445.343-.229 0-.406-.14-.502-.241 0 .006-.762.882-.762.882l.064.058.216-.248c.165.127.285.248.654.254v2.222L11.722.738c-.12-.203-.324-.508-.699-.508-.419 0-.806.362-.755.972h.076c.019-.165.101-.343.286-.343.146 0 .279.14.349.266v.87c-.483 0-.8.223-.8.616 0 .204.101.546.438.61l.006-.057c-.045-.045-.09-.095-.09-.184 0-.146.109-.242.305-.242.032 0 .121.006.14.013v1.13c-.565.006-1.003.318-1.003.851 0 .508.438.75.895.724l.006-.063c-.286-.032-.438-.165-.438-.35 0-.228.165-.348.375-.348.216 0 .406.133.54.285l.768-.857-.064-.057-.197.222c-.292-.26-.457-.356-.793-.406V1.208l2.152 3.753h.153v-3.74c.413-.026.8-.337.8-.8zm1.924 3.499l-.654.508-.68-.534v-.317l1.264-.845v-.038l-.629-.965-1.378.737v1.752l-.273.21.045.057.248-.197.901.654 1.207-.952-.051-.07zm-1.334-.439V2.173l.045-.032.584.921zm5.702-1.46l-.196.146-.508-.432-.59.534.24.228V4.51l-.647-.413V2.46l.21-.146-.623-.578-.578.534.241.228v1.911l-.082.051-.565-.4V2.453c0-.369-.178-.477-.413-.623-.197-.12-.286-.222-.286-.406 0-.152.153-.241.229-.286-.006-.006-.006-.063-.006-.063-.203-.006-.769.216-.781.73-.006.267.12.38.254.508.133.127.254.248.254.47v1.543l-.286.222.045.058.26-.204.705.553.666-.451.737.45 1.416-.825V2.34l.35-.255-.045-.063zM25.412.554l-.267.241-.596-.52-.87.647v-.61h-.09l.02 4.325c-.09-.013-.311-.063-.515-.095L23.075.93a.633.633 0 0 0-.666-.635c-.49 0-.807.374-.807.749h.076c.026-.159.108-.299.267-.299.165 0 .305.102.305.458v1.041c-.49.02-.769.292-.769.629 0 .21.096.533.439.546l.012-.064c-.114-.05-.14-.12-.14-.184 0-.152.147-.215.35-.215h.095v1.65c-.387.134-.565.42-.565.744 0 .444.356.78.876.78.369 0 .686-.063 1.023-.14.273-.056.603-.12.762-.12.203 0 .292.095.292.242 0 .183-.083.254-.19.285l.012.064c.438-.083.692-.343.692-.737 0-.406-.387-.648-.82-.648-.221 0-.66.07-.99.147-.368.082-.743.12-.857.12-.184 0-.413-.089-.413-.336 0-.223.184-.4.642-.4.247 0 .527.038.831.107.324.07.61.16.89.16.387 0 .736-.14.736-.706V.877l.311-.266zM24.32 2.199a.447.447 0 0 1-.318.152c-.146 0-.254-.089-.323-.152V1.01l.273-.184.368.337zm0 .793a.463.463 0 0 0-.318-.133.527.527 0 0 0-.323.133v-.698c.057.05.184.14.323.14.14 0 .254-.077.318-.14zm0 1.245c0 .216-.146.425-.426.425a2.44 2.44 0 0 1-.215-.012V3.088a.499.499 0 0 1 .323-.147c.134 0 .242.077.318.147zm3.645-1.893l-.864-.616-1.295.744v1.74l-.267.216.038.056.21-.17.857.628 1.32-.807zm-1.416 1.683V2.122l.673.483V4.51zM30.51 1.8c0 .006-.05 0-.05 0a.38.38 0 0 1-.236.107.421.421 0 0 1-.298-.145h-.05l-.452.495-.463-.495-.788.545.038.064.21-.14.273.292v1.683l-.356.267.045.05.171-.12.642.546.832-.553-.038-.057-.235.14-.312-.28V2.325c.134.146.293.273.477.273.355 0 .552-.393.59-.8zm3.207 2.559l-.908.597-1.232-1.861.87-1.352.057-.006c.102.101.28.21.445.21a.467.467 0 0 0 .387-.21s.05.006.05 0c-.03.54-.393.844-.666.844-.28 0-.413-.127-.559-.216l-.082.121 1.333 1.975.267-.165zm-2.934-.153l-.355.267.044.05.171-.12.597.546.8-.533-.044-.058-.203.134-.26-.26V.11h-.058l-.965.64v.058c.095.057.273.083.273.406zm7.36-3.543c0-.527-.496-.68-.908-.66v.082c.247.006.438.089.438.254 0 .114-.083.26-.33.26-.197 0-.578-.114-.883-.216-.337-.114-.654-.222-.92-.222-.522 0-.915.388-.915.864 0 .387.292.527.412.578l.039-.064c-.077-.05-.153-.107-.153-.26 0-.114.102-.299.368-.299.242 0 .56.108.978.229.362.102.762.197.978.223v.825l-.406.337v.031l.406.356v1.137c-.21.12-.45.152-.66.152-.387 0-.756-.102-1.048-.425l1.092-.527V1.494l-1.34.597c.14-.356.42-.59.705-.762l-.019-.064c-.793.216-1.517.946-1.517 1.848 0 1.08.876 1.88 1.873 1.88a1.71 1.71 0 0 0 1.753-1.74l-.064-.006c-.159.343-.387.667-.686.838V2.98l.432-.343-.006-.038-.425-.343V1.43c.393 0 .806-.267.806-.769zm-2.318 2.953l-.324.158c-.184-.24-.305-.565-.305-1.016 0-.184.02-.413.076-.571l.56-.248-.007 1.677zM39.058.414L39.02.408l-.533.45v.039l.45.508h.045l.533-.445-.005-.03-.45-.515zm.813 3.944l-.203.133-.26-.26V2.389l.253-.19-.05-.064-.197.152-.464-.552-.762.534.045.07.19-.128.235.292V4.23l-.343.26.038.051.178-.127.584.534.8-.534zm4.445-.032l-.19.127-.286-.26v-1.81l.273-.203-.045-.058-.235.178-.61-.565-.787.559-.603-.56-.775.553-.476-.552-.762.533.038.07.19-.127.26.286v1.727l-.209.21.61.514.59-.534-.24-.228V2.383l.228-.153.413.381v1.613l-.204.21.616.514.578-.533-.241-.229V2.37l.203-.133.438.374V4.2l-.178.184.623.565.819-.559zm2.318-.407l-.654.509-.68-.534v-.317l1.264-.845v-.038l-.629-.965-1.378.737v1.81l.92.666 1.207-.953zM45.3 3.481V2.173l.045-.032.584.921zm3.772-.248l-.514-.388c.343-.298.476-.699.476-.971a1.95 1.95 0 0 0-.013-.172h-.063c-.051.14-.153.26-.362.26-.203 0-.35-.114-.477-.254l-1.2.655v.971l.445.35c-.451.4-.534.679-.534.882 0 .267.121.458.35.546l.031-.057c-.057-.05-.108-.083-.108-.203 0-.09.108-.216.312-.216.26 0 .419.177.501.273 0-.006 1.156-.692 1.156-.692zm-.286-.8c-.178.317-.59.628-.819.806l-.292-.229v-.946c.114.254.394.47.698.47a.796.796 0 0 0 .413-.102zm-.47 2.12c-.133-.298-.444-.514-.762-.514-.076 0-.298 0-.501.127.12-.203.476-.584.933-.857l.33.254z' /> </Svg> ) -NYTimes.defaultProps = { - ratio: 0.8 -} - -export const TheGuardian = ({ ratio, ...props }) => ( +export const TheGuardian = ({ ratio = 0.8, ...props }) => ( <Svg height={68 * ratio} viewBox='0 0 295 97' {...props}> <path d='M66.9 51.7c1-.5 2.1-1.1 3.1-1.6.4-.2 1.8-.7 2-1.1.1-.2 0-.8 0-1.1V9.5c0-.1.1-.8 0-.9-.1-.1-.9 0-1 0h-2.2c-.8 0-.7.1-1.2.7-1.9 2.5-3.8 5-5.7 7.6-.9 1.2-1.8 2.3-2.6 3.5-.6.8-.6.9-1.7.9l.3-6.6c.1-1.6.1-3.2.2-4.8 0-.6.1-1.2.1-1.8 0-.2-.1-.8 0-.9.2-.3 2-.1 2.5-.1h37.4c.2 0 1.1-.1 1.3 0 .2.1.1.7.1 1 .1 1.3.1 2.7.2 4 .1 2.9.2 5.7.4 8.6v.6c-.5 0-.9.1-1.3-.2-.4-.3-.7-.9-1-1.3-1.2-1.6-2.4-3.3-3.7-4.9l-3.6-4.8c-.2-.3-.5-1-.9-1.2-.3-.2-.9-.1-1.3-.1h-1.6c-.2 0-1-.1-1.2 0-.1.1 0 .1-.1.3-.2.8 0 1.8 0 2.6v34.8c0 .7-.2 1.7 0 2.4s1.8 1.2 2.5 1.5c.7.4 1.9.7 2.5 1.3.2.2.4 1.2.2 1.5-.1.1-.6 0-.7 0h-22c-.2 0-.9.1-1 0-.1-.4 0-1.2 0-1.5zm37.1-1.8V7.5c0-.6.2-1.5 0-2.1-.2-.7-1.4-.8-2.1-1.1-.4-.1-1.7-.4-1.9-.8v-.8h.3c.4-.2 1.2-.2 1.7-.3.9-.2 1.8-.3 2.6-.5 2-.4 4.1-.8 6.1-1.1 1.2-.2 2.4-.5 3.6-.7.3 0 1.5-.2 1.6 0 .1.1 0 .5 0 .6v20.7c3.8-3.8 10.4-5.9 15.7-4.6 4.6 1.1 6.1 5.4 6.1 9.8.1 5.6 0 11.1 0 16.7v4.5c0 .5-.2 1.7 0 2.2.1.2.5.3.7.5.7.4 1.5.8 2.2 1.2.1.1.4.2.4.3.1.1.1 1 0 1.1-.1.2-.1.1-.4.1-1.1.2-2.3 0-3.3 0h-14.4c-.1 0-.6.1-.7 0-.1-.1-.1-1.2 0-1.3.3-.4 1.5-.8 1.9-1.1.3-.2 1.2-.5 1.4-.8.2-.3 0-1.4 0-1.7v-4.1c0-5.8.1-11.7 0-17.5 0-1.7-.3-3.7-2-4.6-.9-.5-2.1-.6-3.1-.6-.8 0-1.6.2-2.3.4-.6.2-1.7.6-2.1 1.1-.3.4-.1 1-.1 1.5v23.6c0 .5-.2 1.5 0 1.9.1.2.5.4.8.5.7.4 1.6.8 2.3 1.2.1.1.3.1.3.2.1.1.1 1 0 1.1-.1.1-.2.1-.4.1-1.1.1-2.3 0-3.4 0h-14.4c-.1 0-.6.1-.7 0-.1-.1 0-1.1.1-1.3.3-.4 1.4-.8 1.8-1 .7-.3 1.2-.6 1.7-.9zm47.5-13.8c.2 4.4 1.6 9.3 5.6 11.7 2.1 1.2 4.7 1.6 7.1 1.4 2.9-.3 5.3-1.7 7.8-3 0 .4.1 1.1 0 1.5-.2.4-.7.9-1 1.2-.4.4-.9.9-1.4 1.3-1.7 1.4-3.6 2.4-5.6 3.1-3.8 1.3-8.2 1.2-12.1.2-3.1-.8-5.9-2.3-8-4.7-2.1-2.4-3.3-5.5-3.8-8.7-1.1-6.9.2-14.8 5.9-19.4 5-4 13-4.8 18.9-2.4 7.2 2.9 8.4 11.1 8.4 17.9h-19.1c-.9-.1-1.8-.1-2.7-.1zm-.2-1.7c2-.1 4-.2 6.1-.4 1.2-.1 2.5-.1 3.7-.2.2 0 .7 0 .9-.1.3-.2.1-2.2.1-2.6-.1-3.6-.2-8-2.3-11.1-1.5-2.2-3.8-1.8-5.2.2-2.9 3.9-3.3 9.7-3.3 14.2zM-.1 70.9c0-5.6 1.1-11.4 4.2-16.1 3-4.6 7.8-7.6 13-9.1 6.3-1.8 13.3-1.6 19.8-.4 1.4.3 2.8.6 4.1 1 .2.1 1.1.3 1.2.5v.3c.3 1.2.1 2.7.1 3.9.1 3.1.1 6.3.2 9.4-.4 0-1.1.1-1.4 0-.2-.1-.4-.6-.5-.8-.8-1.2-1.6-2.4-2.3-3.7-1.7-2.7-3.5-5.4-5.2-8.1-.9-1.5-3.4-1.5-5-1.5-1.8 0-3.6.3-5.1 1.2-3.4 2.1-5 6.2-5.9 9.9-1.4 5.9-1.3 12.1-1 18.1.3 4.6.7 9.5 2.5 13.7 1.1 2.6 3 4.9 5.9 5.5.9.2 1.8.2 2.8.1.6-.1 2.7-.2 3-.8.1-.2 0-.7 0-.9V76.7c0-.7.2-1-.4-1.4-.7-.4-1.5-.8-2.2-1.3-.5-.3-1.5-.6-1.8-1-.2-.2-.3-1.3-.1-1.5.1-.2.1-.1.4-.1.9-.2 2.1 0 3 0h15.5c1 0 2.1-.1 3.1 0h.4c.1.1.1 1.5 0 1.7-.2.3-1.2.7-1.6.9-.7.4-1.5.8-2.2 1.3-.8.4-.7.4-.7 1.3v16.3c0 .2.1.7 0 .9-.2.5-2.3.8-2.9 1-1.7.5-3.5.9-5.3 1.2-3.5.6-7 .8-10.5.7-5.6-.2-11.5-1.4-16.1-4.8-4-2.9-6.6-7.3-7.8-12.1C.2 77-.1 73.9-.1 70.9zM46 61.8c0-.2-.1-1 0-1.1.1-.1.2 0 .3-.1.6-.3 1.4-.3 2.1-.4 2.3-.4 4.6-.8 7-1.2 1.8-.3 3.6-.7 5.3-.9.5-.1 1.1-.1 1.6.1.5.1.3 0 .4.4.2 1.2 0 2.6 0 3.8v20.9c0 2.5-.7 7.1 1.7 8.6 1.2.8 2.9.8 4.3.5 1.1-.2 3.2-1 3.6-2.2.1-.3 0-.7 0-1V64.7c0-.2.1-.8 0-1-.3-.3-1.3-.6-1.6-.7-.6-.2-1.1-.5-1.7-.7-.2-.1-.9-.2-1-.4-.1-.1-.1-1 0-1.1.1-.1.1 0 .2-.1.5-.3 1.4-.2 1.9-.3 4.1-.7 8.3-1.6 12.5-2.2.5-.1 1-.1 1.5 0s.3-.1.4.4c.2 1 0 2.4 0 3.5v28.8c0 .3-.1.8 0 1.2.1.3 0 .2.5.4 1 .4 2.1.9 3.1 1.3.3.1.4.1.5.3.1.2.1.9 0 .9-.2.2-1.2.1-1.4.2-2.2.3-4.4.5-6.7.8-2 .2-4 .5-5.9.7-.4.1-.8.1-1.2 0-.2 0-.8 0-.9-.1-.1-.2 0-1 0-1.2v-1.7c0-.3.2-1.1 0-1.4-.2-.3-.6.1-.9.3-.8.7-1.7 1.4-2.6 1.9-3.3 2-7.4 2.9-11.2 2.1-2.8-.6-5.2-2.2-6.4-4.9-.9-1.9-1.1-4-1.1-6v-21c0-.2.1-.8 0-1-.2-.3-1.4-.6-1.7-.8-1-.4-1.8-.7-2.6-1.1zm94.3-3.8c.2 0 1.1 0 1.2.2.1.1 0 .8 0 .9v8.8c0 .3-.1.8 0 1.1v.2c.4.4.5-.9.6-1 .9-3.7 2.6-8 6.4-9.5.7-.3 1.4-.4 2.1-.5.6 0 2.3-.2 2.6.3.1.2 0 .7 0 .9v10.2c-2.4-.5-5.1-.4-7.4.1-1.1.2-2.1.5-3.1 1-.5.2-.6.1-.7.5-.1.4 0 1.1 0 1.5V92c0 .2-.1.5 0 .7.2.3.9.5 1.2.6.5.3 1.1.6 1.6.9.2.1.5.2.6.4.1.1.1 1.3 0 1.4-.1.1-.7 0-.9 0h-16.6c-.5 0-1.4.2-1.8 0h-.3c-.1-.1 0-1.2 0-1.3.2-.6 1.5-1 2.1-1.3.4-.2 1.2-.5 1.4-.9.1-.2 0-.8 0-1V63.7c0-.1.1-.6 0-.7-.1-.1-.6-.2-.8-.2-.6-.2-1.2-.4-1.8-.5-.6-.2-2.1-.3-1.6-1.3.1-.3.5-.2.9-.3 4.4-.8 8.7-1.6 13.1-2.4.4-.2.8-.2 1.2-.3zm37.7.9V48.6c0-.3.1-.9 0-1.2-.1-.2-.5-.3-.8-.4-.8-.3-1.6-.6-2.5-.9-.6-.2-.9-.1-.9-.8 0-.6-.1-.4.4-.5 1.1-.4 2.4-.4 3.5-.6 3.3-.6 6.5-1.2 9.8-1.8.7-.1 1.4-.3 2.1-.2.8.1.9-.1.9.6.1 1.6 0 3.3 0 4.9v43.8c0 .4-.1.4.2.6.6.4 1.6.6 2.2.8.4.1 1.5.3 1.7.6.1.1.1 1.2 0 1.3-.1.1-.7.1-.8.1-1.4.2-2.7.4-4.1.5-3.1.4-6.2.8-9.4 1.2-.5.1-1.7.3-1.9-.1-.2-.4 0-1.7 0-2.1 0-.3.2-1.6 0-1.8-.2-.2-2.4 1.8-2.7 2-1.2.8-2.5 1.4-3.9 1.8-2.2.6-4.7.6-6.9.1-9.6-2.2-11.6-13.6-10.8-21.9.4-4.4 1.8-8.8 4.8-12 2.8-2.9 6.6-4.4 10.5-4.7 3-.3 5.9-.1 8.6 1zm0 31.9V61.6c0-.6-.1-.7-.8-1.1-1.4-.8-3.2-1.1-4.7-.5-2.3.9-3.4 3.6-4 5.8-1.2 4-1.3 8.3-1.2 12.5.1 3.6.2 8 2.2 11.2 1.8 2.8 5.9 3.5 8.5 1.3zM211.1 58c.5.1 1.1-.1 1.3.4.1.3 0 1 0 1.3V91c0 .4-.1 1 0 1.4.1.4.5.5.9.7.6.3 1.1.6 1.7.9.2.1.8.3.9.6 0 .1.1 1.3 0 1.4h-.3c-.6.1-1.4 0-2.1 0h-15.2c-.4 0-1.5.2-1.8 0-.2-.1-.3-1.3-.1-1.5.2-.3.9-.5 1.2-.6.6-.3 1.2-.7 1.8-1 .5-.3.4-.2.4-.6.2-1.5 0-3.2 0-4.7V65.3c0-.4.1-1.1 0-1.5-.1-.4-.6-.4-1-.6-.7-.3-1.3-.5-2-.8-.2-.1-1-.2-1.2-.5-.1-.1-.1-1.1 0-1.2.1-.1.3 0 .4-.1.8-.3 1.7-.3 2.6-.5 1.3-.2 2.5-.5 3.8-.7 2.5-.4 4.9-.9 7.4-1.3.5.1.9 0 1.3-.1zm1.4-9.3c-.2 6-8.3 8.6-12 3.9-1.7-2.2-1.8-5.2-.3-7.5s4.4-3.3 7.1-2.7c3 .6 5.2 3.2 5.2 6.3zm43.8 43.9V63.9c0-.1.1-.6 0-.7-.1-.2-.7-.3-.9-.3l-1.8-.6c-.3-.1-1.1-.2-1.3-.5-.2-.2-.1-.7-.1-1 0-.6.2-.5.8-.6l6.6-1.2 6.6-1.2c.4-.1.7-.2 1.1-.2.2 0 1.2 0 1.4.1.1.1 0 .7 0 .9v1.9c0 .3-.2 1.2 0 1.5.2.4.6 0 .9-.3.9-.7 1.8-1.3 2.8-1.8 3.6-2 7.9-2.9 12-2.3 2.8.4 5.1 1.9 6.1 4.6.7 1.9.8 3.9.8 5.9v22.8c0 .4-.1 1.1 0 1.5.1.4.4.5.9.7.5.3 1.1.6 1.6.9.2.1.9.3 1 .6.1.2.1 1.2 0 1.3-.1.2.1 0-.2.1-.4.2-1.3 0-1.8 0h-14.3c-.6 0-2.9.3-3.2-.1-.1-.1-.1-1.2 0-1.4.1-.2.7-.4.9-.5.6-.3 1.1-.6 1.7-.9.2-.1.8-.3.9-.5.1-.2 0-.6 0-.8V69.1c0-1.6.1-3.4-.9-4.8-.8-1.2-2.2-1.5-3.6-1.6-1.1 0-2.1.1-3.1.4-.5.2-2 .6-2.3 1.2-.1.2 0 .6 0 .8V91c0 .3-.1 1 0 1.3.1.4.7.5 1 .7.5.3 1.1.6 1.6.9.2.1.6.3.7.4.1.1.1 1.3 0 1.4 0 .1-.1 0-.2 0-.4.2-1.4 0-1.8 0h-16.8c-.5 0-.6.1-.7-.2-.1-.2-.1-1.1 0-1.3.1-.2.7-.4.9-.5 1-.1 1.8-.6 2.7-1.1zm-21.2-18.4c0-2.6.1-5.3-.1-8-.3-2.9-1.1-6.1-4.4-6.7-1-.2-2.8-.5-3.5.3-.7.7-1.2 1.7-1.8 2.5l-5.1 6.9c-.3.4-.6 1.2-1 1.4-.1.1-1.1.1-1.1 0-.1-.1 0-.8 0-1v-8.1c0-.3-.1-.8 0-1.1.2-.5 2.4-.8 2.9-1 2.8-.7 5.7-1.2 8.6-1.4 4.1-.3 8.7-.2 12.5 1.6 3 1.4 4.9 3.9 5.4 7.1.3 1.6.2 3.4.2 5v20c0 .3-.2 1.1 0 1.3.1.1.6.2.7.2.8.2 1.5.4 2.3.6.5.1.6.1.6.6s.1.5-.5.7c-.7.3-1.4.6-2.1.8-3.7 1.1-9.5 1.4-12.2-2-.2-.3-.8-1.6-1.1-1.7-.4-.1-1.6 1.5-2 1.8-1.6 1.4-3.7 2.2-5.8 2.5-3.9.5-8.1-.3-10.5-3.7-2-2.9-2.4-7.4-.9-10.6 2.7-6.1 10.7-6.7 16.5-7.7.7 0 1.5-.2 2.4-.3zm0 16.6V76c-3 .2-6.1.4-7.2 3.7-.8 2.2-.8 4.8-.5 7.1.2 1.6.6 3.6 2.1 4.6 1.6 1.1 4.3.9 5.6-.6zM108.5 74.2c0-2.6.1-5.3-.1-8-.3-2.9-1.1-6.1-4.4-6.7-1-.2-2.8-.5-3.5.3-.7.7-1.2 1.7-1.8 2.5l-5.1 6.9c-.3.4-.6 1.2-1 1.4-.1.1-1.1.1-1.1 0-.1-.1 0-.8 0-1v-8c0-.3-.1-.8 0-1.1.2-.5 2.3-.8 2.9-1 2.8-.7 5.7-1.2 8.5-1.4 4.1-.3 8.7-.2 12.5 1.6 3 1.4 4.9 3.9 5.4 7.1.3 1.6.2 3.4.2 5v20c0 .3-.2 1.1 0 1.3.1.1.6.2.7.2.8.2 1.5.4 2.3.6.5.1.6.1.6.6s.1.5-.5.7c-.7.3-1.4.6-2.1.8-3.7 1.1-9.5 1.4-12.2-2-.2-.3-.8-1.6-1.1-1.7-.4-.1-1.6 1.5-1.9 1.8-1.6 1.4-3.7 2.2-5.8 2.5-3.9.5-8.1-.3-10.5-3.7-2-2.9-2.4-7.4-.9-10.6 2.7-6.1 10.7-6.7 16.4-7.7.8-.1 1.6-.3 2.5-.4zm0 16.6V76c-3 .2-6.1.4-7.2 3.7-.8 2.2-.8 4.8-.5 7.1.2 1.6.6 3.6 2.1 4.6 1.6 1.1 4.3.9 5.6-.6z' /> </Svg> ) -TheGuardian.defaultProps = { - ratio: 0.8 -} - -export const CNNBase = ({ ratio, ...props }) => ( +export const CNNBase = ({ ratio = 0.8, ...props }) => ( <Svg height={96 * ratio} viewBox='0 0 1000 464.6231995' {...props}> <path className='logo' @@ -485,26 +416,18 @@ export const CNNBase = ({ ratio, ...props }) => ( </Svg> ) -CNNBase.defaultProps = { - ratio: 0.8 -} - export const CNN = styled(CNNBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#c00' } } })}; ` -export const TheWashingtonPost = ({ ratio, ...props }) => ( +export const TheWashingtonPost = ({ ratio = 1, ...props }) => ( <Svg height={31.7 * ratio} viewBox='0 0 122.227 18.729' {...props}> <path d='M6.804 5.766v6.625c.895-.484 1.522-1.325 1.826-2.274l.072.036c-.197 2.363-1.809 4.726-4.315 4.726C1.862 14.88 0 13 0 9.991c0-2.256 1.468-3.67 3.348-4.942a3.283 3.283 0 0 0-.841-.107c-1.29 0-2.042.877-2.042 1.773H.358C.34 6.589.34 6.464.34 6.339c0-1.594.842-3.528 2.883-3.528 1.307 0 2.31 1.2 3.832 1.2.608 0 1.36-.287 1.665-.95h.053c-.017 1.165-.375 2.365-1.969 2.705zm.967 6.786c-.896.949-1.862 1.755-3.116 1.755-2.327 0-4.118-1.827-4.118-4.477 0-1.558.645-2.399 1.361-3.384h-.072C1.38 6.894.197 8.022.197 9.937c0 2.937 1.844 4.746 4.261 4.746 1.684 0 2.83-1.164 3.349-2.113zm.716-8.684c-.304.573-.949 1.307-2.256 1.307s-2.507-.896-3.563-.896c-.967 0-1.63.645-1.88 1.129l.018.036c.34-.34.859-.681 1.7-.681 1.397 0 2.292.86 3.707.86 1.504 0 2.184-.985 2.31-1.737zM3.509 5.103c-.913.95-1.755 1.988-1.755 4.011 0 1.11.376 2.256 1.218 2.972l.52-.269V7.02l-.484.25-.09-.178L5.425 5.73c-.68-.143-1.289-.448-1.916-.627zm3.098.699c-.126.017-.25.017-.394.017-.25 0-.483-.017-.716-.071v5.228L3.15 12.248c.484.358 1.074.572 1.826.572.61 0 1.146-.125 1.63-.34V5.802zm-2.578.913l-.34.197v4.798l.34-.179zm10.295.68v6.195c0 1.72-1.522 2.883-3.223 3.223l-.036-.071a2.371 2.371 0 0 0 1.325-2.15v-6.41l-.966-.876-.376.411v4.996l.537.483v.036l-1.45 1.576-1.665-1.522v-.072l.644-.68V4.62l1.898-2.023.036.018v4.798l1.558-1.683 1.629 1.47.304-.323.144.126zM9.311 13.25v-.036l.376-.376V4.315l-.376.395v7.95l-.573.572v.036l1.396 1.253.25-.286zm3.652-5.354L11.8 6.894l-.25.268 1.038.932v6.445c0 .43-.09.877-.25 1.128l.018.018c.447-.322.609-.806.609-1.432V7.896zm4.208 3.098v.913l1.737 1.36 1.002-1.073.144.143-2.328 2.488-2.363-1.897-.358.376-.144-.144.412-.43V8.2l3.384-2.47 1.773 2.865zm-1.325 1.576V8.022l-.376.268v4.459l2.22 1.808.287-.304zm1.36-5.515l-.035.018v3.67l1.594-1.163zm.466-.358l-.322.232 1.576 2.525.322-.233zm14.429 8.111l-2.489-2.149-1.898 2.149-2.578-2.22v-3.51h-.501c-.448 0-.68.287-.788.627h-.054a2.845 2.845 0 0 1-.09-.68c0-.466.126-1.684 1.433-1.684v-3.08c0-.59-.698-.823-.698-1.61 0-1.021.966-2.024 2.74-2.651l.07.054c-.644.376-.984.734-.984 1.504 0 1.182 1.146.877 1.146 2.74v.716l2.095-2.203 2.202 2.167 2.077-2.167 2.006 1.97v6.625zM25.71 12.3V8.523h-1.003c-.52 0-.752.34-.788.645l.018.018c.18-.197.358-.304.77-.304h.627v3.616l2.363 2.042.269-.323zm0-8.218c0-.734-.644-.985-.644-1.45 0-.645.25-1.182.644-1.684l-.036-.017c-.537.412-1.038 1.074-1.038 1.718 0 .645.698.95.698 1.522v3.17h.376zm3.778 1.79l-1.36-1.325-.717.734v6.338L29.04 13l.447-.502zm.573 6.392V5.623l-1.522-1.504-.287.286 1.433 1.379v6.678l2.417 2.095.287-.269zm3.474-6.625l-1.128-1.074-.645.662v6.375l1.755 1.54.018-.018zm.572-.25L32.8 4.119l-.268.286 1.2 1.146v7.484l.375-.358zm7.607 9.419l-1.7-1.54-1.522 1.54-1.863-1.648-.25.269-.144-.143.323-.34V8.147l3.366-2.435 1.934 1.504.34-.358.144.143-.394.412v4.96l.948.877.305-.322.143.125zm-4.583-1.988V7.986l-.376.268V13l1.719 1.54.286-.287zm2.882-4.709l-1.468-1.146-.053.036v5.21l1.217 1.057.304-.304zm.574 4.87V7.844l-1.522-1.236-.358.25L40.21 8.04v5.12l1.504 1.361.268-.286zm6.338-4.01h1.844v3.831l-2.847 2.006c-.376-.43-.913-.734-1.575-.734-.538 0-.968.179-1.54.662l-.09-.036 2.435-3.545h-1.504v-3.33l2.99-2.077c.359.286.627.447 1.093.447.358 0 .877-.071 1.271-.393l.072.035zm-2.005 4.583c-.52 0-.931.18-1.29.43v.036c.287-.125.573-.161.842-.161.412 0 1.056.197 1.486.698l.412-.304c-.34-.394-.752-.699-1.45-.699zm1.915-3.008h-1.003l-2.095 3.027.018.035c.52-.376 1.021-.626 1.63-.626.537 0 1.092.25 1.432.68l.018-.018zm-2.614 0V7.664l-.376.268v3.009h1.45l.287-.394h-1.36zm3.742-3.51c-.376.27-.59.413-1.217.413-.358 0-.788-.161-1.128-.52l-.036.018v2.615h.68l1.72-2.507zm-.859-.16c-.322 0-.734-.161-1.003-.52l-.447.305c.34.412.662.59 1.163.59.322 0 .788-.089 1.272-.501l.017-.053a2.76 2.76 0 0 1-1.002.179zm.304 3.08h-1.164l-.268.376h1.056v3.473l.376-.268zm7.538-2.56v6.194c0 1.72-1.522 2.883-3.223 3.223l-.035-.071a2.371 2.371 0 0 0 1.325-2.15v-6.41l-.967-.876-.376.411v4.996l.537.483v.036l-1.45 1.576-1.665-1.522v-.072l.644-.68V4.62l1.898-2.023.036.018v4.798l1.558-1.683 1.63 1.469.303-.323.144.126zm-5.013 5.854v-.036l.376-.376V4.315l-.376.394v7.95l-.573.573v.036l1.396 1.253.25-.286zm3.653-5.354l-1.164-1.002-.25.268 1.038.932v6.445c0 .43-.09.877-.251 1.128l.018.018c.448-.322.609-.806.609-1.432V7.896zm4.62 6.912l-1.54-1.415-.359.376-.143-.143.412-.448V8.004l-.752-.716-.287.322-.143-.143 1.611-1.755 1.432 1.29.359-.395.16.126-.447.483v5.229l.86.805.394-.412.143.144zm-1.057-1.755V7.717l-.931-.859-.251.287.806.77v5.317l1.432 1.29.269-.287zm.537-7.484l-1.468-1.343 1.343-1.432 1.468 1.342zm-.913-1.63l-.269.269L57.668 5.3l.268-.304zm9.003 10.869l-1.558-1.415V8.165l-.949-.86-.501.538v4.834l.555.52v.07l-1.468 1.54-1.665-1.521v-.054l.644-.68V8.04l-.841-.77-.34.376-.144-.143 1.63-1.773 1.629 1.45v.358l1.7-1.808 1.594 1.432.358-.376.162.143-.43.448v5.12l.806.753.394-.43.143.143zM61.05 13.25v-.036c0 .036.358-.358.358-.358V7.771l-1.02-.931-.251.268.895.824v4.727l-.555.573v.036l1.379 1.253.286-.304zm3.742-.143V7.86l-1.11-1.003-.286.304 1.02.913v5.21l1.343 1.254.286-.304zm6.034 4.924c-.59-.645-1.002-.914-1.557-.914-.591 0-1.272.233-1.97.61l-.054-.054 2.471-2.865-1.754-1.397-.34.359-.144-.126.394-.43V8.148l3.402-2.435 1.898 1.504.322-.358.143.143-.376.412v6.124c0 .93.52.895.52 1.593 0 .806-1.164 1.558-2.955 2.9zm-2.381-4.96V8.004l-.376.269v4.96l1.772 1.432.27-.323zm1.253 3.581c-.59 0-1.128.18-1.629.52v.035c.322-.125.68-.286 1.29-.286.554 0 1.02.304 1.485.841l.358-.286c-.447-.52-.985-.824-1.504-.824zm2.185-1.719c-.448-.286-.555-.59-.555-1.36v-.323l-2.973 3.438.018.017c.573-.34 1.093-.59 1.934-.59.716 0 1.2.286 1.755.752.34-.287.573-.573.573-1.02 0-.359-.305-.627-.752-.914zm-.555-6.822L69.84 6.948l-.036.035v5.497l1.147.895.376-.43zm1.092 6.572c-.466-.359-.52-.663-.52-1.433V7.807L70.395 6.59l-.34.233 1.468 1.164V13.5c0 .77.036.985.52 1.307.43.286.77.59.77 1.002 0 .108-.018.287-.018.287l.018.018a.63.63 0 0 0 .197-.466c0-.394-.197-.662-.591-.966zm4.297.125l-1.647-1.29-.34.377-.143-.144.393-.43V7.056h-1.038l-.036-.036.627-.931h.447v-1.2l1.898-2.023.036.036v3.187h1.432l.036.036-.627.931h-.841v5.425l.985.753.376-.412.143.143zM75.552 4.584l-.376.412v1.092h.376zm0 8.559V7.055h-.376v6.302l1.522 1.182.269-.286zm8.72-5.569v5.014l-3.026 2.238-2.274-1.72-.269.305-.143-.143.322-.358V8.004l3.17-2.274 2.112 1.647.34-.358.144.143zm-4.816 5.157V7.843l-.377.268v4.817l2.15 1.647.34-.25zm2.882-4.566l-1.504-1.182-.018.018v5.336l1.522 1.146zm.573-.322l-1.665-1.29-.34.251 1.63 1.253v5.569l.375-.286zm8.2 6.965l-1.557-1.415V8.165l-.949-.86-.501.538v4.834l.555.52v.07l-1.468 1.54-1.666-1.521v-.054l.645-.68V8.04l-.842-.77-.34.376-.143-.143 1.63-1.773 1.629 1.45v.358l1.7-1.808 1.594 1.432.358-.376.161.143-.43.448v5.12l.806.753.394-.43.143.143zm-4.726-1.558v-.036c0 .036.358-.358.358-.358V7.771l-1.02-.931-.251.268.895.824v4.727l-.555.573v.036l1.379 1.253.286-.304zm3.742-.143V7.86l-1.11-1.003-.287.304 1.02.913v5.21l1.344 1.254.286-.304zm12.046 1.701c-.501-.537-.68-.717-1.271-.878v3.51l-.036.017-.716-.644-2.077 1.916-.036-.018v-4.816c-.627.143-1.29.465-1.934 1.11l-.036-.018c.125-1.379.806-2.4 1.97-2.793V8.702h-.377c-.519 0-.805.269-1.056.752h-.054c-.053-.16-.09-.412-.09-.823 0-.753.556-1.54 1.47-1.54h.106V5.157l-.734-.663-.358.359-.125-.126 1.808-1.916 1.683 1.54v1.63l.394-.43v-2.06h.197v1.88l2.381-2.56 2.023 1.845v7.788zm-4.136-1.576c-.734.143-1.253.59-1.593 1.182l.018.036c.501-.43.966-.627 1.575-.77zm.573-5.138h-.985c-.68 0-.949.43-.966.93l.017.018c.215-.358.43-.483.86-.536h.698v9.758l.376-.359zm0-3.224l-.895-.823-.287.304.806.716v2.024h.376zm2.095 1.02l-.394.413V16.67l.394.358zm2.346-.41l-1.057-.968-1.092 1.182v6.303c.931.09 1.576.358 2.13.967l.019-.018zm-2.149 7.752v.466c.609.143.86.322 1.29.823l.411-.322c-.43-.537-.86-.86-1.701-.967zm2.722-8.039l-1.218-1.128-.287.304 1.129 1.039v8.325l.376-.286zm7.931 2.381v5.014l-3.026 2.238-2.274-1.72-.268.305-.144-.143.323-.358V8.004l3.17-2.274 2.112 1.647.34-.358.143.143zm-4.816 5.157V7.843l-.376.268v4.817l2.148 1.647.34-.25zm2.883-4.566l-1.504-1.182-.018.018v5.336l1.522 1.146zm.573-.322l-1.666-1.29-.34.251 1.63 1.253v5.569l.376-.286zm5.514 1.128h1.845v3.831l-2.847 2.006c-.376-.43-.913-.734-1.576-.734-.537 0-.967.179-1.54.662l-.09-.036 2.436-3.545h-1.504v-3.33l2.99-2.077c.358.286.626.447 1.092.447.358 0 .877-.071 1.271-.393l.072.035zm-2.005 4.583c-.52 0-.931.18-1.29.43v.036c.287-.125.574-.161.842-.161.412 0 1.057.197 1.486.698l.412-.304c-.34-.394-.752-.699-1.45-.699zm1.916-3.008h-1.003l-2.094 3.027.017.035c.52-.376 1.02-.626 1.63-.626.537 0 1.092.25 1.432.68l.018-.018v-3.098zm-2.614 0V7.664l-.376.268v3.009h1.45l.286-.394h-1.36zm3.742-3.51c-.376.27-.59.413-1.218.413-.358 0-.788-.161-1.128-.52l-.036.018v2.615h.68l1.72-2.507zm-.86-.16c-.322 0-.734-.161-1.002-.52l-.448.305c.34.412.663.59 1.164.59.322 0 .788-.089 1.271-.501l.018-.053c-.304.125-.68.179-1.003.179zm.305 3.08h-1.164l-.268.376h1.056v3.473l.376-.268zm4.333 4.852l-1.647-1.29-.34.377-.144-.144.394-.43V7.056h-1.039l-.035-.036.626-.931h.448v-1.2l1.898-2.023.036.036v3.187h1.432l.036.036-.627.931h-.841v5.425l.985.753.376-.412.143.143zm-1.164-10.224l-.376.412v1.092h.376zm0 8.559V7.055h-.376v6.302l1.522 1.182.268-.286z' /> </Svg> ) -TheWashingtonPost.defaultProps = { - ratio: 1 -} - -const EtsyBase = ({ ratio, ...props }) => ( +const EtsyBase = ({ ratio = 0.8, ...props }) => ( <Svg aria-hidden='true' height={103.5 * ratio} viewBox='0 0 48 24' {...props}> <path className='logo' @@ -513,16 +436,12 @@ const EtsyBase = ({ ratio, ...props }) => ( </Svg> ) -EtsyBase.defaultProps = { - ratio: 0.8 -} - export const Etsy = styled(EtsyBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#f45800' } } })}; ` -const EvenBriteBase = ({ ratio, ...props }) => ( +const EvenBriteBase = ({ ratio = 0.8, ...props }) => ( <Svg height={35 * ratio} viewBox='0 0 26.872 4.549' {...props}> <path className='logo' @@ -532,16 +451,12 @@ const EvenBriteBase = ({ ratio, ...props }) => ( </Svg> ) -EvenBriteBase.defaultProps = { - ratio: 0.8 -} - export const EventBrite = styled(EvenBriteBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#f5662e' } } })}; ` -const TimeBase = ({ ratio, ...props }) => ( +const TimeBase = ({ ratio = 0.8, ...props }) => ( <Svg height={64 * ratio} viewBox='0 0 298 92.321' {...props}> <path className='logo' @@ -550,26 +465,18 @@ const TimeBase = ({ ratio, ...props }) => ( </Svg> ) -TimeBase.defaultProps = { - ratio: 0.8 -} - export const Time = styled(TimeBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#e90606' } } })}; ` -export const BBC = ({ ratio, ...props }) => ( +export const BBC = ({ ratio = 0.8, ...props }) => ( <Svg height={59.5 * ratio} version={1} viewBox='0 0 300 86.219' {...props}> <path d='M162.5 55.573c0 9.26-11.521 8.71-11.521 8.71h-11.523V47.55h11.523c11.865-.069 11.522 8.024 11.522 8.024m-23.045-33.538h8.78c9.121.48 8.778 7.27 8.778 7.27 0 8.436-10.082 8.573-10.082 8.573h-7.476V22.035zm20.92 19.135s7.886-3.36 7.818-12.277c0 0 1.199-14.608-18.159-16.391h-21.484v61.246h24.623s20.575.069 20.575-17.284c0 0 .48-11.796-13.374-15.294M104.784.5h90.432v85.22h-90.432V.5zM58.217 55.573c0 9.26-11.522 8.71-11.522 8.71H35.172V47.55h11.523c11.865-.069 11.522 8.024 11.522 8.024M35.172 22.035h8.78c9.121.48 8.778 7.27 8.778 7.27 0 8.436-10.082 8.573-10.082 8.573h-7.476V22.035zm20.92 19.135s7.886-3.36 7.818-12.277c0 0 1.199-14.608-18.159-16.391H24.267v61.246H48.89s20.575.069 20.575-17.284c0 0 .48-11.796-13.374-15.294M.5.5h90.432v85.22H.5V.5zm280.55 16.392V28.21s-11.042-6.79-23.25-6.928c0 0-22.77-.444-23.799 21.829 0 0-.823 20.489 23.525 21.655 0 0 10.22 1.234 24.073-7.613V68.88s-18.586 11.042-40.122 2.537c0 0-18.107-6.617-18.793-28.307 0 0-.755-22.308 23.388-29.716 0 0 6.447-2.469 18.038-1.372 0 0 6.927.687 16.94 4.87M209.068 85.72H299.5V.5h-90.432v85.22z' /> </Svg> ) -BBC.defaultProps = { - ratio: 0.8 -} - -const NasaBase = ({ ratio, ...props }) => ( +const NasaBase = ({ ratio = 0.8, color = 'black', ...props }) => ( <Svg version='1.1' xmlnsXlink='http://www.w3.org/1999/xlink' @@ -586,7 +493,7 @@ const NasaBase = ({ ratio, ...props }) => ( </defs> <path className='logo' - stroke={props.color} + stroke={color} d='M5 39V10a6 6 0 0 1 6-6 5.993 5.993 0 0 1 5.644 3.988l6.712 24.024A5.993 5.993 0 0 0 29 36a6 6 0 0 0 6-6V1' fillOpacity={0} strokeWidth={8} @@ -595,7 +502,7 @@ const NasaBase = ({ ratio, ...props }) => ( d='M40.5 41.5L51.356 7.988A5.992 5.992 0 0 1 57 4a5.992 5.992 0 0 1 5.644 3.988L73.5 41.5' fillOpacity={0} className='logo' - stroke={props.color} + stroke={color} strokeWidth={8} clipPath='url(#a)' /> @@ -603,7 +510,7 @@ const NasaBase = ({ ratio, ...props }) => ( d='M104 5H84.494a7.503 7.503 0 0 0-7.504 7.502 7.505 7.505 0 0 0 7.51 7.502h10A7.5 7.5 0 1 1 94.5 35L74 34.992' fillOpacity={0} className='logo' - stroke={props.color} + stroke={color} strokeWidth={8} strokeMiterlimit={0} /> @@ -611,24 +518,19 @@ const NasaBase = ({ ratio, ...props }) => ( d='M106.625 41.5L117.5 7.988a6.002 6.002 0 0 1 11.308 0L139.683 41.5' fillOpacity={0} className='logo' - stroke={props.color} + stroke={color} clipPath='url(#a)' strokeWidth={8} /> </Svg> ) -NasaBase.defaultProps = { - color: 'black', - ratio: 0.8 -} - export const Nasa = styled(NasaBase)` ${style}; ${theme({ _hover: { '.logo': { stroke: '#f00' } } })}; ` -const TEDBase = ({ ratio, ...props }) => ( +const TEDBase = ({ ratio = 0.8, ...props }) => ( <Svg height={76 * ratio} viewBox='0 0 324 119' {...props}> <path className='logo' @@ -637,16 +539,12 @@ const TEDBase = ({ ratio, ...props }) => ( </Svg> ) -TEDBase.defaultProps = { - ratio: 0.8 -} - export const TED = styled(TEDBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#e62b1e' } } })}; ` -const BuzzFeedBase = ({ ratio, ...props }) => ( +const BuzzFeedBase = ({ ratio = 0.8, ...props }) => ( <Svg height={36.5 * ratio} viewBox='0 0 853.3 150.1' {...props}> <path className='logo' @@ -655,16 +553,12 @@ const BuzzFeedBase = ({ ratio, ...props }) => ( </Svg> ) -BuzzFeedBase.defaultProps = { - ratio: 0.8 -} - export const BuzzFeed = styled(BuzzFeedBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#ee3322' } } })}; ` -const FoxBase = ({ ratio, ...props }) => ( +const FoxBase = ({ ratio = 0.8, ...props }) => ( <Svg version={1} height={89.4 * ratio} @@ -682,16 +576,12 @@ const FoxBase = ({ ratio, ...props }) => ( </Svg> ) -FoxBase.defaultProps = { - ratio: 0.8 -} - export const Fox = styled(FoxBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#002885' } } })}; ` -const TechCrunchBase = ({ ratio, ...props }) => ( +const TechCrunchBase = ({ ratio = 0.8, ...props }) => ( <Svg height={141.5 * ratio} viewBox='-3.5 -2.607 290 198.312' {...props}> <path className='logo' @@ -704,10 +594,6 @@ const TechCrunchBase = ({ ratio, ...props }) => ( </Svg> ) -TechCrunchBase.defaultProps = { - ratio: 0.8 -} - export const TechCrunch = styled(TechCrunchBase)` ${style}; ${theme({ @@ -718,17 +604,13 @@ export const TechCrunch = styled(TechCrunchBase)` })}; ` -export const Vice = ({ ratio, ...props }) => ( +export const Vice = ({ ratio = 0.8, ...props }) => ( <Svg height={66.2 * ratio} viewBox='0 0 500 160' {...props}> <path d='M155.235 159.85c-18.337-1.673-30.49-10.364-32.969-23.574-.519-2.767-.418-9.372.18-11.867.16-.663.246-1.205.193-1.205-.053 0-2.852 2.035-6.219 4.522-13.029 9.624-23.75 16.386-34.614 21.833-12.534 6.283-19.827 8.146-31.974 8.165-8.242.013-13.304-.936-18.678-3.502-8.305-3.965-12.188-9.959-12.188-18.815 0-4.326.396-6.14 2.051-9.398.787-1.55 1.432-2.972 1.432-3.16 0-.19-1.155-2.442-2.565-5.007-5.027-9.137-11.2-22.857-16.02-35.61-11.07-29.29 1.976-54.82 34.888-68.27 2.264-.924 7.89-3.528 12.505-5.785C60.755 3.531 61.628 3.15 65.872 1.78c8.364-2.7 16.009-1.842 22.213 2.49 3.365 2.351 6.696 7.47 7.49 11.51.2 1.025.462 2.243.58 2.708l.214.845 2.532-.769c10.153-3.08 21.819-5.703 30.708-6.905 6.32-.854 20.268-1.046 25.388-.348l2.912.397 2.295-1.507c12.215-8.021 32.702-8.26 62.443-.728 9.438 2.39 14.669 3.994 19.79 6.068 9.72 3.937 10.134 3.917 18.345-.881 7.983-4.665 21.67-9.88 32.626-12.432C300.728.523 305.375.013 313.696 0c9.341-.014 12.943.468 19.282 2.58 6.23 2.075 7.85 2.27 13.033 1.577 5.613-.751 22.306-1.024 31.95-.522 23.277 1.212 39.529 3.629 81.201 12.077 18.393 3.73 33.042 6.525 39.097 7.463l1.741.27-.034 1.17c-.018.643-.303 1.527-.633 1.964-2.743 3.64-15.127 19.105-18.124 22.634-5.032 5.923-11.679 12.618-16.272 16.39l-3.763 3.09.215 3.396c.245 3.851-.209 8.53-1.081 11.154l-.571 1.717 2.656 3.456c2.879 3.745 5.323 7.648 6.403 10.226l.682 1.628-.638 2.87c-4.284 19.272-13.944 31.96-29.864 39.222-12.236 5.582-45.952 13.294-69.246 15.839-12.758 1.394-30.024 1.703-38.305.685-13.448-1.652-22.967-4.709-30.324-9.738l-2.622-1.793-2.601 1.403c-8.043 4.338-19.605 7.713-32.517 9.492-6.22.857-21.23 1.21-27.58.65-14.976-1.324-27.89-5.212-36.421-10.963-1.04-.701-1.97-1.275-2.067-1.275-.098 0-1.122.904-2.276 2.008-5.702 5.455-14.407 9.206-24.765 10.672-4.237.6-11.365.84-15.017.507zm13.312-18.02c6.444-.744 11.153-2.442 13.226-4.771 1.585-1.781 2.593-3.653 4.66-8.647 1.001-2.423 3.394-7.63 5.316-11.574l3.494-7.169.208 2.189c1.177 12.415 8.123 20.06 22.68 24.964 15.528 5.232 28.754 6.178 44.914 3.212 13.782-2.529 29.298-8.475 43.606-16.71 1.957-1.126 3.602-2.048 3.655-2.048.052 0 .037 1.785-.035 3.967-.307 9.359 2.376 11.784 16.025 14.485 12.772 2.528 27.636 2.799 43.276.788 13.91-1.79 45.995-9.003 56.983-12.813 13.99-4.85 20.57-11.245 23.475-22.816l.766-3.052-.676-.56c-1.04-.86-4.284-1.756-7.262-2.004-5.984-.5-13.795.84-28.966 4.965-14.836 4.034-21.783 5.306-31.024 5.681-9.885.402-21.375-1.676-22.651-4.096-.746-1.414-.078-3.49 1.504-4.671 5.22-3.9 13.382-5.188 36.342-5.737 23.57-.565 31.638-2.216 38.604-7.905 5.052-4.125 8-9.96 7.33-14.501-.852-5.768-8.77-9.329-19.637-8.833-5.233.239-8.95.938-19.807 3.726-4.788 1.23-10.273 2.471-12.188 2.76-5.07.761-14.975.677-16.276-.14-.283-.177-.22-.518.247-1.332.345-.602 1.15-2.384 1.788-3.96 1.232-3.04 2.264-4.895 3.126-5.621.729-.614 11.697-.296 22.195.643 9.312.833 21.807 1.002 26.276.355 13.922-2.017 24.214-7.547 33.548-18.028 1.315-1.476 2.959-3.244 3.653-3.928.79-.779 1.262-1.535 1.262-2.025 0-.844-.253-.975-2.532-1.31-3.283-.481-14.244-2.541-25.643-4.818-27.172-5.429-39.605-7.455-55.558-9.056-7.924-.796-30.679-.82-36.61-.04-5.635.742-6.213 1.064-13.398 7.455-.972.864-1.85 1.489-1.95 1.387-.1-.101.25-1.604.777-3.34.527-1.734 1.055-3.694 1.174-4.354.257-1.436.248-1.441-5.19-2.85-17.79-4.607-36.75-1.094-61.302 11.36-22.367 11.346-38.284 22.086-52.712 35.569l-2.9 2.71 2.277-3.835c5.43-9.142 9.724-15.231 17.813-25.263 5.744-7.123 6.091-7.612 5.549-7.807-3.381-1.215-27.06-6.956-36.35-8.813-8.548-1.71-15.266-2.348-20.43-1.941-6.27.493-9.78 1.923-13.69 5.579-4.074 3.807-4.962 4.026-10.538 2.59-8.775-2.257-20.387-1.879-35.751 1.165-21.849 4.327-29.628 8.436-30.305 16.004-.115 1.296.127 3.272.853 6.945 1.742 8.816 1.171 10.712-7.253 24.084-3.752 5.954-5.763 8.57-8.04 10.453-1.973 1.633-3.986 2.722-4.349 2.354-.75-.762-1.307-8.398-1.143-15.689.22-9.764 2.068-21.392 6.08-38.24 1.467-6.162 1.821-12.113.956-16.06l-.548-2.503-2.74.176c-4.127.265-6.255 1.102-14.927 5.87-2.35 1.292-7.194 3.531-10.763 4.976-14.354 5.809-21.098 9.901-25.554 15.504-4.301 5.409-6.036 11.172-5.704 18.946.209 4.906.8 7.023 4.87 17.436 6.564 16.795 10.8 25.279 18.662 37.366 1.986 3.053 3.61 5.69 3.61 5.86 0 .17-1.682 2.01-3.74 4.088-2.908 2.94-3.822 4.074-4.115 5.103-.583 2.053-.47 2.568.795 3.627 2.083 1.743 4.403 2.338 9.818 2.519 11.573.386 20.809-2.707 37.988-12.721 18.784-10.95 29.262-20.498 51.714-47.127 3.577-4.242 7.766-9.303 9.31-11.247 3.556-4.48 4.751-5.776 6.394-6.936l1.32-.932.375 1.685c.206.926.445 3.781.531 6.344.27 8.067-.837 12.592-6.191 25.285-7.756 18.389-11.04 32.258-9.28 39.196 1.171 4.623 6.611 7.319 17.307 8.577 2.154.254 8.738.18 11.396-.126zm85.475-30.185c-6.555-1.478-10.085-5.144-10.067-10.453.01-2.852.443-4.432 2.195-8.021 3.395-6.953 8.282-13.023 18.861-23.427 3.88-3.817 8.26-8.312 9.732-9.988 1.471-1.676 2.729-2.993 2.795-2.927.212.216-1.73 7.189-4.483 16.102-2.384 7.718-4.627 15.613-4.628 16.29-.001.695 10.328.017 25.8-1.693 6.268-.692 12.791-1.358 14.496-1.478 2.858-.202 3.144-.284 3.683-1.054.765-1.093 2.04-4.198 2.72-6.62.297-1.06.642-2.04.767-2.177.317-.35 1.723 2.389 2.604 5.07.954 2.902 1.066 9.515.196 11.488-.516 1.167-.583 1.205-2.17 1.205-6.3 0-14.555 2.428-24.828 7.303-18.697 8.871-22.96 10.29-31.658 10.533-2.612.073-5.318.004-6.015-.153zm70.91-59.693c.125-.313.93-2.593 1.79-5.067.86-2.475 1.792-5.12 2.073-5.88l.51-1.38.981.945c1.514 1.46 3.86 2.497 9.185 4.063 4.488 1.32 8.415 2.8 8.415 3.171 0 .266-3.133.851-9.804 1.832-6.25.92-10.572 1.798-12.471 2.533-.81.314-.883.29-.68-.217z' /> </Svg> ) -Vice.defaultProps = { - ratio: 0.8 -} - -const ChangeBase = ({ ratio, ...props }) => ( +const ChangeBase = ({ ratio = 0.8, ...props }) => ( <Svg height={40.5 * ratio} viewBox='0 0 300 58.828' {...props}> <path d='M86.265 31.286h-5.882c-2.81 0-4.553 1.756-4.553 3.826 0 2.115 1.561 3.358 4.31 3.358 3.006 0 5.002-1.413 6.125-2.577v-4.607zm0 12.88c-3.045 1.563-4.985 2.579-8.53 2.579-6.794 0-11.202-4.765-11.202-11.014 0-7.024 5.817-11.269 12.545-11.269h7.187v-1.16c0-3.342-2.287-5.08-4.951-5.08-3.54 0-7.42 1.292-9.253 1.99a1.094 1.094 0 0 1-.864-.037 1.094 1.094 0 0 1-.564-.655l-1.736-5.555a1.09 1.09 0 0 1 .622-1.33c1.97-.816 6.764-2.616 10.755-2.616 10.235 0 15.21 4.172 15.21 13.936v21.338a1.09 1.09 0 0 1-1.09 1.089H87.78c-.471 0-.888-.302-1.037-.752l-.478-1.464zm23.059 2.216c.6 0 1.088-.488 1.088-1.09V21.016c2.036-1.451 4.163-2.43 6.424-2.43 2.47 0 3.738 1.871 3.738 5.297v21.41c0 .602.488 1.09 1.09 1.09h7.043a1.09 1.09 0 0 0 1.09-1.09V22.577c0-7.61-4.031-12.557-10.964-12.557-2.952 0-5.636.804-8.421 2.576l-.423-1.432a1.091 1.091 0 0 0-1.045-.781h-6.664c-.601 0-1.086.487-1.086 1.088v33.823c0 .601.485 1.089 1.086 1.089h7.044zm90.736-4.778c0-2.71 2.192-4.964 5.03-4.964 2.903 0 5.096 2.255 5.096 4.964 0 2.835-1.934 5.286-5.03 5.286-2.904 0-5.095-2.386-5.095-5.286m33.62-8.433a5.08 5.08 0 0 1-5.082 5.08 5.08 5.08 0 0 1-5.082-5.08v-9.507a5.08 5.08 0 0 1 5.082-5.079 5.08 5.08 0 0 1 5.082 5.08v9.506zM228.59 10.02c-7.985 0-14.29 4.5-14.29 13.21v10.306c0 8.71 6.326 13.21 14.31 13.21 7.986 0 14.293-4.5 14.293-13.21V23.228c0-8.71-6.326-13.21-14.313-13.21m-50.3 15.263v-1.617a5.079 5.079 0 0 1 5.081-5.08 5.08 5.08 0 0 1 5.083 5.08v1.617H178.29zm5.072-15.262c-7.988 0-14.293 4.499-14.293 13.21v10.306c0 8.71 6.328 13.21 14.314 13.21 3.65 0 8.345-.57 10.355-.84.557-.076.966-.56.943-1.124l-.246-6.088a1.108 1.108 0 0 0-.38-.785 1.108 1.108 0 0 0-.828-.255c-1.922.212-5.945.599-9.856.599a5.078 5.078 0 0 1-5.08-5.08v-.705h18.294c.601 0 1.087-.488 1.087-1.091v-8.148c0-8.71-6.324-13.21-14.31-13.21M148.09 36.729c-2.471 0-3.74-1.872-3.74-5.3v-7.547c0-3.426 1.269-5.297 3.74-5.297 2.26 0 4.39.979 6.423 2.43v13.283c-2.034 1.454-4.162 2.43-6.423 2.43m7.868-26.346a1.09 1.09 0 0 0-1.037.748l-.48 1.466c-2.784-1.773-5.396-2.577-8.348-2.577-6.933 0-10.962 4.946-10.962 12.557v10.16c0 7.612 4.03 12.556 10.962 12.556 2.952 0 5.637-.803 8.42-2.576v2.539a5.082 5.082 0 0 1-5.082 5.081c-3.908 0-7.932-.386-9.853-.6a1.094 1.094 0 0 0-1.21 1.04l-.244 6.089a1.088 1.088 0 0 0 .944 1.122c2.007.269 6.701.841 10.353.841 7.987 0 14.313-4.499 14.313-13.21V11.47c0-.602-.488-1.088-1.088-1.088h-6.688zm128.394 26.347c-2.467 0-3.736-1.872-3.736-5.3v-7.547c0-3.426 1.27-5.297 3.736-5.297 2.266 0 4.393.979 6.428 2.43v13.283c-2.035 1.454-4.162 2.43-6.428 2.43m7.871-26.346c-.47 0-.89.302-1.035.748l-.481 1.466c-2.786-1.773-5.396-2.577-8.349-2.577-6.934 0-10.961 4.946-10.961 12.557v10.16c0 7.612 4.027 12.556 10.961 12.556 2.953 0 5.634-.803 8.422-2.576v2.539a5.083 5.083 0 0 1-5.083 5.081c-3.909 0-7.932-.386-9.852-.6a1.094 1.094 0 0 0-1.211 1.039l-.247 6.09a1.089 1.089 0 0 0 .946 1.122c2.007.269 6.704.841 10.354.841 7.986 0 14.313-4.499 14.313-13.21V11.47a1.09 1.09 0 0 0-1.088-1.088h-6.689zm-24.027.795a1.09 1.09 0 0 0-1.126-1.139c-3.77.136-5.909.988-9.541 3.465L257 11.225a1.09 1.09 0 0 0-1.063-.843h-6.612c-.602 0-1.087.487-1.087 1.088v33.823c0 .601.485 1.089 1.087 1.089h7.044c.6 0 1.088-.488 1.088-1.09V22.106c3.006-2.121 5.34-3.179 9.389-3.323a1.085 1.085 0 0 0 1.048-1.036l.302-6.57zM50.961 10.019c-2.95 0-5.637.804-8.422 2.577V1.09A1.09 1.09 0 0 0 41.45 0h-7.04a1.09 1.09 0 0 0-1.089 1.09v44.203a1.09 1.09 0 0 0 1.09 1.089h7.04c.601 0 1.088-.488 1.088-1.09V21.016c2.036-1.451 4.163-2.43 6.425-2.43 2.47 0 3.74 1.871 3.74 5.297v21.41c0 .602.488 1.09 1.09 1.09h7.04a1.09 1.09 0 0 0 1.09-1.09V22.577c0-7.61-4.028-12.557-10.963-12.557M28.597 33.834a.911.911 0 0 0-.262-.564c-.188-.192-.45-.3-.725-.3h-7.26c-.485 0-.898.33-.981.782-.026.14-.093.453-.097.473A5.08 5.08 0 0 1 9.22 33.171v-9.507a5.08 5.08 0 0 1 9.852-1.738c.1.327.183.667.255 1.019.018.087.038.173.054.261.051.282.24.505.486.64.148.082.312.14.494.14h7.25c.183 0 .359-.05.513-.14a.908.908 0 0 0 .476-.805l-.002-.095c-.137-8.524-6.408-12.927-14.306-12.927l-.056.002C6.275 10.04 0 14.538 0 23.228v10.307c0 8.71 6.326 13.21 14.31 13.21 2.766 0 5.323-.55 7.493-1.617 1.406-.692 2.653-1.598 3.677-2.729 1.802-1.99 2.931-4.659 3.1-7.985.005-.068.021-.534.017-.58' @@ -737,16 +619,12 @@ const ChangeBase = ({ ratio, ...props }) => ( </Svg> ) -ChangeBase.defaultProps = { - ratio: 0.8 -} - export const Change = styled(ChangeBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#ec2c22' } } })}; ` -const NetflixBase = ({ ratio, ...props }) => ( +const NetflixBase = ({ ratio = 0.8, ...props }) => ( <Svg height={56.2 * ratio} viewBox='0 0 300 81.387' {...props}> <path className='logo' @@ -755,16 +633,12 @@ const NetflixBase = ({ ratio, ...props }) => ( </Svg> ) -NetflixBase.defaultProps = { - ratio: 0.8 -} - export const Netflix = styled(NetflixBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#b81d24' } } })}; ` -const LifeHackerBase = ({ ratio, ...props }) => ( +const LifeHackerBase = ({ ratio = 0.8, ...props }) => ( <Svg height={51.5 * ratio} viewBox='0 0 795.187 197.987' {...props}> <path d='M30.498 195.773H0V1.963l30.498 1.966v191.844m49.927 0H49.927V57.548l30.498 1.721zM65.175 15.49c9.593 0 17.463 7.871 17.463 17.463 0 9.593-7.87 17.464-17.463 17.464-9.592 0-17.462-7.87-17.462-17.464 0-9.592 7.87-17.463 17.462-17.463m88.05 69.85v30.498h-22.873v79.802H99.854V44.02c0-23.119 19.183-44.025 41.811-44.025 7.624 0 13.774 2.214 15.25 3.197l-1.231 29.268h-14.019c-6.149 0-11.313 5.165-11.313 11.56v41.32h22.873m42.835 26.562h22.873V97.638c0-6.396-5.165-11.56-11.314-11.56a11.545 11.545 0 0 0-11.559 11.56zm-30.499-14.264c0-23.12 18.692-42.058 42.058-42.058 23.12 0 41.812 18.937 41.812 42.058v29.515c0 8.607-6.887 15.247-15.248 15.247H196.06v13.283c0 6.393 5.164 11.56 11.559 11.56h29.269l.984 25.825-27.547 4.18c-26.564 4.428-44.764-18.447-44.764-41.565V97.638m109.949 98.135V3.192h19.678v58.536c5.41-1.721 14.019-2.459 19.921-2.459 20.907 0 37.139 18.938 37.139 40.337v96.167h-19.184V99.606c0-10.577-8.608-18.94-19.184-18.94h-18.692v115.107h-19.677m148.721-37.138V125.43h-18.939c-10.574 0-18.937 8.363-18.937 18.938v14.267c0 10.574 8.363 19.182 18.937 19.182 10.578 0 18.939-8.608 18.939-19.182zm0-62.227c0-11.068-5.165-19.923-19.184-18.446h.245c-7.87.245-17.953 1.23-26.316 1.721-.245-7.133-.492-9.838-.737-15.248 6.64-2.46 16.232-4.92 24.35-5.166 24.594-.492 40.827 19.43 40.827 40.828v58.538c0 21.15-16.97 38.613-38.124 38.613-21.15 0-38.613-17.463-38.613-38.613v-12.052c0-21.153 14.51-37.139 38.613-37.139 9.102 0 13.774.984 18.939 2.458V96.408m74.287-37.138c21.153 0 38.614 17.215 38.614 38.614v2.46c-7.624.246-13.773.246-19.429.491v-2.951c0-10.33-8.61-18.938-19.185-18.938-10.33 0-18.694 8.608-18.694 18.938v61.488c0 10.821 8.364 18.939 18.694 18.939 10.33 0 18.938-7.871 19.185-18.202 9.59.74 18.692 1.23 19.43 1.23-.985 20.414-18.2 36.648-38.615 36.648-21.151 0-38.37-17.218-38.37-38.615V97.884c0-21.399 17.219-38.615 38.37-38.615m116.136 136.504l-37.384-65.178c-3.691-6.394-3.691-7.132.737-14.757l32.957-54.6h22.383l-37.14 62.963 40.09 71.572zM572.35 3.684v192.09h-19.676V3.683h19.676m87.769 115.107h37.877V98.128c0-10.575-8.61-19.183-18.939-19.183-10.576 0-18.938 8.608-18.938 19.183zm-19.676-20.661c0-21.397 17.217-38.86 38.614-38.86 21.151 0 38.37 17.463 38.37 38.86v30.253c0 5.658-4.428 9.838-9.839 9.838h-47.47v20.905c0 10.576 8.363 19.186 18.94 19.186h24.84c.246 6.393.493 10.823.985 15.248l-23.612 3.69c-24.103 4.18-40.828-16.725-40.828-38.124V98.13m113.918 97.643h-19.677V99.851c0-21.398 16.725-41.319 41.32-40.828 8.363.246 13.528 2.214 19.185 4.92-.246 5.902-.492 10.821-.737 15.248l-21.399-.491c-10.33 0-18.692 11.068-18.692 21.151v95.922' @@ -773,16 +647,12 @@ const LifeHackerBase = ({ ratio, ...props }) => ( </Svg> ) -LifeHackerBase.defaultProps = { - ratio: 0.8 -} - export const LifeHacker = styled(LifeHackerBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#87b827' } } })}; ` -const TwitchBase = ({ ratio, ...props }) => ( +const TwitchBase = ({ ratio = 0.8, ...props }) => ( <Svg viewBox='0 0 999 331.095' height={68.5 * ratio} {...props}> <path className='logo' @@ -792,16 +662,12 @@ const TwitchBase = ({ ratio, ...props }) => ( </Svg> ) -TwitchBase.defaultProps = { - ratio: 0.8 -} - export const Twitch = styled(TwitchBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#6441a5' } } })}; ` -const GfycatBase = ({ ratio, ...props }) => ( +const GfycatBase = ({ ratio = 0.8, ...props }) => ( <Svg height={56.5 * ratio} viewBox='0 0 220 60' {...props}> <path className='logo' @@ -811,16 +677,12 @@ const GfycatBase = ({ ratio, ...props }) => ( </Svg> ) -GfycatBase.defaultProps = { - ratio: 0.8 -} - export const Gfycat = styled(GfycatBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#3073ff' } } })}; ` -const StackOverflowBase = ({ ratio, ...props }) => ( +const StackOverflowBase = ({ ratio = 0.8, ...props }) => ( <Svg height={50.9 * ratio} viewBox='0 0 480.5 117.9' {...props}> <path className='logo' @@ -834,10 +696,6 @@ const StackOverflowBase = ({ ratio, ...props }) => ( </Svg> ) -StackOverflowBase.defaultProps = { - ratio: 0.8 -} - export const StackOverflow = styled(StackOverflowBase)` ${style}; ${theme({ @@ -849,7 +707,7 @@ export const StackOverflow = styled(StackOverflowBase)` })}; ` -export const MDN = ({ ratio, ...props }) => ( +export const MDN = ({ ratio = 0.8, ...props }) => ( <Svg height={45.3 * ratio} viewBox='0 0 218.836 47.956' @@ -860,23 +718,15 @@ export const MDN = ({ ratio, ...props }) => ( </Svg> ) -MDN.defaultProps = { - ratio: 0.8 -} - -export const Engadget = ({ ratio, ...props }) => ( +export const Engadget = ({ ratio = 0.8, ...props }) => ( <Svg height={45.1 * ratio} viewBox='0 0 1534.667 334.667' {...props}> <path d='M0 243.492c0 16.15 13.126 29.276 30.286 29.276h121.135v-30.287H30.286V212.2h119.115c16.151 0 32.302-13.125 32.302-29.276v1.01-59.562c0-16.15-15.14-32.303-32.302-32.303H30.286C14.131 92.07 0 108.221 0 124.372zm151.421-61.579H30.286v-60.568h121.135zm404.792-90.849H436.088c-16.15 0-32.301 16.152-32.301 32.303v120.125-1.01c0 16.15 16.15 30.286 32.301 30.286h119.115v30.281H434.068v30.287h122.145c16.151 0 29.276-14.136 29.276-30.287V123.367c0-16.151-13.125-32.303-29.276-32.303zm-1.01 151.417H434.068V121.345h121.135zM323.027 91.064h-89.839c-16.152 0-31.297 16.152-31.297 32.303v149.401h30.286V121.345h90.85c16.15 0 30.285 15.142 30.285 32.303v119.12h30.281v-119.12c0-33.312-27.254-62.584-60.566-62.584zm434.072 151.417H635.964v-89.844c0-16.15 16.15-32.301 33.312-32.301h87.823v151.421h30.281v-148.39c0-16.151-12.115-32.303-28.265-32.303h-89.839c-33.312 0-63.599 29.272-63.599 62.584v89.844c0 16.15 17.162 29.276 33.312 29.276h52.495c27.256 0 55.521-11.104 65.615-30.287v30.287M1443.533.211h-30.28v272.557h30.28V121.345h90.854V91.064h-90.854m-423.976 152.428c0 16.15 9.083 29.276 25.24 29.276h116.088v30.281h-111.041v30.287h115.077c16.152 0 26.246-14.136 26.246-31.297v1.01-179.682c0-16.151-10.094-32.303-26.246-32.303h-120.124c-16.157 0-25.24 16.152-25.24 32.303zm141.328-1.01h-111.041V121.344h111.041zM958.99 91.063H841.891c-16.151 0-34.318 16.152-34.318 32.303v120.125-1.01c0 16.15 18.167 30.286 34.318 30.286h147.385V.211h-30.287zm0 151.417H837.855V121.345h121.134zm252.366 1.011c0 16.15 17.161 29.276 33.312 29.276h118.106V242.48H1241.64V212.2h123.16c16.147 0 28.253-13.125 28.253-29.276v1.01-59.562c0-16.15-12.106-32.303-28.253-32.303h-120.133c-16.151 0-33.312 16.152-33.312 32.303zm151.418-61.579H1241.64v-60.568h121.133z' /> </Svg> ) -Engadget.defaultProps = { - ratio: 0.8 -} - -const ArsBase = ({ ratio, ...props }) => ( +const ArsBase = ({ ratio = 0.8, color = 'black', ...props }) => ( <Svg height={68.8 * ratio} viewBox='0 0 437 145' {...props}> - <circle className='logo' cx='72.2' cy='72.2' r='72.2' fill={props.color} /> + <circle className='logo' cx='72.2' cy='72.2' r='72.2' fill={color} /> <path className='logo' d='M46.6 94.2l-.9-5.9a20.8 20.8 0 0 1-15.6 6.8c-8 0-13-4.8-13-12.3 0-11 9.4-15.4 27.9-17.3v-1.9c0-5.6-3.3-7.5-8.4-7.5s-10.5 1.7-15.3 3.8l-1.1-7.1c5.3-2.1 10.3-3.7 17.1-3.7 10.7 0 15.9 4.3 15.9 14.2v30.9h-6.7zM45 71.8c-16.3 1.6-19.7 6-19.7 10.6s2.4 5.9 6.6 5.9 9.4-2.4 13.1-6.2V71.8zm27.4-3.7v26.1h-8.2V50.1h6.6l1.4 9c3.1-5 8.2-9.5 15.5-9.9l1.3 7.9c-7.4.3-13.6 5.2-16.6 11zm37.3 27a36.2 36.2 0 0 1-16.1-4.2l1.2-7.8a27.6 27.6 0 0 0 15.6 5.1c5.6 0 9-2.1 9-5.8s-2.5-5.6-10.5-7.5c-10.4-2.6-14.5-5.7-14.5-13.6s5.9-12.2 15.6-12.2a35.7 35.7 0 0 1 14.5 3l-1.3 7.8a28.2 28.2 0 0 0-13.4-3.8c-5 0-7.6 1.9-7.6 5.1s2.2 4.6 9.2 6.4c10.9 2.8 15.8 5.9 15.8 14.3s-6.1 13.2-17.5 13.2z' @@ -886,11 +736,6 @@ const ArsBase = ({ ratio, ...props }) => ( </Svg> ) -ArsBase.defaultProps = { - ratio: 0.8, - color: 'black' -} - export const Ars = styled(ArsBase)` ${style}; ${theme({ @@ -901,7 +746,7 @@ export const Ars = styled(ArsBase)` })}; ` -const ProductHuntBase = ({ ratio, ...props }) => ( +const ProductHuntBase = ({ ratio = 0.8, ...props }) => ( <Svg height={48.5 * ratio} viewBox='0 0 1025.2 240' {...props}> <path d='M240 120c0 66.3-53.7 120-120 120S0 186.3 0 120 53.7 0 120 0s120 53.7 120 120' @@ -918,16 +763,12 @@ const ProductHuntBase = ({ ratio, ...props }) => ( </Svg> ) -ProductHuntBase.defaultProps = { - ratio: 0.8 -} - export const ProductHunt = styled(ProductHuntBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#da552f' } } })}; ` -const TheVergeBase = ({ ratio, ...props }) => ( +const TheVergeBase = ({ ratio = 0.8, ...props }) => ( <Svg height={35.1 * ratio} viewBox='0 23.628 435 73.729' {...props}> <path className='logo' @@ -936,16 +777,12 @@ const TheVergeBase = ({ ratio, ...props }) => ( </Svg> ) -TheVergeBase.defaultProps = { - ratio: 0.8 -} - export const TheVerge = styled(TheVergeBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#f94a2b' } } })}; ` -const TNWBase = ({ ratio, ...props }) => ( +const TNWBase = ({ ratio = 0.8, ...props }) => ( <Svg height={50.3 * ratio} viewBox='0 0 165 40' {...props}> <path className='logo' @@ -954,10 +791,6 @@ const TNWBase = ({ ratio, ...props }) => ( </Svg> ) -TNWBase.defaultProps = { - ratio: 0.8 -} - export const TNW = styled(TNWBase)` ${style}; ${theme({ _hover: { '.logo': { fill: '#f42' } } })}; diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index ba5a8ddaf..c3dacf651 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -65,26 +65,23 @@ export const Code = withContainer(CodeEditor) export const MultiCodeEditor = withContainer(MultiCodeEditorBase) -export const H1 = withTitle( - withSlug(styled(Heading)` - ${theme({ - maxWidth: layout.small, - fontSize: `calc(${fontSizes[5]} * 0.75)`, - lineHeight: [1, 2], - textAlign: 'left', - mt: 5, - mb: 4, - mx: 'auto' - })} - `) -) +const StyledH1 = styled(Heading)` + ${theme({ + maxWidth: layout.small, + fontSize: `calc(${fontSizes[5]} * 0.75)`, + lineHeight: [1, 2], + textAlign: 'left', + mt: 5, + mb: 4, + mx: 'auto' + })} +` -H1.defaultProps = { - as: 'h1', - variant: null -} +const H1Base = props => <StyledH1 forwardedAs='h1' variant={null} {...props} /> + +export const H1 = withTitle(withSlug(H1Base)) -const H2Base = styled(Heading)` +const StyledH2 = styled(Heading)` ${theme({ mx: 'auto', maxWidth: layout.small, @@ -96,89 +93,74 @@ const H2Base = styled(Heading)` })} ` -H2Base.defaultProps = { - as: 'h2', - variant: null -} +const H2Base = props => <StyledH2 forwardedAs='h2' variant={null} {...props} /> export const H2 = withTitle(withSlug(H2Base)) -export const H3 = withTitle( - withSlug(styled(Heading)` - ${theme({ - mx: 'auto', - maxWidth: layout.small, - fontSize: `calc(${fontSizes[4]} * 0.75 * 0.75)`, - lineHeight: 1, - textAlign: 'left', - mt: 5, - mb: 4 - })} - `) -) +const StyledH3 = styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: `calc(${fontSizes[4]} * 0.75 * 0.75)`, + lineHeight: 1, + textAlign: 'left', + mt: 5, + mb: 4 + })} +` -H3.defaultProps = { - as: 'h3', - variant: null -} +const H3Base = props => <StyledH3 forwardedAs='h3' variant={null} {...props} /> -export const H4 = withTitle( - withSlug(styled(Heading)` - ${theme({ - mx: 'auto', - maxWidth: layout.small, - fontSize: 2, - lineHeight: 1, - textAlign: 'left', - mt: 4, - mb: 3 - })} - `) -) +export const H3 = withTitle(withSlug(H3Base)) -H4.defaultProps = { - as: 'h4', - variant: null -} +const StyledH4 = styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 2, + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} +` -export const H5 = withTitle( - withSlug(styled(Heading)` - ${theme({ - mx: 'auto', - maxWidth: layout.small, - fontSize: 1, - lineHeight: 1, - textAlign: 'left', - mt: 4, - mb: 3 - })} - `) -) +const H4Base = props => <StyledH4 forwardedAs='h4' variant={null} {...props} /> -H5.defaultProps = { - as: 'h5', - variant: null -} +export const H4 = withTitle(withSlug(H4Base)) -export const H6 = withTitle( - withSlug(styled(Heading)` - ${theme({ - mx: 'auto', - maxWidth: layout.small, - fontSize: 1, - color: 'gray9', - lineHeight: 1, - textAlign: 'left', - mt: 4, - mb: 3 - })} - `) -) +const StyledH5 = styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 1, + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} +` -H6.defaultProps = { - as: 'h6', - variant: null -} +const H5Base = props => <StyledH5 forwardedAs='h5' variant={null} {...props} /> + +export const H5 = withTitle(withSlug(H5Base)) + +const StyledH6 = styled(Heading)` + ${theme({ + mx: 'auto', + maxWidth: layout.small, + fontSize: 1, + color: 'gray9', + lineHeight: 1, + textAlign: 'left', + mt: 4, + mb: 3 + })} +` + +const H6Base = props => <StyledH6 forwardedAs='h6' variant={null} {...props} /> + +export const H6 = withTitle(withSlug(H6Base)) export const Paraph = props => { const isMedia = get(props, 'children.props.name') === 'img' @@ -192,16 +174,14 @@ export const Paraph = props => { ) } -export const Strong = styled(Text)` +const StyledStrong = styled(Text)` display: inline; font-weight: bold; ` -Strong.defaultProps = { - as: 'b' -} +export const Strong = props => <StyledStrong as='b' {...props} /> -export const Ul = styled(Text)` +const StyledUl = styled(Text)` max-width: ${layout.small}; ${theme({ @@ -210,17 +190,11 @@ export const Ul = styled(Text)` })} ` -Ul.defaultProps = { - as: 'ul' -} - -export const Ol = styled(Ul)`` +export const Ul = props => <StyledUl as='ul' {...props} /> -Ol.defaultProps = { - as: 'ol' -} +export const Ol = props => <StyledUl as='ol' {...props} /> -export const Li = styled(Text)` +const StyledLi = styled(Text)` max-width: ${layout.small}; ${theme({ @@ -229,9 +203,7 @@ export const Li = styled(Text)` })} ` -Li.defaultProps = { - as: 'li' -} +export const Li = props => <StyledLi as='li' {...props} /> const codeStyle = css` color: ${({ theme }) => theme.colors.pink7}; @@ -241,7 +213,7 @@ const codeStyle = css` text-shadow: rgba(0, 0, 0, 0.05) 0px 1px; ` -export const CodeInline = styled(Text)` +export const StyledCodeInline = styled(Text)` ${codeStyle}; ${wordBreak}; display: inline; @@ -253,9 +225,7 @@ export const CodeInline = styled(Text)` } ` -CodeInline.defaultProps = { - as: 'code' -} +export const CodeInline = props => <StyledCodeInline as='code' {...props} /> const mediaStyle = { borderRadius: '3px', @@ -271,15 +241,13 @@ export const Image = withContainer(_ImageBase, { maxWidth: 'inherit' }) -const _VideoBase = styled(VideoBase)` +const StyledVideoBase = styled(VideoBase)` ${theme(mediaStyle)} - width: 100%, + width: 100%; ` -_VideoBase.defaultProps = { - autoPlay: true -} +const _VideoBase = props => <StyledVideoBase autoPlay {...props} /> export const Video = withContainer(_VideoBase) @@ -309,7 +277,7 @@ export const Blockquote = styled.blockquote` color: ${colors.gray8}; ` -const Type = styled(Text)` +const StyledType = styled(Text)` ${theme({ bg: 'gray1', color: 'gray7', @@ -323,9 +291,7 @@ const Type = styled(Text)` border-radius: 3px; ` -Type.defaultProps = { - as: 'span' -} +const Type = props => <StyledType as='span' {...props} /> const TypeContainer = styled(Box)` ${theme({ diff --git a/src/components/patterns/Aside/AsideBase.js b/src/components/patterns/Aside/AsideBase.js index eb8d4f274..12dd5b4e2 100644 --- a/src/components/patterns/Aside/AsideBase.js +++ b/src/components/patterns/Aside/AsideBase.js @@ -100,7 +100,7 @@ const Aside = ({ activeRouteName = DEFAULT_ACTIVE_ROUTE_NAME, CloseButton, isOpen, - onChange, + onChange = noop, ...props }) => { const [tree, setTree] = useState(activeRouteName) @@ -194,8 +194,4 @@ const Aside = ({ ) } -Aside.defaultProps = { - onChange: noop -} - export default Aside diff --git a/src/components/patterns/Aside/NavLink.js b/src/components/patterns/Aside/NavLink.js index fba85880d..67fbc24aa 100644 --- a/src/components/patterns/Aside/NavLink.js +++ b/src/components/patterns/Aside/NavLink.js @@ -33,10 +33,4 @@ const NavLink = styled(Text)( navlinkStyle ) -NavLink.defaultProps = { - fontSize: 0, - as: 'div', - color: 'gray7' -} - export default withAnalytics(withLink(NavLink)) diff --git a/src/components/patterns/Average/Average.js b/src/components/patterns/Average/Average.js index e4f223fcf..966e18286 100644 --- a/src/components/patterns/Average/Average.js +++ b/src/components/patterns/Average/Average.js @@ -56,7 +56,6 @@ const Average = ({ size, value }) => { display: 'inline', fontWeight: 'bold' })} - titleize={false} > {unit} </Caption> diff --git a/src/components/patterns/Caption/Caption.js b/src/components/patterns/Caption/Caption.js index 04dab0403..97cc967b2 100644 --- a/src/components/patterns/Caption/Caption.js +++ b/src/components/patterns/Caption/Caption.js @@ -1,18 +1,18 @@ -import { Subhead } from 'components/elements' +import { Text } from 'components/elements' +import { commonHeadingStyles } from 'components/elements/Heading' import styled from 'styled-components' import { theme } from 'theme' +import React from 'react' -const Caption = styled(Subhead)( +const StyledCaption = styled(Text)( theme({ + ...commonHeadingStyles, lineHeight: 2, - textAlign: 'center', fontWeight: 'normal', fontSize: [2, 2, 3, 3] }) ) -Caption.defaultProps = { - forwardedAs: 'h3' -} +const Caption = props => <StyledCaption as='h3' {...props} /> export default Caption diff --git a/src/components/patterns/ClusterMonitor/ClusterMonitor.js b/src/components/patterns/ClusterMonitor/ClusterMonitor.js index b13026c59..bda1c7f7f 100644 --- a/src/components/patterns/ClusterMonitor/ClusterMonitor.js +++ b/src/components/patterns/ClusterMonitor/ClusterMonitor.js @@ -12,14 +12,13 @@ const ClusterMonitor = ({ children, endpoint, ...opts }) => { const { data, isLoading } = useSWR( endpoint, () => window.fetch(endpoint).then(res => res.text()), - opts + { + refreshInterval: 3000, + ...opts + } ) return children({ ...parseData(data, isLoading), isLoading }) } -ClusterMonitor.defaultProps = { - refreshInterval: 3000 -} - export default ClusterMonitor diff --git a/src/components/patterns/DemoLinks/DemoLinks.js b/src/components/patterns/DemoLinks/DemoLinks.js index f3d0b4c4e..98190d398 100644 --- a/src/components/patterns/DemoLinks/DemoLinks.js +++ b/src/components/patterns/DemoLinks/DemoLinks.js @@ -14,14 +14,14 @@ import chunk from 'lodash/chunk' const NoWrap = styled(Flex)` white-space: nowrap; overflow: hidden; + justify-content: center; + align-items: center; ` -NoWrap.defaultProps = { - justifyContent: 'center', - alignItems: 'center' -} - const LogoWrap = styled(Box)` + ${theme({ px: 4 })} + + display: 'inline-block'; cursor: pointer; opacity: 0.25; transition: opacity ${transition.medium}; @@ -30,16 +30,11 @@ const LogoWrap = styled(Box)` } ` -LogoWrap.defaultProps = { - display: 'inline-block', - px: 4 -} - const DURATION = 60 const logoIds = Object.keys(LogoBrand) -const DemoLinks = ({ children, chunkSize, onClick }) => { +const DemoLinks = ({ children, chunkSize = 10, onClick }) => { // remove missing logos const links = children.filter(({ id }) => { const hasLogo = logoIds.includes(id) @@ -78,8 +73,4 @@ const DemoLinks = ({ children, chunkSize, onClick }) => { ) } -DemoLinks.defaultProps = { - chunkSize: 10 -} - export default DemoLinks diff --git a/src/components/patterns/DotsBackground/DotsBackground.js b/src/components/patterns/DotsBackground/DotsBackground.js index 4f8dc9923..9fd514594 100644 --- a/src/components/patterns/DotsBackground/DotsBackground.js +++ b/src/components/patterns/DotsBackground/DotsBackground.js @@ -2,6 +2,7 @@ import styled, { css } from 'styled-components' import { slide } from 'components/keyframes' import { Box } from 'components/elements' import is from 'styled-is' +import React from 'react' const darkStyle = css` background: #000; @@ -20,7 +21,7 @@ const animateStyle = css` animation-direction: reverse; ` -const DotsBackground = styled(Box).withConfig({ +const StyledDotsBackground = styled(Box).withConfig({ shouldForwardProp: prop => !['animate'].includes(prop) })` position: relative; @@ -41,9 +42,8 @@ const DotsBackground = styled(Box).withConfig({ } ` -DotsBackground.defaultProps = { - theme: 'light', - animate: true -} +const DotsBackground = props => ( + <StyledDotsBackground theme='light' animate {...props} /> +) export default DotsBackground diff --git a/src/components/patterns/Faq/Faq.js b/src/components/patterns/Faq/Faq.js index 6e320ed46..60bd1e72f 100644 --- a/src/components/patterns/Faq/Faq.js +++ b/src/components/patterns/Faq/Faq.js @@ -1,7 +1,7 @@ import React from 'react' import { Subhead, Text, Box, Container, Flex } from 'components/elements' import { slug as slugger } from 'github-slugger' -import { Caption } from 'components/patterns' +import Caption from '../Caption/Caption' import { withSlug } from 'helpers/hoc' import { layout, theme } from 'theme' @@ -31,7 +31,6 @@ const Faq = ({ title, caption, questions, ...props }) => { pb: [4, 4, 4, 5], maxWidth: layout.normal })} - titleize={false} > {caption} </Caption> diff --git a/src/components/patterns/FetchProvider.js b/src/components/patterns/FetchProvider.js index cdf56be73..6c08c88c4 100644 --- a/src/components/patterns/FetchProvider.js +++ b/src/components/patterns/FetchProvider.js @@ -29,7 +29,12 @@ const fetch = (url, fromCache, opts) => { return fromCache(variations, opts) || mql(url, opts) } -const FetchProvider = ({ fromCache, mqlOpts, children }) => { +const FetchProvider = ({ + fromCache = variations => + demoLinks.find(item => variations.includes(item.data.url)), + mqlOpts, + children +}) => { const [status, setStatus] = useState('initial') const [response, setResponse] = useState({}) const [error, setError] = useState(null) @@ -89,9 +94,4 @@ const FetchProvider = ({ fromCache, mqlOpts, children }) => { ) } -FetchProvider.defaultProps = { - fromCache: variations => - demoLinks.find(item => variations.includes(item.data.url)) -} - export default FetchProvider diff --git a/src/components/patterns/PricingTable/PricingTable.js b/src/components/patterns/PricingTable/PricingTable.js index 598d747b0..8d84e4fd6 100644 --- a/src/components/patterns/PricingTable/PricingTable.js +++ b/src/components/patterns/PricingTable/PricingTable.js @@ -1,5 +1,6 @@ import PricePicker, { DEFAULT_PLAN } from 'components/elements/PricePicker' -import { Caption, ArrowLink, Checkout } from 'components/patterns' +import { ArrowLink, Checkout } from 'components/patterns' +import Caption from '../Caption/Caption' import FeatherIcon from 'components/icons/Feather' import { breakpoints, colors, theme } from 'theme' import React, { useState } from 'react' diff --git a/src/components/patterns/Toolbar/ToolbarDesktop.js b/src/components/patterns/Toolbar/ToolbarDesktop.js index 7d9a2c9d5..55e2ab4ca 100644 --- a/src/components/patterns/Toolbar/ToolbarDesktop.js +++ b/src/components/patterns/Toolbar/ToolbarDesktop.js @@ -48,7 +48,7 @@ const iconDark = css` ` const ToolbarSecondary = ({ isDark, children }) => ( - <Toolbar type='secondary' aria-label='Secondary Navigation'> + <Toolbar as='nav' type='secondary' aria-label='Secondary Navigation'> <Flex css={theme({ alignItems: 'center', @@ -103,6 +103,7 @@ const ToolbarDesktop = ({ isDark }) => { > <Box css={theme({ px: 3 })}> <Toolbar + forwardedAs='nav' aria-label='Primary Navigation' css={theme({ justifyContent: 'space-between', diff --git a/src/components/patterns/Toolbar/ToolbarMobile.js b/src/components/patterns/Toolbar/ToolbarMobile.js index b3086aa21..04881a9ff 100644 --- a/src/components/patterns/Toolbar/ToolbarMobile.js +++ b/src/components/patterns/Toolbar/ToolbarMobile.js @@ -41,9 +41,9 @@ const ToolbarMobile = ({ isDark }) => { })} > <Box> - <Toolbar> + <Toolbar as='nav'> <NavMicrolinkLogo isMobile /> - <Nav> + <Nav as='ul'> <NavDocs isDark={isDark} /> <NavInsights isDark={isDark} /> <NavLogo isDark={isDark} isMobile /> diff --git a/src/components/patterns/index.js b/src/components/patterns/index.js index 280efc2d2..842d9970c 100644 --- a/src/components/patterns/index.js +++ b/src/components/patterns/index.js @@ -1,7 +1,9 @@ +import { withTitle } from 'helpers/hoc' + import Announcement from './Announcement/Announcement' import Aside from './Aside/Aside' import Block from './Block/Block' -import Caption from './Caption/Caption' +import CaptionBase from './Caption/Caption' import Chat from './Chat/Chat' import Checkout from './Checkout' import CubeBackground from './CubeBackground/CubeBackground' @@ -24,6 +26,8 @@ import Toolbar from './Toolbar/Toolbar' import ArrowLink from './ArrowLink' import Features from './Features/Features' +const Caption = withTitle(CaptionBase) + export { Announcement, ArrowLink, diff --git a/src/pages/meta.js b/src/pages/meta.js index 50953c043..a16535064 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -1,10 +1,9 @@ -import { layout, breakpoints, transition, colors, borders, theme } from 'theme' +import { layout, breakpoints, colors, borders, theme } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' import { cdnUrl, trimMs } from 'helpers' import prependHttp from 'prepend-http' -import styled from 'styled-components' import chunk from 'lodash/chunk' import { @@ -95,19 +94,6 @@ const [JsonKeysFirstChunk, JsonKeysSecondChunk] = chunk( const COLOR = '#3e55ff' -const LogoWrap = styled(Box)` - cursor: pointer; - opacity: 0.5; - transition: opacity ${transition.medium}; - &:hover { - opacity: 1; - } -` - -LogoWrap.defaultProps = { - display: 'inline-block' -} - const JSONProperty = ({ property, data, ...props }) => { const children = data[property] const type = children !== null ? 'yes' : 'no' diff --git a/src/pages/sdk.js b/src/pages/sdk.js index cb10a254e..7dcebe687 100644 --- a/src/pages/sdk.js +++ b/src/pages/sdk.js @@ -1,5 +1,5 @@ import { useQueryState, useWindowSize } from 'components/hook' -import { layout, breakpoints, transition, theme, toPx } from 'theme' +import { layout, breakpoints, theme, toPx } from 'theme' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { cdnUrl, mqlCode } from 'helpers' @@ -85,19 +85,6 @@ const LinkPreview = styled(Microlink)` --microlink-hover-background-color: white; ` -const LogoWrap = styled(Box)` - cursor: pointer; - opacity: 0.5; - transition: opacity ${transition.medium}; - &:hover { - opacity: 1; - } -` - -LogoWrap.defaultProps = { - display: 'inline-block' -} - const LiveDemo = React.memo(function LiveDemo ({ data, isInitialData, From f488695ecadcd09ce2a0f701b29a455d93070bfb Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 31 May 2024 21:08:08 +0200 Subject: [PATCH 23/57] fix: passing theme property --- src/components/elements/Label.js | 2 +- src/components/elements/PriceMonthly.js | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/elements/Label.js b/src/components/elements/Label.js index 61c986439..6d3e9270a 100644 --- a/src/components/elements/Label.js +++ b/src/components/elements/Label.js @@ -5,7 +5,7 @@ import React from 'react' import Text from './Text' -const getColor = ({ theme }) => +export const getColor = ({ theme }) => theme === 'dark' ? colors.white60 : colors.black60 export const labelStyle = css` diff --git a/src/components/elements/PriceMonthly.js b/src/components/elements/PriceMonthly.js index 46883d32c..59f1a10fd 100644 --- a/src/components/elements/PriceMonthly.js +++ b/src/components/elements/PriceMonthly.js @@ -3,7 +3,7 @@ import styled from 'styled-components' import React from 'react' import { theme } from 'theme' -import Label, { labelStyle } from './Label' +import Label, { labelStyle, getColor } from './Label' const Price = styled(Label)` font-weight: bold; @@ -17,16 +17,18 @@ const Price = styled(Label)` top: -5px; left: 0; } + + &::after { + color: ${props => getColor(props)}; + } ` -const PriceMonthly = props => { - return ( - <Price - aria-label={`${childrenText(props.children)} euros per month`} - suffix='/month' - {...props} - /> - ) -} +const PriceMonthly = props => ( + <Price + aria-label={`${childrenText(props.children)} euros per month`} + suffix='/month' + {...props} + /> +) export default PriceMonthly From b7830375cace6ae12d5c897f138b469b12b9bc1e Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 31 May 2024 21:10:36 +0200 Subject: [PATCH 24/57] refactor(/formats): add DotsBackground --- src/pages/formats.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/pages/formats.js b/src/pages/formats.js index e0acdeed2..f5a173d93 100644 --- a/src/pages/formats.js +++ b/src/pages/formats.js @@ -1,6 +1,6 @@ -import { Faq, Caption, Layout } from 'components/patterns' -import { XCircle, CheckCircle } from 'react-feather' +import { DotsBackground, Faq, Caption, Layout } from 'components/patterns' import { cx, colors, borders, layout, theme } from 'theme' +import { XCircle, CheckCircle } from 'react-feather' import React, { createElement } from 'react' import { issueUrl } from 'helpers' @@ -144,8 +144,8 @@ const FAQs = props => ( /> ) -const FormatsPage = () => { - return ( +const FormatsPage = () => ( + <DotsBackground> <Layout> <Container css={theme({ @@ -240,7 +240,8 @@ const FormatsPage = () => { <Box css={theme({ p: [4, 4, 0, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') + } > <Caps>Request a format</Caps> </Button> @@ -256,7 +257,7 @@ const FormatsPage = () => { })} /> </Layout> - ) -} + </DotsBackground> +) export default FormatsPage From ee062e68e7d7d505093b1b6037fb55abe9f5c8ff Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 31 May 2024 21:37:06 +0200 Subject: [PATCH 25/57] refactor: add announcement on logo page --- src/components/elements/Terminal/Terminal.js | 12 +++++----- .../patterns/Announcement/Announcement.js | 23 +++++++++++-------- src/pages/formats.js | 13 +++++------ src/pages/logo.js | 14 +++++++++-- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/components/elements/Terminal/Terminal.js b/src/components/elements/Terminal/Terminal.js index 4b7032c9f..f460a9dc6 100644 --- a/src/components/elements/Terminal/Terminal.js +++ b/src/components/elements/Terminal/Terminal.js @@ -84,9 +84,9 @@ const TerminalButtonRed = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(1), - animationDuration - } + animationDelay: animationDelay(1), + animationDuration + } : undefined } {...props} @@ -112,9 +112,9 @@ const TerminalButtonGreen = ({ loading, ...props }) => ( style={ loading ? { - animationDelay: animationDelay(3), - animationDuration - } + animationDelay: animationDelay(3), + animationDuration + } : undefined } {...props} diff --git a/src/components/patterns/Announcement/Announcement.js b/src/components/patterns/Announcement/Announcement.js index 85fd7147b..5d6d1da09 100644 --- a/src/components/patterns/Announcement/Announcement.js +++ b/src/components/patterns/Announcement/Announcement.js @@ -1,14 +1,19 @@ -import React from 'react' -import { Link } from 'components/elements' +import { Box, Badge, Link } from 'components/elements' import { theme } from 'theme' +import React from 'react' + +const Announcement = ({ href, children, ...props }) => ( + <Box {...props}> + <Link css={theme({ whiteSpace: 'pre-wrap', color: 'black' })} href={href}> + <> + <Badge css={theme({ mr: 2 })}>new</Badge> + {children} + {/* {' →'} */} + </> + </Link> + + </Box> -const Announcement = ({ href, children }) => ( - <Link css={theme({ color: 'black' })} href={href}> - <> - {children} - {' →'} - </> - </Link> ) export default Announcement diff --git a/src/pages/formats.js b/src/pages/formats.js index f5a173d93..ecc1b89d2 100644 --- a/src/pages/formats.js +++ b/src/pages/formats.js @@ -1,9 +1,4 @@ import { DotsBackground, Faq, Caption, Layout } from 'components/patterns' -import { cx, colors, borders, layout, theme } from 'theme' -import { XCircle, CheckCircle } from 'react-feather' -import React, { createElement } from 'react' -import { issueUrl } from 'helpers' - import { Box, Button, @@ -16,6 +11,11 @@ import { Text } from 'components/elements' +import { cx, colors, borders, layout, theme } from 'theme' +import { XCircle, CheckCircle } from 'react-feather' +import React, { createElement } from 'react' +import { issueUrl } from 'helpers' + import fileFormats from '../../data/formats' const [{ score }, formats] = fileFormats @@ -240,8 +240,7 @@ const FormatsPage = () => ( <Box css={theme({ p: [4, 4, 0, 0] })}> <Button onClick={() => - window.open(issueUrl.bug(), '_blank', 'noopener noreferrer') - } + window.open(issueUrl.bug(), '_blank', 'noopener noreferrer')} > <Caps>Request a format</Caps> </Button> diff --git a/src/pages/logo.js b/src/pages/logo.js index 2d1286a38..6fbf61c69 100644 --- a/src/pages/logo.js +++ b/src/pages/logo.js @@ -38,6 +38,7 @@ import { } from 'components/elements' import { + Announcement, ArrowLink, Average, Block, @@ -219,7 +220,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ </Flex> <Flex css={theme({ - justifyContent: 'center', + justifyContent: 'space-between', alignItems: 'center', pb: 4 })} @@ -301,6 +302,15 @@ const LiveDemo = React.memo(function LiveDemo ({ as='section' css={theme({ alignItems: 'center', pt: 2, pb: [4, 4, 5, 5] })} > + <Announcement + data-event-location='Home' + data-event-name='Announcement' + href='https://logo.microlink.io/' + css={theme({ pb: 3 })} + > + <span>Add logo to any website with </span> + <b>Microlink for Logo</b> + </Announcement> <Heading css={theme({ px: [4, 5, 5, 5], maxWidth: layout.large })}> Hey, oh, logos! </Heading> @@ -382,7 +392,7 @@ const LiveDemo = React.memo(function LiveDemo ({ toClipboard={toClipboard} data={data} /> - <Box css={theme({ px: 4, width: '100%' })}> + <Box css={theme({ width: '100%' })}> <Tooltip tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ From f6976850701033c545218f5af4b02bb20d90aebc Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 10:32:00 +0200 Subject: [PATCH 26/57] chore: add tooltip type --- src/components/elements/Tooltip/Tooltip.js | 24 ++++------- src/pages/insights.js | 10 +++-- src/pages/logo.js | 48 ++++++++++++---------- src/pages/meta.js | 9 ++-- src/pages/pdf.js | 5 ++- src/pages/screenshot.js | 10 +++-- 6 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/components/elements/Tooltip/Tooltip.js b/src/components/elements/Tooltip/Tooltip.js index a897cc825..ee3303cbd 100644 --- a/src/components/elements/Tooltip/Tooltip.js +++ b/src/components/elements/Tooltip/Tooltip.js @@ -59,7 +59,7 @@ const TippyTheme = styled(Tippy)` const TippyContainer = styled(Box)` outline: 0; - cursor: help; + cursor: ${({ $type }) => $type}; ` const TooltipContent = styled(Text)` @@ -74,6 +74,7 @@ const Tooltip = ({ children, tooltipsOpts, containerProps, + type = 'help', top, ...props }) => { @@ -83,7 +84,9 @@ const Tooltip = ({ content={content} {...Object.assign(TOOLTIPS_OPTS, tooltipsOpts)} > - <TippyContainer {...props}>{children}</TippyContainer> + <TippyContainer $type={type} {...props}> + {children} + </TippyContainer> </TippyTheme> ) } @@ -91,20 +94,9 @@ const Tooltip = ({ Tooltip.Content = TooltipContent Tooltip.TEXT = { - OPTIONS: { - interactive: false, - hideOnClick: true - }, - COPY: { - URL: 'Click to copy URL', - COLOR: color => `Click to copy ${color}`, - HTML: 'Click to copy HTML' - }, - COPIED: { - URL: 'Copied URL to clipboard!', - COLOR: color => `Copied ${color} to clipboard!`, - HTML: 'Copied HTML to clipboard!' - } + OPTIONS: { interactive: false, hideOnClick: true }, + COPY: word => `Click to copy ${word}`, + COPIED: word => `Copied ${word} to clipboard!` } export default Tooltip diff --git a/src/pages/insights.js b/src/pages/insights.js index 267a786dd..5c57816c9 100644 --- a/src/pages/insights.js +++ b/src/pages/insights.js @@ -331,9 +331,10 @@ const LiveDemo = React.memo(function LiveDemo ({ })} > <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -342,7 +343,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetTechnologiesText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} css={theme({ @@ -363,9 +364,10 @@ const LiveDemo = React.memo(function LiveDemo ({ <LighthouseReport width={528} src={reportUrl} /> <Box css={theme({ pt: [2, 2, 3, 3], mx: 'auto' })}> <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -374,7 +376,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetInsightsText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} css={theme({ diff --git a/src/pages/logo.js b/src/pages/logo.js index 6fbf61c69..a7aff41d4 100644 --- a/src/pages/logo.js +++ b/src/pages/logo.js @@ -1,5 +1,5 @@ -import { cdnUrl, issueUrl, noop, trimMs } from 'helpers' import { toPx, borders, layout, colors, theme } from 'theme' +import { cdnUrl, issueUrl, noop, trimMs } from 'helpers' import React, { useMemo, useState } from 'react' import isUrl from 'is-url-http/lightweight' import { getApiUrl } from '@microlink/mql' @@ -106,7 +106,7 @@ const LogoPreview = ({ toClipboard = noop, logo, style, ...props }) => { return ( <LogoBox onClick={() => { - toClipboard({ copy: logo.url, text: Tooltip.TEXT.COPIED.URL }) + toClipboard({ copy: logo.url, text: Tooltip.TEXT.COPIED('URL') }) }} style={{ cursor: style.cursor }} {...props} @@ -137,17 +137,17 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ const colors = isLoading ? Array.from({ length: 6 }, () => '#fff') : [ - ...new Set( - [] - .concat( - logo.palette, - logo.background_color, - logo.color, - logo.alternative_color - ) - .filter(Boolean) - ) - ] + ...new Set( + [] + .concat( + logo.palette, + logo.background_color, + logo.color, + logo.alternative_color + ) + .filter(Boolean) + ) + ] const LogoComponent = isLoading ? LogoEmpty @@ -203,16 +203,19 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ {IMAGE_PREVIEW_STYLE.map((imagePreviewStyle, index) => { return ( <Tooltip + type='copy' key={`${data.url}_${index}`} tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.URL}</Tooltip.Content> + <Tooltip.Content> + {Tooltip.TEXT.COPY('URL')} + </Tooltip.Content> } > <LogoComponent toClipboard={toClipboard} logo={logo} - style={{ ...imagePreviewStyle, cursor: 'pointer' }} + style={{ ...imagePreviewStyle }} /> </Tooltip> ) @@ -230,6 +233,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ {colors.map((color, index) => { return ( <Tooltip + type='copy' key={`${color}_${index}`} tooltipsOpts={{ interactive: false, @@ -237,7 +241,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ }} content={ <Tooltip.Content> - {Tooltip.TEXT.COPY.COLOR(color)} + {Tooltip.TEXT.COPY(color)} </Tooltip.Content> } css={theme({ @@ -253,12 +257,13 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ borderColor: 'black10' })} title={color} - style={{ cursor: 'pointer', background: color }} + style={{ background: color }} onClick={() => toClipboard({ copy: color, - text: Tooltip.TEXT.COPIED.COLOR(color) - })} + text: Tooltip.TEXT.COPIED(color) + }) + } /> </Tooltip> ) @@ -394,9 +399,10 @@ const LiveDemo = React.memo(function LiveDemo ({ /> <Box css={theme({ width: '100%' })}> <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -405,7 +411,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} css={theme({ diff --git a/src/pages/meta.js b/src/pages/meta.js index a16535064..912c9b21c 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -122,7 +122,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const [ClipboardComponent, toClipboard] = useClipboard() const size = useWindowSize() - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.9 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio @@ -259,11 +259,12 @@ const LiveDemo = React.memo(function LiveDemo ({ > {JSON.stringify(jsonData, null, 2)} </CodeEditor> - <Box css={theme({ pt: 4, px: 4, width: cardWidth })}> + <Box css={theme({ pt: 4, width: cardWidth })}> <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -272,7 +273,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} css={theme({ cursor: 'copy', width: '100%', color: 'black60' })} diff --git a/src/pages/pdf.js b/src/pages/pdf.js index c28e27682..321d20faf 100644 --- a/src/pages/pdf.js +++ b/src/pages/pdf.js @@ -260,9 +260,10 @@ const LiveDemo = React.memo(function LiveDemo ({ /> <Box css={theme({ mt: 4, px: 4, width: cardWidth })}> <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -271,7 +272,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} style={{ cursor: 'copy' }} diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 80018a780..4372a9dab 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -180,8 +180,9 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - }} + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + } + } /> </Link> ) @@ -356,9 +357,10 @@ const LiveDemo = React.memo(function LiveDemo ({ /> <Box css={theme({ px: 4 })} style={{ width: cardWidth / 1.5 }}> <Tooltip + type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} content={ - <Tooltip.Content>{Tooltip.TEXT.COPY.HTML}</Tooltip.Content> + <Tooltip.Content>{Tooltip.TEXT.COPY('HTML')}</Tooltip.Content> } > <Input @@ -367,7 +369,7 @@ const LiveDemo = React.memo(function LiveDemo ({ event.target.select() toClipboard({ copy: snippetText, - text: Tooltip.TEXT.COPIED.HTML + text: Tooltip.TEXT.COPIED('HTML') }) }} style={{ cursor: 'copy' }} From ceb60a5fda311d34d3f92d45d75adade1c373b7f Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 10:32:17 +0200 Subject: [PATCH 27/57] refactor: avoid capitalize --- src/templates/doc/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/doc/index.js b/src/templates/doc/index.js index 4366800d3..2ac5e28bd 100644 --- a/src/templates/doc/index.js +++ b/src/templates/doc/index.js @@ -55,7 +55,7 @@ const DocTemplate = ({ meta, content, githubUrl, ...props }) => { })} > <Text css={theme({ color: 'gray', fontSize: 0 })}> - Last Edited on {formatDate(meta.date)} + Last edited on {formatDate(meta.date)} </Text> <Link href={githubUrl} css={theme({ fontSize: 0 })}> Edit on GitHub From 6347a337a293f4e53e201c846d062b08544c7d1b Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 10:32:33 +0200 Subject: [PATCH 28/57] refactor(/user-agents): better experience --- package.json | 3 +- .../fetch-data/providers/fetch-user-agents.js | 35 ++++ src/components/elements/Toggle/Toggle.js | 9 +- src/pages/user-agents.js | 168 ++++++++++++------ 4 files changed, 157 insertions(+), 58 deletions(-) create mode 100644 scripts/fetch-data/providers/fetch-user-agents.js diff --git a/package.json b/package.json index 8bc4a5b92..e602594b5 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,8 @@ "simple-git-hooks": "latest", "standard": "latest", "standard-markdown": "latest", - "standard-version": "latest" + "standard-version": "latest", + "tinyspawn": "latest" }, "engines": { "node": ">= 18" diff --git a/scripts/fetch-data/providers/fetch-user-agents.js b/scripts/fetch-data/providers/fetch-user-agents.js new file mode 100644 index 000000000..0fb10f187 --- /dev/null +++ b/scripts/fetch-data/providers/fetch-user-agents.js @@ -0,0 +1,35 @@ +'use strict' + +const crawlerAgents = require('top-crawler-agents') +const userAgents = require('top-user-agents') +const $ = require('tinyspawn') +const path = require('path') + +const pkgInfo = async pkgName => { + const { stdout } = await $.json(`npm view ${pkgName} --json`) + const version = stdout.version + const updatedAt = stdout.time[version] + return { updatedAt, version } +} + +const fn = async () => { + const npm = await Promise.all([ + pkgInfo('top-user-agents'), + pkgInfo('top-crawler-agents') + ]) + return { + 'top-user-agents': { + ...npm[0], + data: userAgents + }, + 'top-crawler-agents': { + ...npm[1], + data: crawlerAgents + } + } +} + +module.exports = () => + require('../create-provider').fromCode(fn, { + dist: path.resolve(__dirname, '../../../data/user-agents.json') + }) diff --git a/src/components/elements/Toggle/Toggle.js b/src/components/elements/Toggle/Toggle.js index 928072006..54999de49 100644 --- a/src/components/elements/Toggle/Toggle.js +++ b/src/components/elements/Toggle/Toggle.js @@ -24,7 +24,14 @@ function Toggle ({ onChange = noop, children, defaultValue, ...props }) { return ( <Flex css={{ width: '100%' }} {...props}> - <Box css={theme({ border: 1, borderColor: 'black05', borderRadius: 2 })}> + <Box + css={theme({ + bg: 'white', + border: 1, + borderColor: 'black05', + borderRadius: 2 + })} + > {children.map((value, index) => { const isLast = index + 1 === children.length const isActive = active === value diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index ff960ffd2..1596f2464 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -1,89 +1,145 @@ -import { ArrowLink, Caption, Layout } from 'components/patterns' -import Markdown from 'components/markdown' +import { DotsBackground, ArrowLink, Caption, Layout } from 'components/patterns' +import { Li, Ul } from 'components/markdown' import React, { useState } from 'react' import { layout, theme } from 'theme' -import { Toggle, Container, Flex, Heading, Meta } from 'components/elements' +import { + Box, + Container, + Flex, + Heading, + Meta, + Toggle, + Tooltip +} from 'components/elements' -import userAgents from 'top-user-agents' -import crawlerAgents from 'top-crawler-agents' +import { useClipboard } from 'components/hook' + +import userAgents from '../../data/user-agents.json' export const Head = () => ( <Meta description='Most common user-agents used on Internet' /> ) +const formatYYYMMDDDate = (date = new Date()) => { + const year = date.getFullYear() + const month = String(date.getMonth() + 1).padStart(2, '0') + const day = String(date.getDate()).padStart(2, '0') + return `${year}-${month}-${day}` +} + const UserAgentsPage = () => { - const [type, setType] = useState('user') - const isUserType = type === 'user' + const [ClipboardComponent, toClipboard] = useClipboard() + const [type, setType] = useState('top-user-agents') + const isUserType = type === 'top-user-agents' - const list = isUserType ? userAgents : crawlerAgents + const { data, updatedAt, version } = userAgents[type] const githubUrl = isUserType ? 'https://github.com/microlinkhq/top-user-agents' : 'https://github.com/Kikobeats/top-crawler-agents' const downloadUrl = isUserType - ? 'https://raw.githubusercontent.com/microlinkhq/top-user-agents/master/src/index.json' - : 'https://raw.githubusercontent.com/Kikobeats/top-crawler-agents/master/index.json' - - const content = list.map(userAgent => `* ${userAgent}`).join('\n') + ? `https://raw.githubusercontent.com/microlinkhq/top-user-agents/v${version}/src/index.json` + : `https://raw.githubusercontent.com/Kikobeats/top-crawler-agents/v${version}/index.json` return ( - <Layout> - <Container - css={theme({ - pt: 2, - pb: 3, - justifyContent: 'center', - alignItems: 'center' - })} - > - <Heading css={theme({ px: 5, maxWidth: layout.large })}> - User Agents - </Heading> - <Caption - forwardedAs='h2' - css={theme({ - pt: [3, null, 4], - px: ['48px', 4], - maxWidth: layout.small - })} - titleize={false} - > - Most common `user-agent` used on Internet. - </Caption> - <Flex + <DotsBackground> + <Layout> + <Container css={theme({ - py: [3, null, 4], - flexDirection: 'column', + pt: 2, + pb: 3, justifyContent: 'center', alignItems: 'center' })} > - <Toggle - css={theme({ alignItems: 'center', justifyContent: 'center' })} - defaultValue='User Agent' - onChange={value => - setType(value === 'User Agent' ? 'user' : 'crawler')} + <Heading css={theme({ px: 5, maxWidth: layout.large })}> + User Agents + </Heading> + <Caption + forwardedAs='h2' + css={theme({ + pt: [3, null, 4], + maxWidth: layout.small + })} + titleize={false} > - {['User Agent', 'Crawler Agent']} - </Toggle> + Most common HTTP User-Agent on the Internet. + <br /> + Weekly updated. Last update:{' '} + {formatYYYMMDDDate(new Date(updatedAt))}. + </Caption> <Flex css={theme({ - pt: [3, null, 4], - gap: [2, 4], - fontSize: [2, null, 3] + py: [3, null, 4], + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' })} > - <ArrowLink href={downloadUrl}>Download</ArrowLink> - <ArrowLink href={githubUrl}>See on GitHub</ArrowLink> + <Toggle + css={theme({ alignItems: 'center', justifyContent: 'center' })} + defaultValue='User Agent' + onChange={value => + setType( + `top-${value === 'User Agent' ? 'user' : 'crawler'}-agents` + ) + } + > + {['User Agent', 'Crawler Agent']} + </Toggle> + <Flex + css={theme({ + pt: [3, null, 4], + gap: [2, 4], + fontSize: [2, null, 3] + })} + > + <ArrowLink href={downloadUrl}>Download</ArrowLink> + <ArrowLink href={githubUrl}>See on GitHub</ArrowLink> + </Flex> + </Flex> + <Flex css={theme({ flexDirection: 'column', maxWidth: '95vw' })}> + <Ul> + {data.map((userAgent, index) => ( + <Tooltip + type='copy' + key={`${userAgent}_${index}`} + tooltipsOpts={Tooltip.TEXT.OPTIONS} + content={ + <Tooltip.Content> + {Tooltip.TEXT.COPY('user agent')} + </Tooltip.Content> + } + > + <Li + key={userAgent} + onClick={() => { + toClipboard({ + copy: userAgent, + text: Tooltip.TEXT.COPIED('HTML') + }) + }} + > + <Box + css={` + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + `} + > + {userAgent} + </Box> + </Li> + </Tooltip> + ))} + </Ul> </Flex> - </Flex> - <Flex css={theme({ flexDirection: 'column', maxWidth: '95vw' })}> - <Markdown>{content}</Markdown> - </Flex> - </Container> - </Layout> + <ClipboardComponent /> + </Container> + </Layout> + </DotsBackground> ) } From 24c5034aacdb6e8214ee5304ddfe56ec4b9c0139 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 10:40:36 +0200 Subject: [PATCH 29/57] fix: linter --- src/pages/logo.js | 25 ++++++++++++------------- src/pages/screenshot.js | 5 ++--- src/pages/user-agents.js | 3 +-- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/pages/logo.js b/src/pages/logo.js index a7aff41d4..d0b581b58 100644 --- a/src/pages/logo.js +++ b/src/pages/logo.js @@ -137,17 +137,17 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ const colors = isLoading ? Array.from({ length: 6 }, () => '#fff') : [ - ...new Set( - [] - .concat( - logo.palette, - logo.background_color, - logo.color, - logo.alternative_color - ) - .filter(Boolean) - ) - ] + ...new Set( + [] + .concat( + logo.palette, + logo.background_color, + logo.color, + logo.alternative_color + ) + .filter(Boolean) + ) + ] const LogoComponent = isLoading ? LogoEmpty @@ -262,8 +262,7 @@ const PreviewResponsive = React.memo(function PreviewResponsive ({ toClipboard({ copy: color, text: Tooltip.TEXT.COPIED(color) - }) - } + })} /> </Tooltip> ) diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 4372a9dab..967e40721 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -180,9 +180,8 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - } - } + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + }} /> </Link> ) diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index 1596f2464..6a6bf8122 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -84,8 +84,7 @@ const UserAgentsPage = () => { onChange={value => setType( `top-${value === 'User Agent' ? 'user' : 'crawler'}-agents` - ) - } + )} > {['User Agent', 'Crawler Agent']} </Toggle> From c3bb46eb61e26a9c3f038969fdd33e2d595197ac Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 11:16:30 +0200 Subject: [PATCH 30/57] refactor: theme prop into isDark --- src/components/elements/Label.js | 5 ++--- src/components/elements/PriceMonthly.js | 6 +----- .../patterns/DotsBackground/DotsBackground.js | 8 +++----- src/components/patterns/Layout.js | 3 +-- src/pages/enterprise.js | 10 ++++++---- src/pages/status.js | 12 ++++++------ 6 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/components/elements/Label.js b/src/components/elements/Label.js index 6d3e9270a..d78bb11c9 100644 --- a/src/components/elements/Label.js +++ b/src/components/elements/Label.js @@ -5,8 +5,7 @@ import React from 'react' import Text from './Text' -export const getColor = ({ theme }) => - theme === 'dark' ? colors.white60 : colors.black60 +const getColor = ({ isDark }) => (isDark ? colors.white60 : colors.black60) export const labelStyle = css` font-weight: ${fontWeights.normal}; @@ -15,7 +14,7 @@ export const labelStyle = css` ` const StyledLabel = styled(Text).withConfig({ - shouldForwardProp: prop => !['suffix'].includes(prop) + shouldForwardProp: prop => !['isDark', 'suffix'].includes(prop) })` ${theme({ fontSize: 1 })}; diff --git a/src/components/elements/PriceMonthly.js b/src/components/elements/PriceMonthly.js index 59f1a10fd..2ddb3e114 100644 --- a/src/components/elements/PriceMonthly.js +++ b/src/components/elements/PriceMonthly.js @@ -3,7 +3,7 @@ import styled from 'styled-components' import React from 'react' import { theme } from 'theme' -import Label, { labelStyle, getColor } from './Label' +import Label, { labelStyle } from './Label' const Price = styled(Label)` font-weight: bold; @@ -17,10 +17,6 @@ const Price = styled(Label)` top: -5px; left: 0; } - - &::after { - color: ${props => getColor(props)}; - } ` const PriceMonthly = props => ( diff --git a/src/components/patterns/DotsBackground/DotsBackground.js b/src/components/patterns/DotsBackground/DotsBackground.js index 9fd514594..1243bc316 100644 --- a/src/components/patterns/DotsBackground/DotsBackground.js +++ b/src/components/patterns/DotsBackground/DotsBackground.js @@ -22,7 +22,7 @@ const animateStyle = css` ` const StyledDotsBackground = styled(Box).withConfig({ - shouldForwardProp: prop => !['animate'].includes(prop) + shouldForwardProp: prop => !['isDark', 'animate'].includes(prop) })` position: relative; min-height: 100vh; @@ -34,7 +34,7 @@ const StyledDotsBackground = styled(Box).withConfig({ height: 100%; z-index: -1; - ${props => (props.theme === 'dark' ? darkStyle : lightStyle)} + ${({ isDark }) => (isDark ? darkStyle : lightStyle)} background-position: 0 0, 25px 25px; background-size: 50px 50px; @@ -42,8 +42,6 @@ const StyledDotsBackground = styled(Box).withConfig({ } ` -const DotsBackground = props => ( - <StyledDotsBackground theme='light' animate {...props} /> -) +const DotsBackground = props => <StyledDotsBackground animate {...props} /> export default DotsBackground diff --git a/src/components/patterns/Layout.js b/src/components/patterns/Layout.js index 6878b2059..8b6d4114a 100644 --- a/src/components/patterns/Layout.js +++ b/src/components/patterns/Layout.js @@ -27,11 +27,10 @@ const Layout = ({ children, onClick = noop, style, - theme = 'light', + isDark = false, component = Box, ...props }) => { - const isDark = theme === 'dark' const breakpoint = useBreakpoint([0, 1, 2, 3]) const toolbarHeight = TOOLBAR_HEIGHTS[breakpoint] diff --git a/src/pages/enterprise.js b/src/pages/enterprise.js index 794d613d3..813f20fd5 100644 --- a/src/pages/enterprise.js +++ b/src/pages/enterprise.js @@ -34,7 +34,7 @@ Running a **Microlink Enterprise** plan means: The physical servers associated with your own Microlink API endpoint can be chosen between 8 locations (🇺🇸 New York, 🇺🇸 San Francisco, 🇳🇱 Amsterdam, 🇸🇬 Singapore, 🇬🇧 London, 🇩🇪 Frankfurt, 🇨🇦 Toronto, or 🇮🇳 Bangalore). -The price model is the same as you Microlink Pro plan, plus <PriceMonthly theme='dark'>500</PriceMonthly> for the extra cost of keeping the dedicated infrastructure running.`.trim() +The price model is the same as you Microlink Pro plan, plus <PriceMonthly isDark>500</PriceMonthly> for the extra cost of keeping the dedicated infrastructure running.`.trim() const GradientButton = styled(Button)` transition: filter ${transition.medium}; @@ -59,10 +59,11 @@ export const Head = () => ( const EnterprisePage = () => { const [{ theme, primary, secondary }] = useTheme(THEMES, 'dark') + const isDark = theme === 'dark' return ( - <DotsBackground theme={theme}> - <Layout theme={theme} footer={{ style: { background: 'transparent' } }}> + <DotsBackground isDark={isDark}> + <Layout footer={{ style: { background: 'transparent' } }} isDark={isDark}> <Container css={themeProp({ pt: [2, null, 3], @@ -105,7 +106,8 @@ const EnterprisePage = () => { 'mailto:hello@microlink.io?subject=Microlink%20Enterprise&body=Hello%2C%20I%20want%20to%20upgrade%20my%20customer%20plan%20to%20Microlink%20Enterprise.%0D%0A%0D%0ACan%20you%20tell%20me%20more%20about%20the%20details%3F%0D%0A%0D%0AThank%20you!%0D%0A', '_blank', 'noopener noreferrer' - )} + ) + } > <Caps css={themeProp({ bg: 'black', px: 3, py: 2, color: primary })} diff --git a/src/pages/status.js b/src/pages/status.js index 5dcbe0a25..14aeca3c9 100644 --- a/src/pages/status.js +++ b/src/pages/status.js @@ -45,7 +45,7 @@ const StatusPage = () => { return ( <Layout onClick={toggleTheme} - theme={theme} + isDark={theme === 'dark'} style={{ background: bg }} component={Flex} css={{ justifyContent: 'center', alignItems: 'center' }} @@ -65,12 +65,13 @@ const StatusPage = () => { fontWeight: 'regular', fontFamily: 'mono', lineHeight: 0, - fontSize: [4, null, null, 7], + fontSize: 4, pt: [2, null, 3], color })} > - Loading <DotSpinner /> + Please wait + <DotSpinner /> </Text> </Flex> </Choose.When> @@ -78,9 +79,8 @@ const StatusPage = () => { <Monospace css={themeProp({ color })}> $ watch curl -sL {endpoint} </Monospace> - <Monospace - css={themeProp({ color })} - >{`\n${resume}`} + <Monospace css={themeProp({ color })}> + {`\n${resume}`} </Monospace> <Monospace css={themeProp({ color, fontSize: [0, null, 1] })}> {`\n${info}`} From 63eb9eaee314b6ddbf6c37e7c853767fa4e2ac02 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 1 Jun 2024 11:22:01 +0200 Subject: [PATCH 31/57] fix: setup body background under dark --- src/styles/main.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/styles/main.scss b/src/styles/main.scss index e6343f05f..16b675995 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -255,6 +255,8 @@ select:invalid { body[data-theme="dark"] { + background: var(--black); + input::placeholder, select:invalid { color: rgba(255, 255, 255, 0.5); From 732cdace9f94a05f352c3228ab484a2bf900e4a3 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sun, 2 Jun 2024 10:37:45 +0200 Subject: [PATCH 32/57] fix: letter spacing --- src/pages/blog/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pages/blog/index.js b/src/pages/blog/index.js index 3d9b2a6f8..1b2ed3fab 100644 --- a/src/pages/blog/index.js +++ b/src/pages/blog/index.js @@ -1,4 +1,4 @@ -import { textGradient, layout, transition, theme } from 'theme' +import { textGradient, layout, transition, theme, letterSpacings } from 'theme' import { Meta, Heading, Link, Flex } from 'components/elements' import { Layout, Caption } from 'components/patterns' import { PostTitle } from 'components/pages/blog' @@ -9,7 +9,7 @@ import { H1 } from 'components/markdown' import TimeAgo from 'react-timeago' import React from 'react' -const CustomFlex = styled(Flex)` +const BlogSeparator = styled(Flex)` ${({ $isLastPost }) => theme({ py: 4, @@ -28,7 +28,7 @@ const CustomFlex = styled(Flex)` })} ` -const CustomLink = styled(Link)` +const BlogLink = styled(Link)` cursor: pointer; h3 { @@ -44,8 +44,11 @@ const CustomLink = styled(Link)` const BlogPost = ({ title, date, slug, isLastPost }) => { return ( - <CustomLink href={slug} css={{ width: '100%' }}> - <CustomFlex $isLastPost={isLastPost}> + <BlogLink + href={slug} + css={{ width: '100%', letterSpacing: letterSpacings[1] }} + > + <BlogSeparator $isLastPost={isLastPost}> <H1 forwardedAs='h3' css={theme({ @@ -71,8 +74,8 @@ const BlogPost = ({ title, date, slug, isLastPost }) => { > {formatDate(date)} (<TimeAgo date={date} />) </Caption> - </CustomFlex> - </CustomLink> + </BlogSeparator> + </BlogLink> ) } From d044a0c58dca9830a0acbc3b2b3faa73bb694520 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sun, 2 Jun 2024 10:48:43 +0200 Subject: [PATCH 33/57] fix: linter --- src/pages/enterprise.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/enterprise.js b/src/pages/enterprise.js index 813f20fd5..29cb15a19 100644 --- a/src/pages/enterprise.js +++ b/src/pages/enterprise.js @@ -106,8 +106,7 @@ const EnterprisePage = () => { 'mailto:hello@microlink.io?subject=Microlink%20Enterprise&body=Hello%2C%20I%20want%20to%20upgrade%20my%20customer%20plan%20to%20Microlink%20Enterprise.%0D%0A%0D%0ACan%20you%20tell%20me%20more%20about%20the%20details%3F%0D%0A%0D%0AThank%20you!%0D%0A', '_blank', 'noopener noreferrer' - ) - } + )} > <Caps css={themeProp({ bg: 'black', px: 3, py: 2, color: primary })} From 41824a7e92e4cbc16f96516fe6d5fb872b636c6c Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sun, 2 Jun 2024 11:57:58 +0200 Subject: [PATCH 34/57] refactor: adjust aspect ratio --- src/components/elements/Card/Card.js | 2 +- src/pages/meta.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/elements/Card/Card.js b/src/components/elements/Card/Card.js index f3295f287..7a6203644 100644 --- a/src/components/elements/Card/Card.js +++ b/src/components/elements/Card/Card.js @@ -6,7 +6,7 @@ import Flex from '../Flex' import Text from '../Text' const BASE_WIDTH = 650 -const BASE_RATIO = 1.4 +const BASE_RATIO = 1.35 const BASE_HEIGHT = BASE_WIDTH / BASE_RATIO const CardBase = styled(Flex)` diff --git a/src/pages/meta.js b/src/pages/meta.js index 912c9b21c..19ea9290c 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -122,7 +122,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const [ClipboardComponent, toClipboard] = useClipboard() const size = useWindowSize() - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.9 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio From 252139b8883f9e711601e895a9382b97caa56c59 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sun, 2 Jun 2024 17:37:21 +0200 Subject: [PATCH 35/57] fix: sdk page --- package.json | 4 +-- .../patterns/Microlink/Microlink.js | 11 +++++-- src/pages/sdk.js | 30 ++++++++++--------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index e602594b5..e071cdfa0 100644 --- a/package.json +++ b/package.json @@ -102,8 +102,8 @@ ], "dependencies": { "@kikobeats/use-query-state": "1.2.2", - "@microlink/mql": "~0.12.1", - "@microlink/react": "5.5.15", + "@microlink/mql": "~0.13.6", + "@microlink/react": "5.5.18", "@microlink/recipes": "~1.8.1", "@react-spring/web": "~9.7.3", "@stripe/react-stripe-js": "~2.4.0", diff --git a/src/components/patterns/Microlink/Microlink.js b/src/components/patterns/Microlink/Microlink.js index 48cb14860..68051a5fa 100644 --- a/src/components/patterns/Microlink/Microlink.js +++ b/src/components/patterns/Microlink/Microlink.js @@ -4,7 +4,7 @@ import React from 'react' import demoLinks from '../../../../data/demo-links' -const media = [ +const defaultMedia = [ 'iframe', isFastConnection && 'video', isFastConnection && 'audio', @@ -12,7 +12,14 @@ const media = [ 'logo' ].filter(Boolean) -const Microlink = ({ url, style, fetchData, setData, ...props }) => { +const Microlink = ({ + url, + style, + fetchData, + setData, + media = defaultMedia, + ...props +}) => { if (url) url = template(url) const variations = urlVariations(url) diff --git a/src/pages/sdk.js b/src/pages/sdk.js index 7dcebe687..f6ad5139c 100644 --- a/src/pages/sdk.js +++ b/src/pages/sdk.js @@ -1,12 +1,12 @@ -import { useQueryState, useWindowSize } from 'components/hook' -import { layout, breakpoints, theme, toPx } from 'theme' -import React, { useMemo, useState } from 'react' +import React, { useMemo, useState, useEffect } from 'react' +import { useQueryState } from 'components/hook' import isUrl from 'is-url-http/lightweight' import { cdnUrl, mqlCode } from 'helpers' import * as Icons from 'components/icons' import prependHttp from 'prepend-http' import styled from 'styled-components' import humanizeUrl from 'humanize-url' +import { layout, theme } from 'theme' import { Box, @@ -51,7 +51,6 @@ const SUGGESTIONS = [ return { value: humanizeUrl(data.url) } }) -const SMALL_BREAKPOINT = Number(breakpoints[0].replace('px', '')) const MODES = ['preview', 'iframe'] const TYPES = ['render', 'code'] @@ -76,6 +75,7 @@ const HeroCard = styled(Card)` .microlink_card { width: 100%; height: 100%; + maxw-width: 650px; } ` @@ -92,14 +92,16 @@ const LiveDemo = React.memo(function LiveDemo ({ onSubmit, query }) { - const size = useWindowSize() const [mode, setMode] = useState(MODES[0]) const [type, setType] = useState(TYPES[0]) + const [minHeight, setMinHeight] = useState(0) - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 - const cardWidth = size.width / cardBase - const cardHeight = cardWidth / Card.ratio - const runkitHeight = cardHeight - 36 * 2 - 8 * 2 + useEffect(() => { + const card = document.querySelector('.microlink_card') + if (card) { + setMinHeight(card.getBoundingClientRect().height - 36 * 2 - 8 * 2) + } + }) const [inputUrl, setInputUrl] = useState(query.url || '') @@ -209,14 +211,14 @@ const LiveDemo = React.memo(function LiveDemo ({ > <HeroCard css={theme({ - width: cardWidth, - height: cardHeight, - border: type === 'code' ? 'none' : 1 + maxWidth: layout.small, + border: type === 'code' ? 'inherit' : undefined })} > <Choose> <Choose.When condition={type === 'render'}> <LinkPreview + key={`${url}_${media.join('_')}`} loading={isLoading ? true : undefined} size='large' url={data.url} @@ -228,7 +230,7 @@ const LiveDemo = React.memo(function LiveDemo ({ <Choose.When condition={type === 'code'}> <MultiCodeEditor css={{ width: '100%' }} - interactive={{ minHeight: toPx(runkitHeight) }} + interactive={{ minHeight }} languages={mqlCode( data.url, { @@ -252,7 +254,7 @@ const LiveDemo = React.memo(function LiveDemo ({ pr: '7px', alignItems: ['center', undefined, undefined, undefined], justifyContent: 'space-between', - flexDirection: ['column', 'row', 'row', 'row'] + flexDirection: 'row' })} > <Box css={theme({ pt: [3, 4] })}> From 5e641cbe39358369aa65f0dfab220cb98d76d47d Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Tue, 16 Jul 2024 22:38:06 +0200 Subject: [PATCH 36/57] fix: user-agents title --- src/pages/user-agents.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index 6a6bf8122..cdc654005 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -18,7 +18,10 @@ import { useClipboard } from 'components/hook' import userAgents from '../../data/user-agents.json' export const Head = () => ( - <Meta description='Most common user-agents used on Internet' /> + <Meta + title='User Agents' + description='Most common user-agents used on Internet' + /> ) const formatYYYMMDDDate = (date = new Date()) => { @@ -84,7 +87,8 @@ const UserAgentsPage = () => { onChange={value => setType( `top-${value === 'User Agent' ? 'user' : 'crawler'}-agents` - )} + ) + } > {['User Agent', 'Crawler Agent']} </Toggle> From b35cc4fa57e8b6b7b7ba1deede9c20d72ec99f0d Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Tue, 16 Jul 2024 22:39:52 +0200 Subject: [PATCH 37/57] chore: migrate screenshot --- src/pages/screenshot.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 967e40721..74983340a 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -164,8 +164,7 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { alt={`Microlink screenshot for ${data.url}`} css={theme({ my: 4, - pl: 0, - pr: 0, + px: 0, height: cardHeight, width: cardWidth, border: 1, @@ -180,8 +179,9 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - }} + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + } + } /> </Link> ) From a5cfcd1b1c69ed7d6876cbdf67996ff869e83261 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Tue, 16 Jul 2024 22:51:59 +0200 Subject: [PATCH 38/57] build: update dependencies --- package.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index e071cdfa0..d555eedc6 100644 --- a/package.json +++ b/package.json @@ -109,29 +109,29 @@ "@stripe/react-stripe-js": "~2.4.0", "@stripe/stripe-js": "~2.2.2", "@styled-system/prop-types": "~5.1.5", - "@techstack/styled-system": "~1.0.341", + "@techstack/styled-system": "~1.0.479", "@tippyjs/react": "~4.2.6", - "@vercel/analytics": "~1.2.2", + "@vercel/analytics": "~1.3.1", "babel-plugin-styled-components": "~2.1.4", "beauty-error": "~1.2.18", "cssnano": "~6.0.2", "cssnano-preset-advanced": "~6.0.2", "dlv": "~1.1.3", - "gatsby": "~5.13.1", + "gatsby": "~5.13.7", "gatsby-plugin-advanced-sitemap": "~2.1.0", - "gatsby-plugin-canonical-urls": "~5.13.0", - "gatsby-plugin-catch-links": "~5.13.0", - "gatsby-plugin-sass": "~6.13.0", - "gatsby-plugin-styled-components": "~6.13.0", - "gatsby-source-filesystem": "~5.13.0", - "gatsby-transformer-javascript-frontmatter": "~5.13.0", - "gatsby-transformer-json": "~5.13.0", - "gatsby-transformer-remark": "~6.13.0", - "gatsby-transformer-yaml": "~5.13.0", + "gatsby-plugin-canonical-urls": "~5.13.1", + "gatsby-plugin-catch-links": "~5.13.1", + "gatsby-plugin-sass": "~6.13.1", + "gatsby-plugin-styled-components": "~6.13.1", + "gatsby-source-filesystem": "~5.13.1", + "gatsby-transformer-javascript-frontmatter": "~5.13.1", + "gatsby-transformer-json": "~5.13.1", + "gatsby-transformer-remark": "~6.13.1", + "gatsby-transformer-yaml": "~5.13.1", "github-slugger": "~2.0.0", "humanize-url": "~3.0.0", "is-color": "~1.0.2", - "is-url-http": "~2.3.7", + "is-url-http": "~2.3.8", "json-future": "~2.2.21", "lodash": "~4.17.21", "mdx-scoped-runtime": "~0.8.0", @@ -139,12 +139,12 @@ "normalize.css": "~8.0.1", "path-browserify": "~1.0.1", "polished": "~4.3.1", - "postcss": "~8.4.32", + "postcss": "~8.4.39", "postcss-focus": "~7.0.0", "prepend-http": "~4.0.0", "prettier": "2", "react": "18", - "react-codecopy": "5.0.3", + "react-codecopy": "5.0.13", "react-confetti": "~6.1.0", "react-dom": "18", "react-feather": "~2.0.10", @@ -152,14 +152,14 @@ "react-timeago": "~7.2.0", "react-twitter-widgets": "~1.11.0", "remark-slug": "~7.0.1", - "sass": "~1.70.0", - "styled-components": "~6.1.6", + "sass": "~1.77.8", + "styled-components": "~6.1.11", "styled-is": "~1.3.0", "styled-system": "~5.1.5", - "swr": "~2.2.4", - "tldts": "~6.1.1", - "top-crawler-agents": "~1.0.21", - "top-user-agents": "~2.1.12", + "swr": "~2.2.5", + "tldts": "~6.1.31", + "top-crawler-agents": "~1.0.27", + "top-user-agents": "~2.1.22", "unique-random-array": "~3.0.0" }, "devDependencies": { From 07b8089f6e9ba3fb8fe7ba2d611f883104de9c58 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Tue, 16 Jul 2024 23:38:15 +0200 Subject: [PATCH 39/57] fix: user-agent script --- scripts/fetch-data/providers/fetch-user-agents.js | 11 +++++++---- src/pages/user-agents.js | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/fetch-data/providers/fetch-user-agents.js b/scripts/fetch-data/providers/fetch-user-agents.js index 0fb10f187..1842936ad 100644 --- a/scripts/fetch-data/providers/fetch-user-agents.js +++ b/scripts/fetch-data/providers/fetch-user-agents.js @@ -17,16 +17,19 @@ const fn = async () => { pkgInfo('top-user-agents'), pkgInfo('top-crawler-agents') ]) - return { - 'top-user-agents': { + + return [ + { + name: 'top-user-agents', ...npm[0], data: userAgents }, - 'top-crawler-agents': { + { + name: 'top-crawler-agents', ...npm[1], data: crawlerAgents } - } + ] } module.exports = () => diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index cdc654005..292fc1c91 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -36,7 +36,7 @@ const UserAgentsPage = () => { const [type, setType] = useState('top-user-agents') const isUserType = type === 'top-user-agents' - const { data, updatedAt, version } = userAgents[type] + const { data, updatedAt, version } = userAgents[isUserType ? 0 : 1] const githubUrl = isUserType ? 'https://github.com/microlinkhq/top-user-agents' From a42945c4a1e700ee68e9c85e29dc54e1c3596a11 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Wed, 17 Jul 2024 10:24:47 +0200 Subject: [PATCH 40/57] fix: linter --- src/pages/screenshot.js | 5 ++--- src/pages/user-agents.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 74983340a..425ad4b1d 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -179,9 +179,8 @@ const Screenshot = ({ data, cardWidth, cardHeight }) => { isLoading ? undefined : { - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - } - } + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + }} /> </Link> ) diff --git a/src/pages/user-agents.js b/src/pages/user-agents.js index 292fc1c91..ac96705f8 100644 --- a/src/pages/user-agents.js +++ b/src/pages/user-agents.js @@ -87,8 +87,7 @@ const UserAgentsPage = () => { onChange={value => setType( `top-${value === 'User Agent' ? 'user' : 'crawler'}-agents` - ) - } + )} > {['User Agent', 'Crawler Agent']} </Toggle> From a8443bbe53d84b4f7ea045b3420a2fc6f28602c9 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 18 Jul 2024 17:49:26 +0200 Subject: [PATCH 41/57] build: update dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d555eedc6..772584cd3 100644 --- a/package.json +++ b/package.json @@ -103,13 +103,13 @@ "dependencies": { "@kikobeats/use-query-state": "1.2.2", "@microlink/mql": "~0.13.6", - "@microlink/react": "5.5.18", + "@microlink/react": "5.5.22", "@microlink/recipes": "~1.8.1", "@react-spring/web": "~9.7.3", "@stripe/react-stripe-js": "~2.4.0", "@stripe/stripe-js": "~2.2.2", "@styled-system/prop-types": "~5.1.5", - "@techstack/styled-system": "~1.0.479", + "@techstack/styled-system": "~1.0.480", "@tippyjs/react": "~4.2.6", "@vercel/analytics": "~1.3.1", "babel-plugin-styled-components": "~2.1.4", @@ -153,11 +153,11 @@ "react-twitter-widgets": "~1.11.0", "remark-slug": "~7.0.1", "sass": "~1.77.8", - "styled-components": "~6.1.11", + "styled-components": "~6.1.12", "styled-is": "~1.3.0", "styled-system": "~5.1.5", "swr": "~2.2.5", - "tldts": "~6.1.31", + "tldts": "~6.1.32", "top-crawler-agents": "~1.0.27", "top-user-agents": "~2.1.22", "unique-random-array": "~3.0.0" From 18bd026d2bdc32594fb7e11331da6e877bdf3f0c Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 18 Jul 2024 19:27:03 +0200 Subject: [PATCH 42/57] build: update dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 772584cd3..c18ff87de 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "prepend-http": "~4.0.0", "prettier": "2", "react": "18", - "react-codecopy": "5.0.13", + "react-codecopy": "5.0.14", "react-confetti": "~6.1.0", "react-dom": "18", "react-feather": "~2.0.10", From d2f5f3eda955cd75c36bb708b72c852beaa7031a Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Thu, 18 Jul 2024 19:27:08 +0200 Subject: [PATCH 43/57] fix: warning --- src/components/markdown/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index c3dacf651..ab80e8b34 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -238,7 +238,7 @@ const _ImageBase = styled(ImageBase)` ` export const Image = withContainer(_ImageBase, { - maxWidth: 'inherit' + style: { maxWidth: 'inherit' } }) const StyledVideoBase = styled(VideoBase)` From de7bd52d16c97439ec95174df58fde3013a5731f Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 19 Jul 2024 10:06:02 +0200 Subject: [PATCH 44/57] refactor: don't pass down unnecessary props --- src/templates/doc/index.js | 20 ++++--- src/templates/index.js | 23 ++++---- src/templates/page.js | 104 +++++++++++++++++++------------------ 3 files changed, 76 insertions(+), 71 deletions(-) diff --git a/src/templates/doc/index.js b/src/templates/doc/index.js index 2ac5e28bd..1f8f6ec38 100644 --- a/src/templates/doc/index.js +++ b/src/templates/doc/index.js @@ -7,7 +7,15 @@ import React from 'react' import { Box, Choose, Container, Flex, Link, Text } from 'components/elements' -const DocTemplate = ({ meta, content, githubUrl, ...props }) => { +const DocTemplate = ({ + title, + date, + isPro, + meta, + content, + githubUrl, + ...props +}) => { const activeRouteName = getActiveRouteName(props.location) return ( @@ -22,7 +30,7 @@ const DocTemplate = ({ meta, content, githubUrl, ...props }) => { > <Aside activeRouteName={activeRouteName}> <Choose> - <Choose.When condition={!!meta.title}> + <Choose.When condition={!!title}> <Text as='header'> <H1 css={theme({ @@ -32,10 +40,8 @@ const DocTemplate = ({ meta, content, githubUrl, ...props }) => { variant={null} slug={false} > - <span>{meta.title}</span> - {meta.isPro && ( - <ProBadge css={theme({ top: '12px', ml: 2 })} /> - )} + <span>{title}</span> + {isPro && <ProBadge css={theme({ top: '12px', ml: 2 })} />} </H1> </Text> </Choose.When> @@ -55,7 +61,7 @@ const DocTemplate = ({ meta, content, githubUrl, ...props }) => { })} > <Text css={theme({ color: 'gray', fontSize: 0 })}> - Last edited on {formatDate(meta.date)} + Last edited on {formatDate(date)} </Text> <Link href={githubUrl} css={theme({ fontSize: 0 })}> Edit on GitHub diff --git a/src/templates/index.js b/src/templates/index.js index 7aafb58fe..5079dc9c5 100644 --- a/src/templates/index.js +++ b/src/templates/index.js @@ -9,18 +9,18 @@ import PageTemplate from './page' import DocTemplate from './doc' export const Head = ({ pageContext, location, data }) => { - const metadata = useSiteMetadata() - if (!pageContext.isDocPage) { return <Meta {...data.markdownRemark.frontmatter} /> } + const { name } = useSiteMetadata() const activeRouteName = getActiveRouteName(location) + return ( <Meta name='Microlink Docs' image={cdnUrl('banner/docs.jpeg')} - title={`${metadata.name} ${activeRouteName}: ${data.markdownRemark.frontmatter.title}`} + title={`${name} ${activeRouteName}: ${data.markdownRemark.frontmatter.title}`} date={pageContext.lastEdited} /> ) @@ -29,20 +29,13 @@ export const Head = ({ pageContext, location, data }) => { const Template = ({ pageContext, data, ...props }) => { const { isDocPage, isBlogPage, lastEdited, githubUrl } = pageContext const { frontmatter, rawMarkdownBody } = data.markdownRemark - const metadata = useSiteMetadata() - - const meta = { - ...metadata, - ...frontmatter, - url: `${metadata.siteUrl}${frontmatter.slug}`, - date: lastEdited - } + const date = frontmatter.date ?? lastEdited if (!isDocPage) { return ( <PageTemplate - meta={meta} - date={frontmatter.date && new Date(frontmatter.date)} + title={frontmatter.title} + date={date && new Date(date)} isBlogPage={isBlogPage} content={rawMarkdownBody} {...props} @@ -52,7 +45,9 @@ const Template = ({ pageContext, data, ...props }) => { return ( <DocTemplate - meta={meta} + title={frontmatter.title} + isPro={frontmatter.isPro} + date={date} content={rawMarkdownBody} githubUrl={githubUrl} {...props} diff --git a/src/templates/page.js b/src/templates/page.js index 139c76937..2b8f0ab27 100644 --- a/src/templates/page.js +++ b/src/templates/page.js @@ -7,58 +7,62 @@ import { formatDate } from 'helpers' import TimeAgo from 'react-timeago' import React from 'react' -const PageTemplate = ({ isBlogPage, date, meta, content }) => ( - <Layout {...meta}> - <Box css={theme({ px: 3 })}> - <Text - as='header' - css={theme({ - textAlign: 'center', - maxWidth: isBlogPage ? layout.normal : 'none', - mx: 'auto' - })} - > - <Flex - css={{ - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center' - }} +const PageTemplate = ({ isBlogPage, date, title, content }) => { + return ( + <Layout> + <Box css={theme({ px: 3 })}> + <Text + as='header' + css={theme({ + textAlign: 'center', + maxWidth: isBlogPage ? layout.normal : 'none', + mx: 'auto' + })} > - <Choose> - <Choose.When condition={isBlogPage}> - <H1 css={{ ...textGradient, textAlign: 'center', marginTop: 0 }}> - <PostTitle>{meta.title}</PostTitle> - </H1> - <Caption - forwardedAs='h2' - css={theme({ - color: 'black60', - textAlign: ['center', 'inherit'] - })} - > - {formatDate(date)} (<TimeAgo date={date} />) - </Caption> - </Choose.When> - <Choose.Otherwise> - <Heading - css={{ marginTop: 0, maxWidth: layout.large }} - titleize={false} - > - <PostTitle>{meta.title}</PostTitle> - </Heading> - </Choose.Otherwise> - </Choose> - </Flex> - </Text> + <Flex + css={{ + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center' + }} + > + <Choose> + <Choose.When condition={isBlogPage}> + <H1 + css={{ ...textGradient, textAlign: 'center', marginTop: 0 }} + > + <PostTitle>{title}</PostTitle> + </H1> + <Caption + forwardedAs='h2' + css={theme({ + color: 'black60', + textAlign: ['center', 'inherit'] + })} + > + {formatDate(date)} (<TimeAgo date={date} />) + </Caption> + </Choose.When> + <Choose.Otherwise> + <Heading + css={{ marginTop: 0, maxWidth: layout.large }} + titleize={false} + > + <PostTitle>{title}</PostTitle> + </Heading> + </Choose.Otherwise> + </Choose> + </Flex> + </Text> - <Box css={theme({ pt: [3, null, 4] })}> - <Markdown>{content}</Markdown> - </Box> + <Box css={theme({ pt: [3, null, 4] })}> + <Markdown>{content}</Markdown> + </Box> - {isBlogPage && <PostFooter />} - </Box> - </Layout> -) + {isBlogPage && <PostFooter />} + </Box> + </Layout> + ) +} export default PageTemplate From 9434ade5c38dac24047149bb4e78ea3957eb6741 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Fri, 19 Jul 2024 11:12:31 +0200 Subject: [PATCH 45/57] =?UTF-8?q?fix:=20as=20=E2=86=92=20forwardedAs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/changelog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/changelog.js b/src/pages/changelog.js index 864f55e10..c4b9eee3c 100644 --- a/src/pages/changelog.js +++ b/src/pages/changelog.js @@ -43,7 +43,7 @@ const ChangelogPage = () => { {changelog.map(({ date, notes }) => { return ( <Box key={date}> - <H1 as='h3'>{date}</H1> + <H1 forwardedAs='h3'>{date}</H1> <Markdown>{notes.map(note => `- ${note}`).join('\n')}</Markdown> </Box> ) From 8f1def2b93adff28ec44ea291bbf13dad3dbaafb Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 10:20:55 +0200 Subject: [PATCH 46/57] fix: button spacing --- src/pages/community.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/community.js b/src/pages/community.js index cc9373ca7..793f561a9 100644 --- a/src/pages/community.js +++ b/src/pages/community.js @@ -39,7 +39,7 @@ const CommunityPage = () => ( css={theme({ alignItems: 'center', justifyContent: 'center', - pt: [0, null, 4] + pt: 4 })} > <Chat /> From e94c4fecbb870d159a0ec5c4412027fe15181c65 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 10:31:03 +0200 Subject: [PATCH 47/57] fix: blog titles --- src/components/markdown/index.js | 14 +++++++++----- src/pages/blog/index.js | 8 +++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index ab80e8b34..38f57ea43 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -1,3 +1,4 @@ +import { commonHeadingStyles } from 'components/elements/Heading' import { withContainer, withTitle, withSlug } from 'helpers/hoc' import { space, fontSizes, colors, theme } from 'theme' import styled, { css } from 'styled-components' @@ -65,8 +66,9 @@ export const Code = withContainer(CodeEditor) export const MultiCodeEditor = withContainer(MultiCodeEditorBase) -const StyledH1 = styled(Heading)` - ${theme({ +const StyledH1 = styled(Heading)( + theme({ + ...commonHeadingStyles, maxWidth: layout.small, fontSize: `calc(${fontSizes[5]} * 0.75)`, lineHeight: [1, 2], @@ -74,10 +76,12 @@ const StyledH1 = styled(Heading)` mt: 5, mb: 4, mx: 'auto' - })} -` + }) +) -const H1Base = props => <StyledH1 forwardedAs='h1' variant={null} {...props} /> +export const H1Base = props => ( + <StyledH1 forwardedAs='h1' variant={null} {...props} /> +) export const H1 = withTitle(withSlug(H1Base)) diff --git a/src/pages/blog/index.js b/src/pages/blog/index.js index 1b2ed3fab..20854efe2 100644 --- a/src/pages/blog/index.js +++ b/src/pages/blog/index.js @@ -5,7 +5,7 @@ import { PostTitle } from 'components/pages/blog' import styled from 'styled-components' import { useBlogIndex } from 'components/hook' import { cdnUrl, formatDate } from 'helpers' -import { H1 } from 'components/markdown' +import { H1Base } from 'components/markdown' import TimeAgo from 'react-timeago' import React from 'react' @@ -49,7 +49,7 @@ const BlogPost = ({ title, date, slug, isLastPost }) => { css={{ width: '100%', letterSpacing: letterSpacings[1] }} > <BlogSeparator $isLastPost={isLastPost}> - <H1 + <H1Base forwardedAs='h3' css={theme({ mt: 0, @@ -62,11 +62,9 @@ const BlogPost = ({ title, date, slug, isLastPost }) => { layout.normal ] })} - titleize={false} - slug={false} > <PostTitle>{title}</PostTitle> - </H1> + </H1Base> <Caption forwardedAs='h4' From 4b53b6afaa96090bd57680c20ba3cc9b973b4823 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 10:40:49 +0200 Subject: [PATCH 48/57] refactor: adjust spaces --- src/components/patterns/Chat/Chat.js | 7 +++++-- src/pages/community.js | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/patterns/Chat/Chat.js b/src/components/patterns/Chat/Chat.js index 93d96778a..2c0b44061 100644 --- a/src/components/patterns/Chat/Chat.js +++ b/src/components/patterns/Chat/Chat.js @@ -12,9 +12,12 @@ const Chat = () => { 'https://join.slack.com/t/microlinkhq/shared_invite/zt-3oe805om-HzexWW5yQNcF6cJs3dFM_A', '_blank', 'noopener noreferrer' - )} + ) + } > - <Caps css={theme({ px: 3, py: 2 })}>Join in the community</Caps> + <Caps css={theme({ fontSize: 0, px: 3, py: 2 })}> + Join in the community + </Caps> </Button> </Flex> ) diff --git a/src/pages/community.js b/src/pages/community.js index 793f561a9..260e9003d 100644 --- a/src/pages/community.js +++ b/src/pages/community.js @@ -39,7 +39,8 @@ const CommunityPage = () => ( css={theme({ alignItems: 'center', justifyContent: 'center', - pt: 4 + pt: [3, null, 4], + mt: 3 })} > <Chat /> From ab16b3f9e2fb07d5352be4218d406a07c5df3839 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 10:59:40 +0200 Subject: [PATCH 49/57] fix: card size --- src/pages/meta.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/meta.js b/src/pages/meta.js index 19ea9290c..28c5c290c 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -122,7 +122,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const [ClipboardComponent, toClipboard] = useClipboard() const size = useWindowSize() - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 3 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio From d2f62c92efa361ede3d721b34221e6f52440e128 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 12:29:46 +0200 Subject: [PATCH 50/57] fix: css syntax --- src/components/elements/Unavatar/Unavatar.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/elements/Unavatar/Unavatar.js b/src/components/elements/Unavatar/Unavatar.js index a8525b40b..a541ca66d 100644 --- a/src/components/elements/Unavatar/Unavatar.js +++ b/src/components/elements/Unavatar/Unavatar.js @@ -5,10 +5,8 @@ import { theme } from 'theme' const StyledImage = styled(Image)` max-width: inherit; - height: '100%' - ${theme({ - borderRadius: 2 - })}; + height: 100%; + ${theme({ borderRadius: 2 })}; ` const Unavatar = ({ query, ...props }) => { From d2834dc0d036a9db3787c0b8ecfba5c50e1a378d Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:18:53 +0200 Subject: [PATCH 51/57] refactor: adjust max-width --- src/components/elements/Iframe/Iframe.js | 5 +- src/components/elements/Input/InputIcon.js | 3 +- src/helpers/hoc/with-lazy.js | 13 +++-- src/pages/insights.js | 32 ++++++++---- src/pages/meta.js | 13 +++-- src/pages/pdf.js | 23 ++++++--- src/pages/screenshot.js | 57 +++++++++++++--------- 7 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/components/elements/Iframe/Iframe.js b/src/components/elements/Iframe/Iframe.js index a45d81c9e..60cf59a31 100644 --- a/src/components/elements/Iframe/Iframe.js +++ b/src/components/elements/Iframe/Iframe.js @@ -7,6 +7,7 @@ import Flex from '../Flex' const Iframe = ({ loading = true, + maxWidth, width = aspectRatio.width, height = aspectRatio.height, onLoad = noop, @@ -38,13 +39,13 @@ const Iframe = ({ style={isLoading ? { display: 'none' } : undefined} frameBorder='0' target='_parent' - css={theme({ width, height })} + css={theme({ maxWidth, width, height })} {...props} /> ) return isLoading - ? createElement(Placeholder, { width, height, ...props }, iframe) + ? createElement(Placeholder, { width, height, maxWidth, ...props }, iframe) : iframe } diff --git a/src/components/elements/Input/InputIcon.js b/src/components/elements/Input/InputIcon.js index 0259363f6..8fd41b9c8 100644 --- a/src/components/elements/Input/InputIcon.js +++ b/src/components/elements/Input/InputIcon.js @@ -6,10 +6,11 @@ import { colors } from 'theme' const InputIcon = React.memo(function InputIcon ({ height = '24px', width = height, + style, ...props }) { return props.query || props.url - ? createElement(Unavatar, { height, width, ...props }) + ? createElement(Unavatar, { style: { ...style, height, width }, ...props }) : createElement(LinkIcon, { color: colors.black50, size: '16px' }) }) diff --git a/src/helpers/hoc/with-lazy.js b/src/helpers/hoc/with-lazy.js index 72b4c1729..e2f9778b5 100644 --- a/src/helpers/hoc/with-lazy.js +++ b/src/helpers/hoc/with-lazy.js @@ -8,13 +8,12 @@ const compute = (obj, key, value) => const isDataURI = (str = '') => str.startsWith('data:') -const computedProps = (attr, compiledAttr, props, { isLoading }) => ({ - ...props, - [attr]: compiledAttr, - height: compute(props, 'height', isLoading), - width: compute(props, 'width', isLoading) || aspectRatio.width, - style: compute(props, 'style', isLoading) -}) +const computedProps = (attr, compiledAttr, props, { isLoading }) => { + const style = compute(props, 'style', isLoading) + const height = compute(props, 'height', isLoading) + const width = compute(props, 'width', isLoading) || aspectRatio.width + return { ...props, [attr]: compiledAttr, style: { height, width, ...style } } +} export const withLazy = (Component, { tagName = 'img', attr = 'src' } = {}) => { const LazyWrapper = componentProps => { diff --git a/src/pages/insights.js b/src/pages/insights.js index 5c57816c9..16a45ff0c 100644 --- a/src/pages/insights.js +++ b/src/pages/insights.js @@ -161,7 +161,7 @@ const TechnologyStack = ({ technologies }) => ( </Flex> ) -const LighthousePlaceholder = ({ height, width }) => { +const LighthousePlaceholder = props => { return ( <Flex css={theme({ @@ -169,10 +169,9 @@ const LighthousePlaceholder = ({ height, width }) => { borderColor: 'black20', alignItems: 'center', flexDirection: 'column', - justifyContent: 'center', - height, - width + justifyContent: 'center' })} + {...props} > <Image css={theme({ width: [3, 3, '80%', '80%'] })} @@ -203,7 +202,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const size = useWindowSize() const technologies = get(data, 'insights.technologies') - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.2 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio @@ -318,7 +317,11 @@ const LiveDemo = React.memo(function LiveDemo ({ <Box as='section' id='technology-stack' - css={{ width: cardWidth, flexDirection: 'column' }} + css={{ + width: cardWidth, + maxWidth: layout.normal, + flexDirection: 'column' + }} > <Box css={theme({ pt: 4 })}> <TechnologyStack technologies={technologies} /> @@ -359,9 +362,14 @@ const LiveDemo = React.memo(function LiveDemo ({ <Box as='section' id='lighthouse-report' - css={theme({ width: cardWidth, pt: 5 })} + css={theme({ width: cardWidth, maxWidth: layout.normal, pt: 5 })} > - <LighthouseReport width={528} src={reportUrl} /> + <LighthouseReport + maxWidth={layout.normal} + width={cardWidth} + height={cardHeight} + src={reportUrl} + /> <Box css={theme({ pt: [2, 2, 3, 3], mx: 'auto' })}> <Tooltip type='copy' @@ -391,7 +399,13 @@ const LiveDemo = React.memo(function LiveDemo ({ </Box> </Choose.When> <Choose.Otherwise> - <LighthousePlaceholder height={cardHeight} width={cardWidth} /> + <LighthousePlaceholder + style={{ + height: cardHeight, + width: cardWidth, + maxWidth: layout.normal + }} + /> </Choose.Otherwise> </Choose> <ClipboardComponent /> diff --git a/src/pages/meta.js b/src/pages/meta.js index 28c5c290c..805d9df2f 100644 --- a/src/pages/meta.js +++ b/src/pages/meta.js @@ -122,7 +122,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const [ClipboardComponent, toClipboard] = useClipboard() const size = useWindowSize() - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 3 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.2 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio @@ -254,12 +254,19 @@ const LiveDemo = React.memo(function LiveDemo ({ </Hide> <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> <CodeEditor - css={theme({ pb: 4, width: cardWidth, height: cardHeight })} + css={theme({ + pb: 4, + width: cardWidth, + height: cardHeight, + maxWidth: layout.normal + })} language='json' > {JSON.stringify(jsonData, null, 2)} </CodeEditor> - <Box css={theme({ pt: 4, width: cardWidth })}> + <Box + css={theme({ pt: 4, width: cardWidth, maxWidth: layout.normal })} + > <Tooltip type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} diff --git a/src/pages/pdf.js b/src/pages/pdf.js index 321d20faf..3bcbbd6ce 100644 --- a/src/pages/pdf.js +++ b/src/pages/pdf.js @@ -61,7 +61,7 @@ const SUGGESTIONS = [ const getEmbedUrl = url => getApiUrl(url, { pdf: true, embed: 'pdf.url' })[0] -const PDFPlaceholder = ({ height, width }) => { +const PDFPlaceholder = props => { return ( <Flex css={theme({ @@ -69,10 +69,9 @@ const PDFPlaceholder = ({ height, width }) => { borderColor: 'black20', alignItems: 'center', flexDirection: 'column', - justifyContent: 'center', - height, - width + justifyContent: 'center' })} + {...props} > <Image css={theme({ width: [3, 3, '60%', '60%'] })} @@ -104,7 +103,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const size = useWindowSize() const dataPdfUrl = get(data, 'pdf.url') - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.16 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.2 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio @@ -134,6 +133,7 @@ const LiveDemo = React.memo(function LiveDemo ({ PDF made simple </Heading> <Caption + titleize={false} forwardedAs='h2' css={theme({ pt: [3, 3, 4, 4], @@ -254,11 +254,14 @@ const LiveDemo = React.memo(function LiveDemo ({ <Choose.When condition={!!dataPdfUrl}> <Flex css={{ flexDirection: 'column', alignItems: 'center' }}> <Iframe + maxWidth={layout.normal} width={cardWidth} height={cardHeight} src={`https://docs.google.com/viewer?url=${dataPdfUrl}&embedded=true`} /> - <Box css={theme({ mt: 4, px: 4, width: cardWidth })}> + <Box + css={theme({ pt: 4, width: cardWidth, maxWidth: layout.normal })} + > <Tooltip type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} @@ -284,7 +287,13 @@ const LiveDemo = React.memo(function LiveDemo ({ </Flex> </Choose.When> <Choose.Otherwise> - <PDFPlaceholder height={cardHeight} width={cardWidth} /> + <PDFPlaceholder + style={{ + height: cardHeight, + width: cardWidth, + maxWidth: layout.normal + }} + /> </Choose.Otherwise> </Choose> <ClipboardComponent /> diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 425ad4b1d..158a9792d 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -119,7 +119,7 @@ const fromCache = (variations, opts) => { const getEmbedUrl = ({ url, ...opts }) => getApiUrl(url, { ...opts, screenshot: true, embed: 'screenshot.url' })[0] -const DemoSlider = ({ height, width }) => { +const DemoSlider = props => { const [index, setIndex] = useState(0) const next = index => ++index % SUGGESTIONS.length @@ -135,8 +135,8 @@ const DemoSlider = ({ height, width }) => { }) return ( - <Box css={theme({ pt: 2 })}> - <Flex css={{ position: 'relative', height, width }}> + <Box css={theme({ pt: 3 })}> + <Flex css={{ position: 'relative' }} {...props}> {transitions((style, index) => { const url = SUGGESTIONS[index].cdnUrl const src = url @@ -155,33 +155,35 @@ const DemoSlider = ({ height, width }) => { ) } -const Screenshot = ({ data, cardWidth, cardHeight }) => { +const Screenshot = ({ data, style }) => { const imageUrl = get(data, 'screenshot.url') + const imageStyle = { objectFit: 'contain', ...style } return ( <Link px={3} href={imageUrl} icon={false}> - <Image - alt={`Microlink screenshot for ${data.url}`} + <Box css={theme({ my: 4, px: 0, - height: cardHeight, - width: cardWidth, border: 1, borderColor: 'black05', borderRadius: 3 })} - key={imageUrl} - src={imageUrl} - height={cardHeight} - width={cardWidth} - style={isLoading => - isLoading - ? undefined - : { + > + <Image + alt={`Microlink screenshot for ${data.url}`} + key={imageUrl} + src={imageUrl} + style={isLoading => + isLoading + ? imageStyle + : { + ...imageStyle, filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - }} - /> + } + } + /> + </Box> </Link> ) } @@ -196,7 +198,7 @@ const LiveDemo = React.memo(function LiveDemo ({ const [ClipboardComponent, toClipboard] = useClipboard() const size = useWindowSize() - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2 + const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.2 const cardWidth = size.width / cardBase const cardHeight = cardWidth / Card.ratio @@ -349,11 +351,14 @@ const LiveDemo = React.memo(function LiveDemo ({ })} > <Screenshot - cardWidth={cardWidth} - cardHeight={cardHeight} + style={{ + maxWidth: layout.normal, + width: cardWidth, + height: cardHeight + }} data={data} /> - <Box css={theme({ px: 4 })} style={{ width: cardWidth / 1.5 }}> + <Box css={theme({ width: cardWidth, maxWidth: layout.normal })}> <Tooltip type='copy' tooltipsOpts={Tooltip.TEXT.OPTIONS} @@ -379,7 +384,13 @@ const LiveDemo = React.memo(function LiveDemo ({ </Flex> </Choose.When> <Choose.Otherwise> - <DemoSlider height={cardHeight} width={cardWidth} /> + <DemoSlider + css={{ + height: cardHeight, + width: cardWidth, + maxWidth: layout.normal + }} + /> </Choose.Otherwise> </Choose> <ClipboardComponent /> From 1c24b9e7c435c887ab80f05f1ec7f1e9d0af6002 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:20:54 +0200 Subject: [PATCH 52/57] chore(storybook): disable telemetry --- .storybook/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.storybook/main.js b/.storybook/main.js index 2989e3bbc..cb59b9baf 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -5,7 +5,8 @@ module.exports = { addons: ['@storybook/addon-a11y', '@storybook/addon-essentials'], framework: '@storybook/react', core: { - builder: 'webpack5' + builder: 'webpack5', + disableTelemetry: true }, webpackFinal: async config => { // Remove core-js to prevent issues with Storybook From 0426e34afd9535ce920e5b80d57fb968eadad66f Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:26:26 +0200 Subject: [PATCH 53/57] chore: remove MQLEditor component not used --- .../patterns/MQLEditor/MQLEditor.js | 162 - src/components/patterns/MQLEditor/code.js | 42 - src/components/patterns/MQLEditor/data.js | 5249 ----------------- src/components/patterns/MQLEditor/html.js | 33 - src/components/patterns/MQLEditor/json.js | 5 - src/components/patterns/index.js | 2 - 6 files changed, 5493 deletions(-) delete mode 100644 src/components/patterns/MQLEditor/MQLEditor.js delete mode 100644 src/components/patterns/MQLEditor/code.js delete mode 100644 src/components/patterns/MQLEditor/data.js delete mode 100644 src/components/patterns/MQLEditor/html.js delete mode 100644 src/components/patterns/MQLEditor/json.js diff --git a/src/components/patterns/MQLEditor/MQLEditor.js b/src/components/patterns/MQLEditor/MQLEditor.js deleted file mode 100644 index 292647094..000000000 --- a/src/components/patterns/MQLEditor/MQLEditor.js +++ /dev/null @@ -1,162 +0,0 @@ -import { useWindowSize } from 'components/hook' -import { shadows, breakpoints, theme } from 'theme' -import Microlink from '@microlink/react' -import React, { useState } from 'react' -import styled from 'styled-components' -import { match } from 'styled-is' -import { mqlCode } from 'helpers' - -import { - Choose, - CodeEditor, - MultiCodeEditor, - Card, - Box, - Flex, - Iframe -} from 'components/elements' - -import * as code from './code' -import * as data from './data' -import * as html from './html' -import * as json from './json' - -const TYPES = ['meta', 'iframe', 'screenshot', 'pdf', 'insights'] -const MODES = ['preview', 'html', 'json', 'code'] -const SMALL_BREAKPOINT = Number(breakpoints[0].replace('px', '')) - -const MicrolinkCard = styled(Microlink)` - --microlink-hover-background-color: white; - width: 100%; - - @media screen and (max-width: ${breakpoints[1]}) { - .microlink_card__content { - display: none; - } - } -` - -const MQLCard = styled(Card)` - &:hover { - box-shadow: ${shadows[0]}; - } - - ${match('type', 'screenshot')` - ${match('mode', 'preview')` - background-image: url("${data.screenshotUrl}"); - background-size: cover; - background-position: center; - box-shadow: none; - - &:hover { - box-shadow: none; - } - `} - `}; - - ${match('type', 'iframe')` - ${match('mode', 'preview')` - display: flex; - justify-content: center; - background-color: transparent; - box-shadow: none; - &:hover { - box-shadow: none; - } - `} - `}; -` - -const MQLEditor = props => { - const size = useWindowSize() - - const [mode, setMode] = useState(MODES[0]) - const [type, setType] = useState(TYPES[0]) - - const cardBase = size.width < SMALL_BREAKPOINT ? 1.2 : 2.2 - const cardWidth = size.width / cardBase - const cardHeight = cardWidth / Card.ratio - - return ( - <Flex - alignItems='center' - justifyContent='center' - flexDirection='column' - {...props} - > - <Choose> - <MQLCard width={cardWidth} height={cardHeight} mode={mode} type={type}> - <Choose.When condition={mode === 'preview'}> - <Choose> - <Choose.When condition={type === 'pdf'}> - <Iframe src={data.pdfUrl} /> - </Choose.When> - <Choose.When condition={type === 'insights'}> - <Iframe src={data.insightsUrl} /> - </Choose.When> - <Choose.When condition={type === 'meta' || type === 'iframe'}> - <MicrolinkCard - key={type} - fetchData={false} - media={type === 'iframe' ? 'iframe' : 'video'} - style={{ border: '0', height: 'inherit', maxWidth: '100%' }} - url={data[type] && data[type].url} - setData={data[type]} - size='large' - /> - </Choose.When> - </Choose> - </Choose.When> - <Choose.When condition={mode === 'json'}> - <CodeEditor width='100%' language='json'> - {mqlCode.json(data[type], json[type])} - </CodeEditor> - </Choose.When> - <Choose.When condition={mode === 'html'}> - <CodeEditor width='100%' language='html'> - {html[type](data[type])} - </CodeEditor> - </Choose.When> - <Choose.When condition={mode === 'code'}> - <MultiCodeEditor width='100%' languages={code[type]} /> - </Choose.When> - </MQLCard> - </Choose> - <Flex - css={theme({ - width: '100%', - pl: '15px', - pr: '7px', - alignItems: ['center', 'center', undefined, undefined], - justifyContent: 'space-between', - flexDirection: ['column', 'column', 'row', 'row'] - })} - > - <Box css={theme({ pt: [5, 5, 4, 4] })}> - {MODES.map(children => ( - <Card.Option - key={children} - value={mode} - onClick={() => setMode(children)} - > - {children} - </Card.Option> - ))} - </Box> - <Box css={theme({ pt: [3, 3, 4, 4] })}> - {TYPES.map(children => ( - <Card.Option - key={children} - value={type} - onClick={() => setType(children)} - > - {children} - </Card.Option> - ))} - </Box> - </Flex> - </Flex> - ) -} - -export default MQLEditor diff --git a/src/components/patterns/MQLEditor/code.js b/src/components/patterns/MQLEditor/code.js deleted file mode 100644 index 797447c04..000000000 --- a/src/components/patterns/MQLEditor/code.js +++ /dev/null @@ -1,42 +0,0 @@ -import { mqlCode } from 'helpers' - -import * as data from './data' - -export const meta = mqlCode(data.meta.url, { - data: { - audio: true, - video: true, - meta: true - } -}) - -export const iframe = mqlCode(data.iframe.url, { - data: { - iframe: { - maxWidth: 350 - } - } -}) - -export const pdf = mqlCode(data.pdf.url, { - pdf: { - format: 'A4', - margin: '0.35cm', - scale: 0.6 - }, - meta: false -}) - -export const screenshot = mqlCode(data.screenshot.url, { - screenshot: { - overlay: { - browser: 'dark' - } - } -}) - -export const insights = mqlCode(data.insights.url, { - insights: { - lighthouse: true - } -}) diff --git a/src/components/patterns/MQLEditor/data.js b/src/components/patterns/MQLEditor/data.js deleted file mode 100644 index b838260dd..000000000 --- a/src/components/patterns/MQLEditor/data.js +++ /dev/null @@ -1,5249 +0,0 @@ -import demoLinks from '../../../../data/demo-links.json' - -export const screenshotUrl = - 'https://cdn.microlink.io/screenshot/browser/dark/apple.png' - -export const pdfUrl = 'https://cdn.microlink.io/mqleditor/file.pdf' - -export const insightsUrl = - 'https://lighthouse.microlink.io/?url=https://cdn.microlink.io/mqleditor/insights.json' - -export const meta = demoLinks.find(({ id }) => id === 'twitter').data - -export const iframe = { - iframe: { - html: - '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">These tires can even climb stairs <a href="https://t.co/ymr4KK15oI">pic.twitter.com/ymr4KK15oI</a></p>— Futurism (@futurism) <a href="https://twitter.com/futurism/status/882987478541533189?ref_src=twsrc%5Etfw">July 6, 2017</a></blockquote>\n<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>\n', - scripts: [ - { - async: true, - src: 'https://platform.twitter.com/widgets.js', - charset: 'utf-8' - } - ] - }, - url: 'https://twitter.com/futurism/status/882987478541533189' -} - -export const screenshot = { - screenshot: { - url: screenshotUrl, - type: 'png', - size: 1388551, - height: 1910, - width: 2776, - size_pretty: '1.39 MB' - }, - url: 'https://apple.com/music' -} - -export const pdf = { - pdf: { - size_pretty: '356 kB', - size: 356141, - type: 'pdf', - url: pdfUrl - }, - url: 'https://rauchg.com/2014/7-principles-of-rich-web-applications' -} - -export const insights = { - insights: { - userAgent: - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/84.0.4147.0 Safari/537.36', - environment: { - networkUserAgent: - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Safari/537.36 Chrome-Lighthouse', - hostUserAgent: - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/84.0.4147.0 Safari/537.36', - benchmarkIndex: 954 - }, - lighthouseVersion: '6.1.1', - fetchTime: '2020-07-19T16:38:13.954Z', - requestedUrl: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - finalUrl: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - runWarnings: [], - audits: { - 'is-on-https': { - id: 'is-on-https', - title: 'Uses HTTPS', - description: - "All sites should be protected with HTTPS, even ones that don't handle sensitive data. This includes avoiding [mixed content](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/what-is-mixed-content), where some resources are loaded over HTTP despite the initial request being servedover HTTPS. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more](https://web.dev/is-on-https/).", - score: 1, - scoreDisplayMode: 'binary', - displayValue: '', - details: { type: 'table', headings: [], items: [] } - }, - viewport: { - id: 'viewport', - title: - 'Does not have a `<meta name="viewport">` tag with `width` or `initial-scale`', - description: - 'Add a `<meta name="viewport">` tag to optimize your app for mobile screens. [Learn more](https://web.dev/viewport/).', - score: 0, - scoreDisplayMode: 'binary', - explanation: 'No `<meta name="viewport">` tag found' - }, - 'first-contentful-paint': { - id: 'first-contentful-paint', - title: 'First Contentful Paint', - description: - 'First Contentful Paint marks the time at which the first text or image is painted. [Learn more](https://web.dev/first-contentful-paint/).', - score: 0.78, - scoreDisplayMode: 'numeric', - numericValue: 1162.56, - numericUnit: 'millisecond', - displayValue: '1.2 s' - }, - 'largest-contentful-paint': { - id: 'largest-contentful-paint', - title: 'Largest Contentful Paint', - description: - 'Largest Contentful Paint marks the time at which the largest text or image is painted. [Learn More](https://web.dev/lighthouse-largest-contentful-paint/)', - score: 0.9, - scoreDisplayMode: 'numeric', - numericValue: 1215.06, - numericUnit: 'millisecond', - displayValue: '1.2 s' - }, - 'first-meaningful-paint': { - id: 'first-meaningful-paint', - title: 'First Meaningful Paint', - description: - 'First Meaningful Paint measures when the primary content of a page is visible. [Learn more](https://web.dev/first-meaningful-paint/).', - score: 0.74, - scoreDisplayMode: 'numeric', - numericValue: 1215.06, - numericUnit: 'millisecond', - displayValue: '1.2 s' - }, - 'speed-index': { - id: 'speed-index', - title: 'Speed Index', - description: - 'Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://web.dev/speed-index/).', - score: 0.89, - scoreDisplayMode: 'numeric', - numericValue: 1346.358482898538, - numericUnit: 'millisecond', - displayValue: '1.3 s' - }, - 'screenshot-thumbnails': { - id: 'screenshot-thumbnails', - title: 'Screenshot Thumbnails', - description: 'This is what the load of your site looked like.', - score: null, - scoreDisplayMode: 'informative', - details: { - type: 'filmstrip', - scale: 3000, - items: [ - { - timing: 300, - timestamp: 272095654750, - data: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRQBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEIAFMAeAMBEQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1ToAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//Z' - }, - { - timing: 600, - timestamp: 272095954750, - data: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRQBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEIAFMAeAMBEQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APmRP2hPFpQeXpWjlQAu9NPAzjpkg5J45J685zX2zzGu3dRX4/5nwSwVJK3MRN+0B4ojmWR9O0oNnIV7Q7cj/ZL4PX09Kl5jXX2V+P8AmCwVJ9fwPef2OptQ/aP+IOseFtXt7eK2s9Fk1GIaVEltK8q3FvHhpGST5dsr/wAOc45xkHGtmtelHmSX4/5nXhsupVpOMm/w/wAj60v/ANlKyjv7yC38NeILmW3kt/JklvLCO3ukeWNZpEYW7EeUryOVkVC+wKqnLFeL+3MT1iv/ACb/AOSPS/sTDdJP/wAl/wDkSxH+yRYrf3jNofiFVhkuEgdL3TilxEqxhW2mAbXk8yXaCOPKyzJuU0v7bxP8sf8Ayb/5IP7Ew/8ANL8P8jS079i3wtrdol3fDxPpN03DWsk9plRjjPlRFc464zyDy33jcc9xK+zH7n/mQ8jw7fxP8P8AIs/8ML+C/wDoI+JP+/8AB/8AGKr+3sT/ACx+4X9hYf8Aml94f8ML+C/+gj4k/wC/8H/xij+3sT/LH7g/sLD/AM0vvD/hhfwX/wBBHxJ/3/g/+MUf29if5Y/cH9hYf+aX3h/wwv4L/wCgj4k/7/wf/GKP7exP8sfuD+wsP/NL7w/4YX8F/wDQR8Sf9/4P/jFH9vYn+WP3B/YWH/ml94f8ML+C/wDoI+JP+/8AB/8AGKP7exP8sfuD+wsP/NL7w/4YX8F/9BHxJ/3/AIP/AIxR/b2J/lj9wf2Fh/5pfeWbf9ibwhaxlI7/AMQYLbiXa2Y9uMmA8cDjpWbzzEv7Mfuf+ZayTDr7Uvw/yB/2JvB7XLz/AG7XldjuwrW20H2H2fA60PPMU/sx/wDJv/kh/wBiYf8Aml+H+R+LsEqKTuMRIx8soJB59vxq4ySuec4t9CSW5UoqKLYqSN3lxkHA4x2+v+TV8yewuVo+xv8AglQwH7QHixmXK/8ACH3hKxllOPtdnwCMsD7jn0rysfPkpOa6Hp4HSb9D9HJfFemX2NPuBMouJWkU2+sXu5/3uNquqjPMp/dg4C+X/CF2/JvMGvs/ievGvzR5rDrnx/ocGp2ttd3cMLs8dwxj1ufCN5cAXdgAbCJejEKx2HBZztX9ot/Z/EuNXmSdjp4dOs4JQ4/tByIPs2JNVuHUpt25KlyC2P48biec55qP7Tf8n4lc7CfT7K4Rlf8AtABpPNymqXKkNlzwQ4IH7xvlHGAoxhVAP7Tf8v4hzsf9ktPsklvtvjHIoVidSuN+PL8vh9+4cc5B+9833uaP7Tf8v4hzsh/sqx2QLnU8QrsU/wBsXWSOPvHzMseBy2T19TR/ab/l/EOdlyyMFhM0sSXLOQw/f3ksoAZy5wHJA5Y9OgAUcAAH9pv+X8Q52Xv7Z/6Y/wDj3/1qP7Tf8v4hzsP7Z/6Y/wDj3/1qP7Tf8v4hzsP7Z/6Y/wDj3/1qP7Tf8v4hzsP7Z/6Y/wDj3/1qP7Tf8v4hzsdFqvmyKnlY3EDO7p+la08wc5qHLu+4c7Z/Ok0eRu8tGBHUvzX3lm/s3PlNP5gVRuOFCk44FPlfYi/mfaX/AASk3p+0N4p2xNM48I3eI4yNzf6XZ8AkgZ+pA9xXm4+HPScH1PSwP8R+h+mCW0lpKtxD4Z1VZGDK/k/YFaPLMeSZe+A3BP8ArB33bfl/7Pj/ADHsqkkrF/UI5t5j/sXU7poP3sUkRtchg5XKbpBhipLZIHy5H3srR/Z8f5mNQSSRd0ZJNRVhc6XfaWyAbftjQkyepHlSPjHvjrxmp/s2P8zHyGn/AGPF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcgf2PF/eNH9mx/nYcg5NJjjdWDHKkGrhl8YSUuZ6Byn85oRCwyWA74/wD1/SvuOWLPlVKS2EAA4BJHvSSS2E3fU+0P+CU0Zm/aB8VRgBi/hC7XDOUBzd2fG4cr9R0rz8eoulaWx6GB/iP0P08m0q6cLMLKzF4wKMo1udVwGbbgiLk4Cc7QRlhkgAt8r7DA7XX3/wDBPZ5YWJb7TPMYj7Pam1dV/etq8qMVEmCcBOvlktkHlvlJwd4r6tgu6+//AII7RJo1vizD7Fpvljdsf+0pCWHO0keVxnjPJxz1pfVsF3X3/wDBC0TY+y2H95f+/lH1bBd19/8AwQtEPsth/eX/AL+UfVsF3X3/APBC0Q+y2H95f+/lH1bBd19//BC0Q+y2H95f+/lH1bBd19//AAQtEPsth/eX/v5R9WwXdff/AMELRD7LYf3l/wC/lH1bBd19/wDwQtEPsth/eX/v5R9WwXdff/wQtEPsth/eX/v5R9WwXdff/wAELRHJbWYdSjLuBGPnzzVwoYSMk4PX1GlFH859fbnyYUAfZf8AwSujil+PXi5J/J8hvB14sn2kZj2G6s924dxjORXnY7lVK8tj0sD/ABH6H6aT6b4Ykm+0BtCPkRsbhpIMsIQXZ/m3/KBKN5yCPlYdTuHyvPgv6uewnTtpsH2PQijWV7c6JPqd4BDOotWUXJQLhdhlJbaGXgk4DClzYHt+DGuVbG1b2aQFkMtsIFcCKOOGVdkYH3D85Gc45AAx/DS58B2/BjvEv+Xpv+1/309LnwHb8GF4h5em/wC1/wB9PRz4Dt+DC8Q8vTf9r/vp6OfAdvwYXiHl6b/tf99PRz4Dt+DC8Q8vTf8Aa/76ejnwHb8GF4h5em/7X/fT0c+A7fgwvEPL03/a/wC+no58B2/BheIeXpv+1/309HPgO34MLxHwpp/mps3b8jGWfrWlOWC50oLX0YXR/OpX3R8mFAH2h/wSkcx/tB+KGWKSZl8I3ZEURAdz9rs+BuIGT7kD3rzsdD2lLlfU9HA61GvI/TmbTrd1h83wnfTK3mQs8hsz5cbx73LEzfdZiYyBnLA5G3DH5j+z4d2ez7KPLy3JZdLtXlubo+HLua6gEkiOBbB7l9x+6TIBuPkQkF9uA0WSMNtP7Ph3f4F8q7mi8TLPaRrp99Kk4YyTK8O2DHTf8+Tu7bA3vip/s2n3f4ByLuVbue4t7KSePw/q11Kk5hFtDJaiRlGcSgtMF2n0LBuRlRR/ZtPu/wAA5F3J7QPcGES6TqFoZFJImktztO/btO2Q84+fjI2jru+WhZbT6yYnFGl/ZEJPDv8ATI/wo/s6n3Y+RC/2PF/ef9KP7Np93+Aci7h/Y8X95/0o/s2n3f4ByLuH9jxf3n/Sj+zafd/gHIu4f2PF/ef9KP7Np93+Aci7h/Y8X95/0o/s2n3f4ByLuOj0qOKRXDOSpzzVwwEISU03p6ByrufznV9ufJBQB9kf8EtIo5vjr4wjmjSWJ/Bt4rxyW7XCsDdWeQYl5kB7oOvTvXFi/gXqelgf4j9D9Tf+ET0Z4bS0udN0eZEQxJCumqoAZgX2gltoOxcj1UEnjjyT3inceGPC0tqy3Wl+HRBDJP8AK+nIyI7D943OACyqu71xjJoAfL4T0qWGd5bfQpYllubiQyaUG/eyvjzD8/3iodXOPnJDfKBggG3YaZp9vfmaOCyEsvzRNBbBHChET5myc8Ko7cBR2oAnuvDek3qsLnTLO4DRGBvOgVy0ZySpyOQcnI75NAE9hpVlpX2j7FZwWn2iVp5vIjVPMkb7ztgcse5PNAFugAoAKACgAoAKAP5v6+jPjwoA+zv+CU13b6f+0D4qurueO1tYPCF3LNPMwVI0W7syzMTwAACSTXFivgXqejgf4j9D9KLPxeZ9lxHqGrXE37rGm/adJzLuwByrfxGJgcP1lYL0GzyT3zatE1mVImca6jlEjxdDT+CQAZGMeeR5eTjIzNwrAYQAy4IPEc7SpJP4wtUZQFeU6OcYQ5xtBOScdf4sdBmgDcWHU5dib9bt/KtXQyH7B++f5lDHAOHG0OMAJ84yD8ygApzJrW6O4C+IsSRkG0jOm/u2ZZGySeuw7VHzEE7MhhvagC7YNqqKhnh1ibbmTbcGyySZfuHYR91VyCMfK/JLcKARQS6xErStBr0xud5EDnTwbTk4GQRn7oxy/DDdznAAxrjVoIWmFjr8rSSYW2D6fmEFEOQSwGAdw6k7t/VdhoA14NZvZPsgbQNQiE2A5eS3/cfKp+fbKe7EfJu5Ru20sARnxBfizkm/4RrUzKoUrbiW13vnOQD523K4GckfeGM84AJrjWbyBWK6HfTkNKuI5IOQqkqwzIOHICr3BI3BRkgAjj12/doAfDuooHKhy0tt+7yqEk4m52l2Bxn/AFT4yNm8A/nZr6M+PCgD7S/4JPhm/aH8TBCyufCN0AUxuB+12fTPGfrxXFi/gXqejgf4j9D9OW1TXRZzWw0nxKZJnKrehtM8yANk7lHmbSF6YKMTgcHk15J74n2jXI7RD5PiaWXy2yoOl79xYEA8hcgDaO2GOcnBABNYSa0ly8cqeIWjilZvNuf7O2zKAqbQI/m2ncZBkA5QgkDajAFuw0fVLmxKS6/rNvIHUiWWKy8xhtJIwsRXGX2ngHMYxwSWANJtKumFyBrN6vmqyoQkGYSSxBT93yRuAG7cMIucncSALPpl1NNE66vdwqhJaOOOHa+QeDmMnAyDwQflGSecgC/2Xc74m/te8wiFGXZDhzgfMf3ecjB6YHzHjpgAg/sS+8op/wAJDqOSuBJ5dtuB8oJn/U4zuBk6feOPufJQBbvLG4ubd44tRuLV2JIliSMsgwRgbkI64PIPSgCnc6HfTwyJH4i1G3ZiSJI4rYsmVUYG6EjgqW5B5Zs5GAACa70m6uYnSPWr61ZujwpASvyFeN0RHU7+R94D+H5aANIUAfzgV9GfHhQB9h/8EurE6h8d/FMQedGXwncSKbWTy5Cy3lmQFbco5OOCdp6NwTXFi/gXqelgf4j9D9PLP4aLY3r3Fjr2u2/nLOWjkvWukEkgXEgE7Sbdu3KIuIxk5U5ry+Vdz2ufyZVi+HNyWtpD4j8SNsvYLlkknhIdoXbO7H/LKbcGZAcYChVj5Wiy7jUm+jKlj8EZF06aJvG/i5Guki3LPqQaWFQsgKKy5ClvNbcynOVQqw8tMSWax+EyiwitU8T66m2VJDN9ud5HxIHKEsT8rAbSBj5SQu3rQBVb4PP/AGpJep428RxgoEW1+1q0Ma+akvCspyTs2lmydjMucbcAHYW+hy29tDHNqBupERUaeaNQ8hAxuO3C5PXAAHoAOKAJTo7DrcIPrH/9egAGjselwh/7Z/8A16AA6O463CD/ALZ//XoABo7HpcJ/37/+vQAn9kNz/pCccH93/wDXoAP7IPP+kpx1/d//AGVAH86tfRnx4UAfZH/BLOGO4+O3i+GaNJYZPB14jxyKGV1N3Zggg8EEcYrixXwr1PSwH8R+h+gV14s1W61S+SW5V/J0u4CMYU3qGt0dhu25wWVSRnnaPQV5J7xq/DXxBqOvxeHri/u5J5b3QdI1K4OdokuJfOEjkDAwQq/KPlGOAKAG3eu3+laq9ta3TxQRmJUj4YKBLBwM5x/rHH0OOgGADP8ACfjHWdQs743N/JMYLa8VCwHSPyimePmI3Nyck5Oc0AbOgaxfv4Lg1Nr24a9bUrJS5lYjbI9sjrtztAILcYxliepJoAy5vEWpz63qSteygBbRgUO05Y4bkdsMeOnNAFbQ/G2t6jretWU9+xtrXUNVtoURFTZHGZwgyoB42LyeeKAO0+GWqXOsI0F1IHhtoImhjRFRY87xgBQMDHGOmKAOtutEsrq3hingE8UH72NJWLhXHQ8nkjPegCS406BbbaokjCLkGOVlOduMkg5JwB1oAS20W0061Ntbo8cEjFTH5rkAEAELk/KOO2OST1JJAG22jWVpdSyQwCJriXzpihI8xxg7j6n5V59AB0oA/wD/2Q==' - }, - { - timing: 900, - timestamp: 272096254750, - data: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRQBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEIAFMAeAMBEQACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APeL79n7w9pfiqTR5rPUobOOOMjUjq2lx7v3oHMZgEnEZ3kkct8vzA7z9F/bWJevIvuf+Z89/Y2GWnO/vX+Rd/4Zo8Iyqs1jB4k1y5W4ZJYdM1DSpEhQOQkj+YqDLL823BIIIPTNH9t4lbxj9z/zH/YuGf2pfev8jprz9jTwu+myQ2N3rFxMoBWMyWse7kZy4tiemfX070lneIWvLH8f8w/sTD7c0vw/yMG//ZSso7+8gt/DXiC5lt5LfyZJbywjt7pHljWaRGFuxHlK8jlZFQvsCqpyxU/tzE9Yr/yb/wCSD+xMN0k//Jf/AJEsR/skWK394zaH4hVYZLhIHS904pcRKsYVtpgG15PMl2gjjyssyblNL+28T/LH/wAm/wDkg/sTD/zS/D/I0tO/Yt8La3aJd3w8T6TdNw1rJPaZUY4z5URXOOuM8g8t943HPcSvsx+5/wCZDyPDt/E/w/yLP/DC/gv/AKCPiT/v/B/8Yqv7exP8sfuF/YWH/ml94f8ADC/gv/oI+JP+/wDB/wDGKP7exP8ALH7g/sLD/wA0vvD/AIYX8F/9BHxJ/wB/4P8A4xR/b2J/lj9wf2Fh/wCaX3h/wwv4L/6CPiT/AL/wf/GKP7exP8sfuD+wsP8AzS+8P+GF/Bf/AEEfEn/f+D/4xR/b2J/lj9wf2Fh/5pfeH/DC/gv/AKCPiT/v/B/8Yo/t7E/yx+4P7Cw/80vvD/hhfwX/ANBHxJ/3/g/+MUf29if5Y/cH9hYf+aX3lm3/AGJvCFrGUjv/ABBgtuJdrZj24yYDxwOOlZvPMS/sx+5/5lrJMOvtS/D/ACB/2JvB7XLz/bteV2O7CtbbQfYfZ8DrQ88xT+zH/wAm/wDkh/2Jh/5pfh/kem69GniC1gFlqN4sYllR5dKuIgY2UOrZLHghkYYGTuTBHHHiU5JLU9ucW3oZ2gaS19G+o21/rAlaItAl1fwyxFmUFW+TevdgDyAGbAPy0Xhtb7v+HJUZLW/3/wDDHaaXEbW0uVllmu8QSEu5CyMM5xmMDGAcAqM8Dqa5qs+SLklsa/CtTk5fFemX2NPuBMouJWkU2+sXu5/3uNquqjPMp/dg4C+X/CF2+Q8wa+z+JjGvzR5rDrnx/ocGp2ttd3cMLs8dwxj1ufCN5cAXdgAbCJejEKx2HBZztX9ot/Z/EuNXmSdjp4dOs4JQ4/tByIPs2JNVuHUpt25KlyC2P48biec55qP7Tf8AJ+JXOwn0+yuEZX/tABpPNymqXKkNlzwQ4IH7xvlHGAoxhVAP7Tf8v4hzsf8AZLT7JJb7b4xyKFYnUrjfjy/L4ffuHHOQfvfN97mj+03/AC/iHOyH+yrHZAudTxCuxT/bF1kjj7x8zLHgctk9fU0f2m/5fxDnZcsjBYTNLElyzkMP395LKAGcucByQOWPToAFHAAB/ab/AJfxDnZe/tn/AKY/+Pf/AFqP7Tf8v4hzsP7Z/wCmP/j3/wBaj+03/L+Ic7D+2f8Apj/49/8AWo/tN/y/iHOw/tn/AKY/+Pf/AFqP7Tf8v4hzsdFqvmyKnlY3EDO7p+la08wc5qHLu+4c7Z5dqvhy2v752uvCGgXo85455riIysELFlZN1qd5O/cwyFVi3zMc59xJtbXBuKerN7R9M0rw1axNbabb6c8yrFJ9jtdqkqGYKSqLkDc+MgdTgc0OMm9UJTj3Oi0qf7RDLLDHJNutyyxgbHbpxhsYb2bHPXFY1Ic8XB9S90YqW0lpKtxD4Z1VZGDK/k/YFaPLMeSZe+A3BP8ArB33bfM/s+P8xkqSSsX9Qjm3mP8AsXU7poP3sUkRtchg5XKbpBhipLZIHy5H3srR/Z8f5mNQSSRd0ZJNRVhc6XfaWyAbftjQkyepHlSPjHvjrxmp/s2P8zHyGn/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyB/Y8X940f2bH+dhyDk0mON1YMcqQauGXxhJS5noHKeO+ItY0e9F9JLZ+JN1pcvBs0+PVoA7ALu4gQbh8pwyhgRgqT5hz665SnzdLHa6DNHLpkSxRzRRxlolW4Eu/CsVBJlAZs7c7jnOcgkEEp+Q0+5sWcXnpdRgBt8DrguUBzjjcOV+o6VnNRcWp7A7W1M2bSrpwswsrMXjAoyjW51XAZtuCIuTgJztBGWGSAC3lewwO119/wDwTLlhYlvtM8xiPs9qbV1X962ryoxUSYJwE6+WS2QeW+UnB3ivq2C7r7/+CO0SaNb4sw+xab5Y3bH/ALSkJYc7SR5XGeM8nHPWl9WwXdff/wAELRNj7LYf3l/7+UfVsF3X3/8ABC0Q+y2H95f+/lH1bBd19/8AwQtEPsth/eX/AL+UfVsF3X3/APBC0Q+y2H95f+/lH1bBd19//BC0Q+y2H95f+/lH1bBd19//AAQtEPsth/eX/v5R9WwXdff/AMELRD7LYf3l/wC/lH1bBd19/wDwQtEPsth/eX/v5R9WwXdff/wQtEcltZh1KMu4EY+fPNXChhIyTg9fUaUUcXa+HEju7mac290krb0SSxg3RnJJ+fZluo688dTXrNj5e5b/ALEsP+fKz/8AAOH/AOIpXHyo0YYYGsruGUW6232Vo3E6DygmADuUYG3HbgY9KzqOPK3PYdlYxp9N8MSTfaA2hHyI2Nw0kGWEILs/zb/lAlG85BHysOp3DyufBf1cyTp202D7HoRRrK9udEn1O8AhnUWrKLkoFwuwykttDLwScBhS5sD2/BjXKtjat7NICyGW2ECuBFHHDKuyMD7h+cjOccgAY/hpc+A7fgx3iX/L03/a/wC+npc+A7fgwvEPL03/AGv++no58B2/BheIeXpv+1/309HPgO34MLxDy9N/2v8Avp6OfAdvwYXiHl6b/tf99PRz4Dt+DC8Q8vTf9r/vp6OfAdvwYXiHl6b/ALX/AH09HPgO34MLxDy9N/2v++no58B2/BheI+FNP81Nm7fkYyz9a0pywXOlBa+jC6MmvXNAoAs2LmP7QyxPMywsRFEQGc8cDcQMn3IHvWdSHtIuD6ieplTadbusPm+E76ZW8yFnkNmfLjePe5Ymb7rMTGQM5YHI24Y+d/Z8O7MvZR5eW5LLpdq8tzdHw5dzXUAkkRwLYPcvuP3SZANx8iEgvtwGiyRhtp/Z8O7/AAL5V3NF4mWe0jXT76VJwxkmV4dsGOm/58nd22BvfFT/AGbT7v8AAORdyrdz3FvZSTx+H9WupUnMItoZLUSMoziUFpgu0+hYNyMqKP7Np93+Aci7k9oHuDCJdJ1C0MikkTSW52nft2nbIecfPxkbR13fLQstp9ZMTijS/siEnh3+mR/hR/Z1Pux8iF/seL+8/wClH9m0+7/AORdw/seL+8/6Uf2bT7v8A5F3D+x4v7z/AKUf2bT7v8A5F3D+x4v7z/pR/ZtPu/wDkXcP7Hi/vP8ApR/ZtPu/wDkXcdHpUcUiuGclTnmrhgIQkppvT0DlXcw69QsKAFaKOew1GOZElie1kV45LdrhWBHIMS8yA9Cg+9070AJ/wiejPDaWlzpujzIiGJIV01VADMC+0EttB2Lkeqgk8cAFO48MeFpbVlutL8OiCGSf5X05GRHYfvG5wAWVV3euMZNAD5fCelSwzvLb6FLEstzcSGTSg372V8eYfn+8VDq5x85Ib5QMEA27DTNPt78zRwWQll+aJoLYI4UIifM2TnhVHbgKO1AE914b0m9Vhc6ZZ3AaIwN50CuWjOSVORyDk5HfJoAnsNKstK+0fYrOC0+0StPN5Eap5kjfedsDlj3J5oAt0AFABQAUAFABQBylABQBYtLu309Lq6u7iO1tYIHlmnmYKkaLgszE8AAAkk0AcxZ+LzPsuI9Q1a4m/dY037TpOZd2AOVb+IxMDh+srBeg2AG1aJrMqRM411HKJHi6Gn8EgAyMY88jy8nGRmbhWAwgBlwQeI52lSSfxhaoygK8p0c4whzjaCck46/xY6DNAG4sOpy7E363b+VauhkP2D98/wAyhjgHDjaHGAE+cZB+ZQAU5k1rdHcBfEWJIyDaRnTf3bMsjZJPXYdqj5iCdmQw3tQBdsG1VFQzw6xNtzJtuDZZJMv3DsI+6q5BGPlfkluFAIoJdYiVpWg16Y3O8iBzp4NpycDIIz90Y5fhhu5zgAY1xq0ELTCx1+VpJMLbB9PzCCiHIJYDAO4dSd2/quw0Aa8Gs3sn2QNoGoRCbAcvJb/uPlU/PtlPdiPk3co3baWAIz4gvxZyTf8ACNamZVClbcS2u985yAfO25XAzkj7wxnnABNcazeQKxXQ76chpVxHJByFUlWGZBw5AVe4JG4KMkAEceu37tAD4d1FA5UOWltv3eVQknE3O0uwOM/6p8ZGzeAZ1ABQBc0wM0k4QsrmFgpTG4HjpnjP14oAyW1TXRZzWw0nxKZJnKrehtM8yANk7lHmbSF6YKMTgcHk0AJ9o1yO0Q+T4mll8tsqDpe/cWBAPIXIA2jthjnJwQATWEmtJcvHKniFo4pWbzbn+ztsygKm0CP5tp3GQZAOUIJA2owBbsNH1S5sSkuv6zbyB1IllisvMYbSSMLEVxl9p4BzGMcElgDSbSrphcgazer5qsqEJBmEksQU/d8kbgBu3DCLnJ3EgCz6ZdTTROur3cKoSWjjjh2vkHg5jJwMg8EH5RknnIAv9l3O+Jv7XvMIhRl2Q4c4HzH93nIwemB8x46YAIP7EvvKKf8ACQ6jkrgSeXbbgfKCZ/1OM7gZOn3jj7nyUAW7yxuLm3eOLUbi1diSJYkjLIMEYG5COuDyD0oAp3Oh308MiR+ItRt2YkiSOK2LJlVGBuhI4KluQeWbORgAAmu9JurmJ0j1q+tWbo8KQEr8hXjdER1O/kfeA/h+WgDSFAHK0AFAEdzYHULO4jDzxssfmKbaTy5SykEBW3KOSBwTtPRuCaAM2z+Gi2N69xY69rtv5yzlo5L1rpBJIFxIBO0m3btyiLiMZOVOarlXcz5/JlWL4c3Ja2kPiPxI2y9guWSSeEh2hds7sf8ALKbcGZAcYChVj5Wiy7jUm+jKlj8EZF06aJvG/i5Guki3LPqQaWFQsgKKy5ClvNbcynOVQqw8tMSWax+EyiwitU8T66m2VJDN9ud5HxIHKEsT8rAbSBj5SQu3rQBVb4PP/akl6njbxHGCgRbX7WrQxr5qS8KynJOzaWbJ2My5xtwAdhb6HLb20Mc2oG6kRFRp5o1DyEDG47cLk9cAAegA4oAlOjsOtwg+sf8A9egAGjselwh/7Z//AF6AA6O463CD/tn/APXoABo7HpcJ/wB+/wD69ACf2Q3P+kJxwf3f/wBegA/sg8/6SnHX93/9lQBlUAFACtDHcWOoQzRpLDJbOjxyKGV1OAQQeCCDjFAHmd14s1W61S+SW5V/J0u4CMYU3qGt0dhu25wWVSRnnaPQUAavw18Qajr8Xh64v7uSeW90HSNSuDnaJLiXzhI5AwMEKvyj5RjgCgBt3rt/pWqvbWt08UEZiVI+GCgSwcDOcf6xx9DjoBgAz/CfjHWdQs743N/JMYLa8VCwHSPyimePmI3Nyck5Oc0AbOgaxfv4Lg1Nr24a9bUrJS5lYjbI9sjrtztAILcYxliepJoAy5vEWpz63qSteygBbRgUO05Y4bkdsMeOnNAFbQ/G2t6jretWU9+xtrXUNVtoURFTZHGZwgyoB42LyeeKAO0+GWqXOsI0F1IHhtoImhjRFRY87xgBQMDHGOmKAOtutEsrq3hingE8UH72NJWLhXHQ8nkjPegCS406BbbaokjCLkGOVlOduMkg5JwB1oAS20W0061Ntbo8cEjFTH5rkAEAELk/KOO2OST1JJAG22jWVpdSyQwCJriXzpihI8xxg7j6n5V59AB0oA//2Q==' - }, - { - timing: 1200, - timestamp: 272096554750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 1500, - timestamp: 272096854750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 1800, - timestamp: 272097154750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 2100, - timestamp: 272097454750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 2400, - timestamp: 272097754750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 2700, - timestamp: 272098054750, - data: - 'data:image/jpeg;base64,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' - }, - { - timing: 3000, - timestamp: 272098354750, - data: - 'data:image/jpeg;base64,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' - } - ] - } - }, - 'final-screenshot': { - id: 'final-screenshot', - title: 'Final Screenshot', - description: 'The last screenshot captured of the pageload.', - score: null, - scoreDisplayMode: 'informative', - details: { - type: 'screenshot', - timing: 611, - timestamp: 272095965725, - data: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAFcAfQDASIAAhEBAxEB/8QAGwABAAIDAQEAAAAAAAAAAAAAAAMEAgUGBwH/xABGEAACAQMCAgYHBAkDBAICAwEBAgMABBEFIRIxBhMUQVGSIlJTYXGR0TKB0uEVFyMzQlRik6KCobEHFiRywfA08SVEwtP/xAAZAQEBAQEBAQAAAAAAAAAAAAAAAQIDBQT/xAAqEQEAAQQBAgYCAgMBAAAAAAAAAQIDEVESExQVITFhkaEEQTJSIjPx8P/aAAwDAQACEQMRAD8Aq6ZZJelw06xMpGzY3ByP+eEffnuq2+iojcLXsPEQCBy2JPy2GfvFeofqp0b+cv8AzJ+Gn6qdG/nL/wAyfhr25/OtZ9fp4sfg3Men28rutKjg4B2uMsZFQ5GAAeTeNZnRlHBxXsWWyMKC24bGB416j+qnRj//AHL/AMyfhp+qnRv5y/8AOn4ad9b39HY3NfbzFtCVed7ANk/iB3Y4xn3Hn4AjnUEWmLJHZMsvGZ+LjC81xXqv6qdG/nL/AMyfhp+qjRv5y/8AMn4ad9b39HY3NfbyldNRowRNwM1wsI4xgcJz6Xu7vnU8uiKoLLdxkBQ2CN/DHPu7/AYr0/8AVRo385f+ZPw0/VRo385f+ZPw0763v6Oxua+3l6aGC6o97AkjMFw3IZBO57uX/FfV0RG48XsZZVDcIXf7WMbnnsTj4eNen/qo0b+cv/Mn4afqo0b+cv8AzJ+Gp31v+30djc/r9vNG0BRJwC+g2fgLHly5/Duz44FaySzCpMy3EREfCQCcMwbHIe7O9evr/wBKNGJ3vNQ8yfhrWan0I6G6VcCDUtfktpuENwS3EakL4kcOw95qx+dbj1n6J/BuT6R9uCn0eAyzLaXqSCMlTkYyQSMD47Y+/wAK+DSIRdmCS+hQBkUtzBycHGK9ST/pTobqrJe37KwyCHQgjy1HB/0u0GfrOrvdRPVuUbJUbj4pv8anfW/7T8HY3NR8vMZNFROLiv4DwqzHA7lxy8c528alHR8POIo72Bm9DZd/tHG3wI38BXp36p9F/nNQ86fhqvd/9Ouj2mvbifU9Rhe5kEEQVlLOxBPCAFzyBJ9wOad9b/t9L2Nz+v28vXSQbkxdpTYAg455BPLPuP8At41aTQF61ka+g9E8JIOwbh4s/DkM+Nenfqn0X+c1Dzp+GsW/6V6EjorX98rOcKDImWOM7ejvtSfzre/pI/Buf1+3lN1pSQWxk7XEzhQ/V433bGD7x3irMGgq1wqyXsSxksCw5jA8M9/d7t69P/VPov8AOah50/DUFl/0y6PX0LS2uoX8kayPEWDJ9pGKsPs9zAj7qd9b3Pwdjc19vM20QKCzXkQTCb4ycscYx4jbPxqK80kW8AkFwrHi4SCMY3I5593/ADXrH6ptF/nNQ86fhqCL/pl0elvJ7SPUL9riBUeROJMqGzwn7Pfwn5U763v6Oxua+3j9zD1E7R9ZHJw49KM5U7eNRV7Z+qbRf5zUPOn4afqm0X+c1Dzp+Gt+IWWewvaeJ0r2z9U2i/zmoedPw0/VNov85qHnT8NPELJ2F54nSvbP1TaL/Oah50/DT9U2i/zmoedPw08QsnYXnidK9s/VNov85qHnT8NP1TaL/Oah50/DTxCydheeJ0r2z9U2i/zmoedPw0/VNov85qHnT8NPELJ2F54nSvbP1TaL/Oah50/DT9U2i/zmoedPw08QsnYXnidK9s/VNov85qHnT8NP1TaL/Oah50/DTxCydheeJ0r2z9U2i/zmoedPw0/VNov85qHnT8NPELJ2F54nSvbP1TaL/Oah50/DT9U2i/zmoedPw08QsnYXnidK9s/VNov85qHnT8NP1TaL/Oah50/DTxCydheeJ0r2z9U2i/zmoedPw0/VNov85qHnT8NPELJ2F54nSvbP1TaL/Oah50/DT9U2i/zmoedPw08QsnYXnidK9s/VNov85qHnT8NP1TaL/Oah50/DTxCydheeJ0r2z9U2i/zmoedPw0/VNov85qHnT8NPELJ2F54nSvbP1TaL/Oah50/DT9U2i/zmoedPw08QsnYXnidK9s/VNov85qHnT8NP1TaL/Oah50/DTxCydheeJ1sNK0036yN16QqjKpZ+W4Y7nu+z8yK9c/VNov8AOah50/DX39VGjYI7bqODvjjT8NSfz7Ux5T9LH4F3PnH28pGjIVDC9gxwB/SPDzGw9/vr7+gyXwLmPGcDxzgnHu/OvVP1TaL/ADmoedPw0/VNov8AOah50/DWe+t7+l7G5r7eRW+nrN1eZ1j4ousy/LPHw4/+fnVi50dYI537ZE/V5AVBuxAz8vfXqx/6UaMQM3uonGw9NPw18/VNov8AOah50/DV7+1ufg7G5r7eTRaYkjTg3CRmMgDj/izj61Zk0JFKBb2EEsVPFtggZ+73eNeon/pPoxOTeaiT/wC6fhr5+qbRf5zUPOn4anfW9z8HY3NfbxM86V7Z+qbRf5zUPOn4aVvxCyz2F503STR49VWzLWtvO8Mwc9aoPo4ORuO/auYtdJ6TdrgmuXcvGGWN1nA4OLqCeIZPEuUl2yeY2Hd38jcEbNgnAJwOZrRx9IojGC8YLnP7puIbAHmQMnfuzivDimZ9HtzVEerX9EtL1ywnjj1G4zaRWqRKinKghIx48wQ/cM55nu16dGL6WKxia3WBoRCt5Is3/wCa6zRMZDjc+ijn0t/TxXSRdIIZSypBMJBEZQrFRkcJOOfgKjXpNbl1jMUnW8ZjIyMAjGd88ufyq8KtJzpU7/Sr5tS1CeC1hlupW4rO9eTHZgIwvDjnjiBbA2PEc1XGmdIJC7C5niiDp1Ub3GWVeJOMMRz2EmNz9ociBjbXXSKC3vHgaGU8HHxEY5rj39+/34HfWMfSSCS4jRbe44WyCxUDDZAC/eSPmKcKtHOnbR6dpPSZRHHcXkqRBYEIEuTwhouMcXETxYWXcAZ4uZ2xnZaZ0it7uN5J5pMzxtJxT5RkCRKcjIIOVkPIg8XI5yO3pWWilKUH1edcG8tzot50jhlt7hbm/uxcQXS6dLexzRGNF4CI+RHCVwxHcd67+CPrHxnG2eVWOyn2n+NB5DqEWrvYTfpGxvoNRfSIF02LT0kEUF1h+IDgJVCG6vdjjhHPANX7PS9Rv+kgi1VNQNl1t+zYeRI2/wDx+r3BG32yvwOOVen9lPtP8adlPtP8aDwu+k1KDoxcyax+mV1JdMs+yyKZQIzjEvGRsrcWeLi3IxjNeh9L9Pa71roxcJbSz9lvJZG4CQFHZ5cZI2GW4Rk95x310F70Z02+vY7y8tLea5j4eGR48n0Tlc+ODuM8jyrY9lPtP8aDxPT01Rw4caza295prdcYbO6ZorgSRnhbjYs7BS4LLw8QyFycAbPSLaaTWNCuLnT7xbe2v5kWZI7kI3FCvC/Vvlo14sjf0cgnODXrPZT7T/GnZT7T/Gg836Zpcx9JY7m3jv7thHCqWqxThCQ5JaOaM8KNv6QcYIA3ArTpaXUHal1W01Y2bC/NolrHNkTtdysGITcEoYyrHbnvvXsHZT7T/GnZT7T/ABoPIpIuk9pNGLhL+Y2SQ6tI0XEwmfhiSSBcfaJxcNwjvZfdWCWuqaJDea3d9qFxZW9lfTkk4m3nNxGCdmwsjYHcQnur2Dsp9p/jVW/0a11BIkvY450jkEqq65AYcjj3UGq6KW11b6FbfpBna9m4ricM2eB5GLlB7lzwj3AVt6sdlPtP8adlPtP8aCvSrHZT7T/GnZT7T/Ggr0qx2U+0/wAadlPtP8aCvSrHZT7T/GnZT7T/ABoK9KsdlPtP8adlPtP8aCvSrHZT7T/GnZT7T/Ggr0qx2U+0/wAadlPtP8aCvSrHZT7T/GnZT7T/ABoK9KsdlPtP8adlPtP8aCvSrHZT7T/GnZT7T/Ggr0qx2U+0/wAadlPtP8aCvSrHZT7T/GnZT7T/ABoK9KsdlPtP8adlPtP8aCvSrHZT7T/GnZT7T/Ggr0qx2U+0/wAadlPtP8aCvSrHZT7T/GnZT7T/ABoK9KsdlPtP8adlPtP8aCvSrHZT7T/GnZT7T/Ggr0qx2U+0/wAadlPtP8aCvSrHZT7T/GnZT7T/ABoK9KsdlPtP8aUFOqELagLe9NxDbdasj9mWJyQ6fw8RIGGPfjIq/VDUJ4p9Kv8As9zGCiPG0iNnqmA3zjcEfOrHqk+jWAavC0cktvbSTgdV1gXiY5IAbIxtuSRgcj4ivr3OvIvE1pb4Gcld/vxnPfyG+1UsQMzJFq79cwdxx8apthcA52GR79jt4nKK3Qx2rSaw+FcJIF4iHbgyVznljH/7rrjbjn/2Wzun1R7W3ltowsuCZYjw8xhgMnxwV/1Z7qpyjX0hVBDBcyDdZGCjhbJGcZ8MGoktLeR44ItamaV4wEZXJOxGSN+Z3/38KtWNtHFdREaqZXQl3UknKlRtzwB3/fU8o/4vnP8A1JdS6yL3/wAaGNoApG/DueFSM+lnPFkH3eNbvIzjIz4Vzdjbw20kky6sZcJxsBnOy8OeZ8QT78cqwtYbWCOXi1hJJXX7Z7gWBHfnG2OfKpNOWoqw6fIxnO1fQcjauYsdMMV3Dam/kni6oZRkYKyKO7uOSUz7hjfJrobO3W1to4Y/sqPme8/OszEQ1TMz+l6y/fH4VV6S3Oo21tB+iog8skhRyYy/AvVuQdv6go++rVl++Pwq3JIsYBc4B92azM4aae61K+t3mxZtIouxChCMcR9UG4jgEn08rnGBn3VrIekmrOoDaHOsjcPDlHxuhZsnh24Wwvv5iun7VF6x8pp2qL1j5TWedOzLn11jWDCzHTW60XawhAjAcBiDFySNxx5GRWd9rGrQ29vJb6UZXaEySJ6XosFY8IwPFQP9Qre9qi9Y+U07VD6x8ppzp2ZaJdevX01bqLTmkPajblI+JyQuQzDA5cYIBOBjfvAqrF0k1ZwFOhzrI5QISkgXdCzZ9HbhbC78+YrpxcwgYDYH/qadqi9Y+U0507MtHZa3qM+pW9vLpckcUhYPKUcBMDkSVxkbb8jnY1SHSHXEwG0OSU8bJlFdc4CHvG2eJgDy9A+O3U9qi9Y+U07VF6x8ppzp2Zam31e8n0lZlsXW9MiKYGVl4VaTh4jkZ2GWx7vvrR6d0p1e+uOpj0zheBFadGDFgSzrg7AZ9Di/1Y7q7LtUPrHymvguIQSQcE8/RNOdOzLm59b1qBLaYaW9wklrC8iJGyskjLIX2PcOFBjn6Q8anstb1Sa9tIp9IkiimPpSYbCDhU75G25PPwrfdqi9Y+U07VF6x8ppzp2ZcxN0k1dXuup0G4kWEvwgq6mQBlVQu2MnLH4LUo1rWI9PgmGlvcyu8xZQjxnhWdUTAIyMo3Fv3KfjXRdqi9Y+U07VF6x8ppzp2Zc5F0i1Lr4lm0eZbdj6dxwOAq5O+CuRsrnB7+D1hWeuaxq+n3U6W2nSXcSDrEaONjxKQAE2/i4g5J7hw+NdB2qH1j5TTtUXrHymnOnZlzVxr2sqiPHozlWdQAA/EAZGGT6JwAqgnb+Mfes9Z1q5gvnfTZIsQytBxRMG41VMDHfxEtj4V0vaovWPlNO1ResfKac6dmXMT9I9WhkkiOizuyK3ppG5ViJOEYwN8rkjl8e+rerapfwXIS3hlEbQo5YWkkhjJfDbjYnB+zzHOt52qL1j5TTtUXrHymnOnZlyFtrfSRpE67TSqbGbEDZi9NgeHf0/RCnbnxHGcYq/catrEGrX8MemvPbRunVPwkBl6vLYONzxbff7t+g7VF6x8pp2qL1j5TTnTsy5/SNe1K7ngS60ee3WRCxyrDhIBOGJAA3GOZzz2rGz1nV5lvbiXT2jihgjaKMxODI5J4sZGdgAMY9/Igjou1ResfKadqi9Y+U0507Mubh6R6k2DJotygYDA6t8qxzgH0cdwORsM4O9Y/8AcOsCKItoshldowyBZPQDR8WSeHHP0PcRkjurpu1ResfKadqi9Y+U0507MuYbpHqw6rGizelw8X7OT9nkNxZ9HfgwAcfa4tvCrXRzWNTvZVi1HTpLbCITI0bgMSgJxttvkb4xjHM1ve1ResfKadqi9Y+U0507MpqVD2qL1j5TTtUXrHymnOnZlNSoe1ResfKadqi9Y+U0507MpqVD2qL1j5TTtUXrHymnOnZlNSoe1ResfKadqi9Y+U0507MpqVD2qL1j5TTtUXrHymnOnZlNSoe1ResfKadqi9Y+U0507MpqVD2qL1j5TTtUXrHymnOnZlNSoe1ResfKadqi9Y+U0507MpqVD2qL1j5TTtUXrHymnOnZlNSoe1ResfKadqi9Y+U0507MpqVD2qL1j5TWccySEhDk/Airyif2ZZ0pSqNVWlgnto9O1iW20t7fq5ZjJG8Ii7S4G7j1g3rd9WdV1iz0oqLxpF4o3l9CNnwiY4mOBsBxCvo1rTDIEGoWnGSQF61c5BII5+IPyPhSCWktJNPnEVu2mhGmJRhx+iFBVQc+/hXHw51jFc2hZrddPdUFwhTLt9ogDOc/aAJ293ure/pnTutaNr22Vw5jwZV3YYyOfMEgfE1KmpWLzpCl3btM32UEgJOwPL4EH766c3Pg0cclha9bcDTXDW05hQpksAM+kB3DOeXPJ8TUS31pC/Ww6Zc9YuXOSTw5IQ7Z547vDFblde0o8WdQtV4S4IeQKRwlg3PwKt8jWces6bI6Kl7bEyNwpiVfTOcYG+++3xqc14ILSwt47uaFLRBCY/tiQnPFjIIPecc/cPukm0OykgaJY2jzj00Y8Qxy3Py+FbOlTlK8YRxQxxEFFwQoTPuHL/k1JSlZaWLL98fhX3VSRaOVYK3CcFjgDbvPdXyy/fH4VnqUYltzGSQGBGRzFcr38JSr0czi+W4wmoW7QoyA8T+kdt87YGRyFT6Q121xm4vIJkEIykbBjxbb8htsfn7q1dzFpkN48M6XDvxopkEmBkDbOCN9+/xq30f7F2p+zJKknVkjjIwQSCSMbb+j8hXnz6Plpn/JGi6rJEBbXtsuVkw/XdZj9rtzXfC5U576t2MesreIby7tZIOsk4kQYPBgcA5cwc/OtHO2lPAO2NcTLwy5RWjbi/bjPIDPpYPcMffVnRTo/wClIex9rE3Xz8JkGAzYHFudyMcvh7qPoXimsNq0piurZbMTg8BbiYriPKkcO23Gdj/EK2GotciS2W3liiDTANxMAXXDEqMg77A/AHlXNznRT0lkE5ne8F0uMEFUfEODtyB/Zr8/fW56QvYL2T9Icbnr16pUIyr8L4Py4vltWYcrc5yx1Jbn9Ju1vfordVHwWzShR+89NiOEncYUH48qrhNak4zaXtmsQaYbsZDnjONyNuHYY7sH7vuoy2l3pzanbQzyvM0MClOFWOJcL9rYYZt/hWsvRpIkaS6e4kP/AJA2dWYMJACAoHi5IPdnfltqHV2UPH1SdbjrOEcWOWe+s61+j31veQFLXreGDCftBhuWx33+dbCsBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBSlKBU9n9s/CoKns/tn4V1sf7IIW6UpXptubv9Ksr68t7q9gjme3V1jEihlHEVJOCOfoDf41qx0Y0e7l7Qh60NG0RIKsCCX78ZBHWPyI575roZFDoynkwxWoOgQiWF0nnHVIqKGbiBwcjOdzuBVjH7SZn9Kq9FdM4+FZJ8rwdavWA8fDwFeLbPONTkYyc+NSWPReztLqG4S4uXlibi4mKZb0FQAkKDjCrsMZxvmrF5oUF3dG4eWRXY5YLgBvRC77eAr5eaFFc3Uk5ubiNnxtGQMYGB3dx3q4jaZnSjfdEbS5ScR3NxG0rO/MFQzGQ5xjO3Wvjfv3zgVZs+jNpaXaXUE90s4Z2d+IftONw7A7ciwB2x4ctqls9ES0vlmjmkKBmcoTsWIAH3AZ+dbipOP0sTM+pSlKilKUoLFl++PwqW8+yvxqKy/fH4VLenCLsx37gTXK9GaJSfRqL8XPW2/ZeEIX/acs4+/7/wDaoNNGoLcN2so0PVggjhzxbbbf6v8Ab31LqVjHfrGJDcJwZwUUg78+6sNN02PT3dojM3EgU8UZ7ix54/qP+1efxnHo44nk1yzaw0ai2gjLlXw03VkfvPRzwtv6Hh31asZNYa8QXlrbJAZJAzIdwmBwHnuSc93yrCTQo5Y+B57vhIYHgj4SeKTj8PHb4E1JZaNHaXSTrPeuyyPIQ/EwPEACNxy2HL61eM6dEJl1r9LSrFb2/YxMPSfHEY8R8sNkH94dx4Vf1NbluoNpBBI6SqSZv4QQQWX3jP3gkVTk0NJNSa8NzehjKJhGqkKD6Axy5EIB/qbxq9f2gvRGGkuowjq46tSucZyDtuCDg1OM6YoiYzlV0d74PHBdwQQxrCDwRqBwtnGNnOBttt945VRnfVYoLgBkmcrclXTql6tuIdUNz3DnkHnvWz07ThZPGVkuJAkXVYaPnvnJIHOq0mgwGGWKEzQpKs6uEi59a3Ex5cx3VeM6bfbWbWTeqJrS3S1MrAkEcQTHok+lz5A7eP37qtNb6MkN4tz1968glaUhgxBLcxjGMdw921bfi/ok8h+lSaZ0MqVjxf0SeQ/SnF/RJ5D9KnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQypWPF/RJ5D9KcX9EnkP0pxq0MqVjxf0SeQ/SnF/RJ5D9KcatDKlY8X9EnkP0pxf0SeQ/SnGrQyqez+2fhVbi/ok8h+lWLI5c+iw271IrpZpmK48iFylKV6TbiOlSaz1kUuil2EdtOXiUgCVzwBRvybHGR7xg7GqKXXSkGfitk2m4VAAP7LL5YHI34QhA39I4OATw9e2cHhIB7ia0T6jqlupMll2j0Rjq1ZcEsQdt+4A1YjKTVj1UppNfjs9LZDM8vCy3f7NCc8ab49ydYRjmQOfKteNR6U3Aukhtg88DIvAyhFziFt2DczxSZHLb59FcahqEN04WyMkP8ACRnb0OLwOd9qim1W/Wxilj06RpnfePhbIHEu3LmQTvy2q8ZTnDZaS872KNddZ1uTnrECNjO2QCRVyudm128ijEkmnOiBhxM3EAoORk+j8NqsxarePYtOdOcNgFUySSCWHhnuHd/EKcJTnDc0rTTX2owwRP2TrGcMSEU+hg8j8RsPfUa6tqDJG36MdQxQEEnK5znI4e7H+4pxlecN7StVpN/eXc0gurNoI9+AsCDsF55HeScfCtrUmMLE5WLL98fhUt9eW9jAJruURxllTiPiTgf/AHu51FZfvj8KarpdnqsSRX8ImiUkhCTjJUqf9mPzqKiuNd0y2uZILm9hhlRxGyyHh9IqGAGeexFS22rafc2xuIbyBolRZGbjA4FYZBbPLPvqlcdGtPnunuXWXr3ZXZxIckqvCD8gKxsei+l2FrLb2kJjSTgJIPpAo3EpzzOG33z8tqDYDVLArERfWpEpAjPWr6ZJwMb78jUVzren28cMklwDFMpaOSNWdGABP2lBGdjgd/dmqK9EdHWVJBbkuhQgs3F9kYA3z8fjk1an0GzmitYm60RW0PURoH2C4xn44A350Gdrren3bSLb3Ad4gTIvAwKYAJ4gRtzHPvyOYNfU1zS3Rm/SFqoUEsGlClRnG4PLcgfeKhsujunWU081vEyzXHF1z8ZzLkAHi8eWfcScczVZuiGkNEUMDYMjSbtxekxUk4O38IoNqdSsVhkmN5bCGJuB3Mq8Kt4E52NQLrmmNGrm+gRGMgDO4UHq3CPjPgxA+8VCOjtgttLBGskaSSdb6DcPC2CDjGw2JH31jddGdMubeGCSJurh4ygzkDicOdjnPpKDvQWn1rS0co+o2gYBiczLtggHO+2Cyj76zOracCQb+1BBZSOuXYqMsOfcOfhWuXorpqTCWFZYnUsU6t+EJkgnAG38I351HJ0P0mTrRJHKwlLF8vu3EMHfnyA798b5oNxBqNlcSCOC7t5XOMKkgJ3GRsPdvVqtVpuhWWm3BmtFaNiMMFwqt7yAAD/8d2MmtrQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQKUpQczq+qHTTbAWVzddfIIh1JjGGPIHiZffVGPpZpbR8UkjxEOUZXQgj7YGNvSyY2AxncYrc3NtFc9T1yk9VIJU3xhhy/5rWSdGtNdw/VSK4HCGWRhgftP/8Aq/zoPmrdIrbTobaRoZ5VnR5F4eGMhVAJJ6xlxz5c6y/7k0vPCZ3D4UhDC/EcgnYYy3I5xnGDmp7fRbCBLNEgBW0VlhDHIUNjP/A+HdWrv+iNnLK9zZO1tes7SCUszBSxJbYMOfE3f345YFBs9O1vTtSn6myuVlcp1gwpAZdtwSMHHEuccsjNbKtPoXR2x0XhNmrBxGIyxPPAAJx4nhB//ZrcUClKUClKUFiy/fH4Vlqcxt7ZpQxUICxxjkPjtWNl++Pwqe7h6+Pg9HhPMMMgisXImaZ4+qT6eTSJqzvwBe08TMqhSqA7rxd/uz8jUllqUl2wCNOoMYkBYJjBJxyzzwauppwjOUEKnbcR45bVkLNxyaMbY2Xu+dfHwve/y5xTV+2mk6QxQxdZPNPGPT/gDfZk4DyHiRUlpr1vdTpFDdyl3do1zGACyjJAJXw/+a2CaTEhBSK2UgYBEQG2c1kumqrh1WEOCTkR4OTzq8L3v8tYlqpOkVtFfmzkupVnEohx1YI4iE7wuw/aKM++rl7qK2QiNxdOvWOI1woOWOcDYd+KsDTEEjSBIA7HJYR7k/GpGsmY5Yxk7HdPDl31OF73+UiKv21un6wt/wBX1M04Z4hMA0YGFPLO3Oq56QYgnlbtKiJZ2AZUBYRHDEffyrbx6cI24o1hVsYyseDjOf8AmvkulxykGWO3cgEelEDz51eF73+VxLXQ67BNdC3ju5TIZGiH7MAcS7EZ4ccwflWy6yb27/JfpXxdMRGDKkCsDkER4wcY/wCKm7LJ66eX86nC97/JiUXWTe3f5L9KdZN7d/kv0qXssnrp5fzp2WT108v504Xvf5MSi6yb27/JfpTrJvbv8l+lS9lk9dPL+dOyyeunl/OnC97/ACYlF1k3t3+S/SnWTe3f5L9Kl7LJ66eX86dlk9dPL+dOF73+TEousm9u/wAl+lOsm9u/yX6VL2WT108v507LJ66eX86cL3v8mJRdZN7d/kv0p1k3t3+S/Speyyeunl/OnZZPXTy/nThe9/kxKLrJvbv8l+lOsm9u/wAl+lS9lk9dPL+dOyyeunl/OnC97/JiUXWTe3f5L9KdZN7d/kv0qXssnrp5fzp2WT108v504Xvf5MSi6yb27/JfpTrJvbv8l+lS9lk9dPL+dOyyeunl/OnC97/JiUXWTe3f5L9KdZN7d/kv0qXssnrp5fzp2WT108v504Xvf5MSi6yb27/JfpTrJvbv8l+lS9lk9dPL+dOyyeunl/OnC97/ACYlF1k3t3+S/SnWTe3f5L9Kl7LJ66eX86dlk9dPL+dOF73+TEousm9u/wAl+lOsm9u/yX6VL2WT108v507LJ66eX86cL3v8mJRdZN7d/kv0p1k3t3+S/Speyyeunl/OnZZPXTy/nThe9/kxKLrJvbv8l+lOsm9u/wAl+lS9lk9dPL+dOyyeunl/OnC97/JiUXWTe3f5L9KdZN7d/kv0qXssnrp5fzp2WT108v504Xvf5MSi6yb27/JfpTrJvbv8l+lS9lk9dPL+dOyyeunl/OnC97/JiUXWTe3f5L9KdZN7d/kv0qXssnrp5fzp2WT108v504Xvf5MSi6yb27/JfpTrJvbv8l+lS9lk9dPL+dOyyeunl/OnC97/ACYlF1k3t3+S/SnWTe3f5L9Kl7LJ66eX86dlk9dPL+dOF73+TEousm9u/wAl+lT2jOXPHIzDHeB/8Cseyyeunl/OpbeFo2JZlPwGK3bpuxVHL0WIlPSlK+xpqWBKkDmRXPw6XqkWWS939AcLSFsqM5ySOZyNwB9ZekGpy2V7Z26XNrZRTRyu1zcrxICnDhPtLueInnyQ/EaRenB7JD1toVui0QeJH9LDCAkhSM4/bYH/AK/KxVhJpy30NjqfU3CXV8JeJMIU9Ag+Ocbch48zUcdlrCABbuLhG2CSdsY5kcwd/f7q1+n9K5LrVrO2aK3MVyikPDN1iIxycF8DcjAC4599R6h00NpcXMHYonljnMSjtGAQBIeJm4cLnqyMZJyd8VeUpwhuIrPVFnhL3oaNSvH4tsM/w7d/z7sVua45OmvWaoLKGyR3aQouJt8Lx8eRw8xwEYGQc8++vtv0ruJri2dbe0e1kEQfqbnjKGSRFXfh3I4xkbcudSZysRh2FKUqKUpSgsWX74/Cq/SPVJdLs45La1kupnfAjRSx4QCzHb3Age8irFl++Pwq3JIkYBkdVB8Tig5TUOlVza6lPBHZxywLLGiSs5QFWjDls4Ocb+GwqTSOlUl5pU11PYNE8KRFwXAHE5wSRzVR9rJz6O/uro+1W/tovMKdqt/bReYVMwmXNx9LmkeBBplwpkZFYuwVQXGQAT9o8ODj31nqHSOeC30+SOKBJbqAztBKx4kXhznO3LbIAJO/gTXQ9qt/bR+YU7Vb+3j8wpmDLnNI6R3l7cXcU1mIkhV+qmweG4IVT6PgDnO/cRjOCRXTpjMsDvLpknou8fEW4FyrKN8jYYcb53I7q6vtVv7ePzCnarf20fmFMwZaI9JsWF1cNaFWgnMJRpRgbZyzAEA7YwM7kDvqpedKbq00+1mlsC0080g6tc54FnVMAd7lWzjbkTyFdR2q39tF5hTtVv7aPzCmYMuci6XRkM0tsqIo3YS5DekV4l23XIxxeJxiopOmEscbSNpUqx5wrGTH8ZTLbeiNic+GPHbqO1W/tovMKdqt/bR+YUzBly0nTGSNx1mmtEhBIMsuN+NkA2BGcqTzwBvmo7Xps0zAtpzqjqjKOLfDEjh5fbxg8Phk5rre1W/tovMKdqt/bReYUzBlU0bUX1GJmkgEDrjKF+IjOfcNsf758N9jUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFO1W/t4/MKZgympUParf28fmFZxzRyEiORGI8DmmYXLOlKVRoL6GO8je0ltWuUZQWQYwBnY7kb5Hd4VmqSqBiwm2AGSUJ29/FUFxqLabdyzdR1kQhDO5lVAgBO5Jr6vSSR7dp4tPMkaqXylxGdhnPf4gitYZynCzAYFhMB7uD8VCkpznT5d9z9jf/KrI1CcjPZV/u/lX3t8/wDKr/d/KoKoWUHIsJs+PofioFmAwLCYD3cH4qtdvn/lV/u/lTt8/wDKr/d/Kgr5uP5Kf5p+Kmbj+Sn+afiqx2+f+VX+7+VO3z/yq/3fyoKwlYTLFLBJEzKWXixg4xnkT4ipajlkmuLuGR4ljSNHXZ+Ikkr7vcakpKwsWX74/CmrGQWjmFS0oU8I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' - } - }, - 'estimated-input-latency': { - id: 'estimated-input-latency', - title: 'Estimated Input Latency', - description: - 'Estimated Input Latency is an estimate of how long your app takes to respond to user input, in milliseconds, during the busiest 5s window of page load. If your latency is higher than 50 ms, users may perceive your app as laggy. [Learn more](https://web.dev/estimated-input-latency/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 12.8, - numericUnit: 'millisecond', - displayValue: '10 ms' - }, - 'total-blocking-time': { - id: 'total-blocking-time', - title: 'Total Blocking Time', - description: - 'Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds. [Learn more](https://web.dev/lighthouse-total-blocking-time/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 27.5, - numericUnit: 'millisecond', - displayValue: '30 ms' - }, - 'max-potential-fid': { - id: 'max-potential-fid', - title: 'Max Potential First Input Delay', - description: - 'The maximum potential First Input Delay that your users could experience is the duration of the longest task. [Learn more](https://web.dev/lighthouse-max-potential-fid/).', - score: 0.94, - scoreDisplayMode: 'numeric', - numericValue: 111, - numericUnit: 'millisecond', - displayValue: '110 ms' - }, - 'cumulative-layout-shift': { - id: 'cumulative-layout-shift', - title: 'Cumulative Layout Shift', - description: - 'Cumulative Layout Shift measures the movement of visible elements within the viewport. [Learn more](https://web.dev/cls/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'unitless', - displayValue: '0', - details: { - type: 'debugdata', - items: [{ finalLayoutShiftTraceEventFound: false }] - } - }, - 'errors-in-console': { - id: 'errors-in-console', - title: 'No browser errors logged to the console', - description: - 'Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns. [Learn more](https://web.dev/errors-in-console/)', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'server-response-time': { - id: 'server-response-time', - title: 'Initial server response time was short', - description: - 'Keep the server response time for the main document short because all other requests depend on it. [Learn more](https://web.dev/time-to-first-byte/).', - score: 1, - scoreDisplayMode: 'binary', - numericValue: 89.95400000000004, - numericUnit: 'millisecond', - displayValue: 'Root document took 90 ms', - details: { - type: 'opportunity', - overallSavingsMs: -510.04599999999994, - headings: [], - items: [] - } - }, - 'first-cpu-idle': { - id: 'first-cpu-idle', - title: 'First CPU Idle', - description: - "First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle/).", - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 1215.06, - numericUnit: 'millisecond', - displayValue: '1.2 s' - }, - interactive: { - id: 'interactive', - title: 'Time to Interactive', - description: - 'Time to interactive is the amount of time it takes for the page to become fully interactive. [Learn more](https://web.dev/interactive/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 1215.06, - numericUnit: 'millisecond', - displayValue: '1.2 s' - }, - 'user-timings': { - id: 'user-timings', - title: 'User Timing marks and measures', - description: - "Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences. [Learn more](https://web.dev/user-timings/).", - score: null, - scoreDisplayMode: 'notApplicable', - details: { type: 'table', headings: [], items: [] } - }, - 'critical-request-chains': { - id: 'critical-request-chains', - title: 'Avoid chaining critical requests', - description: - 'The Critical Request Chains below show you what resources are loaded with a high priority. Consider reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load. [Learn more](https://web.dev/critical-request-chains/).', - score: null, - scoreDisplayMode: 'informative', - displayValue: '5 chains found', - details: { - type: 'criticalrequestchain', - chains: { - '78824159071B051C87326BFDF8050474': { - request: { - url: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - startTime: 272095.355724, - endTime: 272095.655509, - responseReceivedTime: 272095.65457400004, - transferSize: 5851 - }, - children: { - 196.2: { - request: { - url: - 'https://varnish-cache.org/docs/6.2/_static/classic.css', - startTime: 272095.673331, - endTime: 272095.755375, - responseReceivedTime: 272095.754602, - transferSize: 1394 - }, - children: { - 196.9: { - request: { - url: - 'https://varnish-cache.org/docs/6.2/_static/basic.css', - startTime: 272095.762277, - endTime: 272095.842891, - responseReceivedTime: 272095.841701, - transferSize: 2777 - } - } - } - }, - 196.3: { - request: { - url: - 'https://varnish-cache.org/docs/6.2/_static/pygments.css', - startTime: 272095.674819, - endTime: 272095.758246, - responseReceivedTime: 272095.75573800004, - transferSize: 1197 - } - }, - 196.4: { - request: { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - startTime: 272095.675119, - endTime: 272095.835399, - responseReceivedTime: 272095.75846800004, - transferSize: 30348 - } - }, - 196.5: { - request: { - url: - 'https://varnish-cache.org/docs/6.2/_static/underscore.js', - startTime: 272095.675376, - endTime: 272095.837817, - responseReceivedTime: 272095.836527, - transferSize: 4369 - } - }, - 196.6: { - request: { - url: - 'https://varnish-cache.org/docs/6.2/_static/doctools.js', - startTime: 272095.675565, - endTime: 272095.840192, - responseReceivedTime: 272095.83908199996, - transferSize: 3562 - } - } - } - } - }, - longestChain: { - duration: 487.1669999556616, - length: 3, - transferSize: 2777 - } - } - }, - redirects: { - id: 'redirects', - title: 'Avoid multiple page redirects', - description: - 'Redirects introduce additional delays before the page can be loaded. [Learn more](https://web.dev/redirects/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0 - } - }, - 'image-aspect-ratio': { - id: 'image-aspect-ratio', - title: 'Displays images with correct aspect ratio', - description: - 'Image display dimensions should match natural aspect ratio. [Learn more](https://web.dev/image-aspect-ratio/).', - score: 1, - scoreDisplayMode: 'binary', - warnings: [], - details: { type: 'table', headings: [], items: [] } - }, - 'image-size-responsive': { - id: 'image-size-responsive', - title: 'Serves images with appropriate resolution', - description: - 'Image natural dimensions should be proportional to the display size and the pixel ratio to maximize image clarity. [Learn more](https://web.dev/serve-responsive-images/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - deprecations: { - id: 'deprecations', - title: 'Avoids deprecated APIs', - description: - 'Deprecated APIs will eventually be removed from the browser. [Learn more](https://web.dev/deprecations/).', - score: 1, - scoreDisplayMode: 'binary', - displayValue: '', - details: { type: 'table', headings: [], items: [] } - }, - 'mainthread-work-breakdown': { - id: 'mainthread-work-breakdown', - title: 'Minimizes main-thread work', - description: - 'Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/mainthread-work-breakdown/)', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 571.4760000000001, - numericUnit: 'millisecond', - displayValue: '0.6 s', - details: { - type: 'table', - headings: [ - { key: 'groupLabel', itemType: 'text', text: 'Category' }, - { - key: 'duration', - itemType: 'ms', - granularity: 1, - text: 'Time Spent' - } - ], - items: [ - { - group: 'scriptEvaluation', - groupLabel: 'Script Evaluation', - duration: 259.7920000000001 - }, - { - group: 'styleLayout', - groupLabel: 'Style & Layout', - duration: 112.30000000000001 - }, - { - group: 'other', - groupLabel: 'Other', - duration: 111.22000000000001 - }, - { - group: 'parseHTML', - groupLabel: 'Parse HTML & CSS', - duration: 34.96 - }, - { - group: 'paintCompositeRender', - groupLabel: 'Rendering', - duration: 26.72 - }, - { - group: 'scriptParseCompile', - groupLabel: 'Script Parsing & Compilation', - duration: 26.483999999999998 - } - ] - } - }, - 'bootup-time': { - id: 'bootup-time', - title: 'JavaScript execution time', - description: - 'Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/bootup-time/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 265.94399999999996, - numericUnit: 'millisecond', - displayValue: '0.3 s', - details: { - type: 'table', - headings: [ - { key: 'url', itemType: 'url', text: 'URL' }, - { - key: 'total', - granularity: 1, - itemType: 'ms', - text: 'Total CPU Time' - }, - { - key: 'scripting', - granularity: 1, - itemType: 'ms', - text: 'Script Evaluation' - }, - { - key: 'scriptParseCompile', - granularity: 1, - itemType: 'ms', - text: 'Script Parse' - } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - total: 362.62, - scripting: 181.90400000000002, - scriptParseCompile: 4.2 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - total: 122.12799999999996, - scripting: 67.90399999999997, - scriptParseCompile: 11.936 - } - ], - summary: { wastedMs: 265.94399999999996 } - } - }, - 'uses-rel-preload': { - id: 'uses-rel-preload', - title: 'Preload key requests', - description: - 'Consider using `<link rel=preload>` to prioritize fetching resources that are currently requested later in page load. [Learn more](https://web.dev/uses-rel-preload/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0 - } - }, - 'uses-rel-preconnect': { - id: 'uses-rel-preconnect', - title: 'Preconnect to required origins', - description: - 'Consider adding `preconnect` or `dns-prefetch` resource hints to establish early connections to important third-party origins. [Learn more](https://web.dev/uses-rel-preconnect/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0 - } - }, - 'font-display': { - id: 'font-display', - title: 'All text remains visible during webfont loads', - description: - 'Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. [Learn more](https://web.dev/font-display/).', - score: 1, - scoreDisplayMode: 'binary', - warnings: [], - details: { type: 'table', headings: [], items: [] } - }, - diagnostics: { - id: 'diagnostics', - title: 'Diagnostics', - description: 'Collection of useful page vitals.', - score: null, - scoreDisplayMode: 'informative', - details: { - type: 'debugdata', - items: [ - { - numRequests: 7, - numScripts: 3, - numStylesheets: 3, - numFonts: 0, - numTasks: 41, - numTasksOver10ms: 2, - numTasksOver25ms: 2, - numTasksOver50ms: 2, - numTasksOver100ms: 0, - numTasksOver500ms: 0, - rtt: 77.463, - throughput: 4673094.407734089, - maxRtt: 77.463, - maxServerLatency: 1.5600000000000165, - totalByteWeight: 49498, - totalTaskTime: 142.86899999999997, - mainDocumentTransferSize: 5851 - } - ] - } - }, - 'network-requests': { - id: 'network-requests', - title: 'Network Requests', - description: - 'Lists the network requests that were made during page load.', - score: null, - scoreDisplayMode: 'informative', - details: { - type: 'table', - headings: [ - { key: 'url', itemType: 'url', text: 'URL' }, - { - key: 'startTime', - itemType: 'ms', - granularity: 1, - text: 'Start Time' - }, - { - key: 'endTime', - itemType: 'ms', - granularity: 1, - text: 'End Time' - }, - { - key: 'transferSize', - itemType: 'bytes', - displayUnit: 'kb', - granularity: 1, - text: 'Transfer Size' - }, - { - key: 'resourceSize', - itemType: 'bytes', - displayUnit: 'kb', - granularity: 1, - text: 'Resource Size' - }, - { key: 'statusCode', itemType: 'text', text: 'Status Code' }, - { key: 'mimeType', itemType: 'text', text: 'MIME Type' }, - { key: 'resourceType', itemType: 'text', text: 'Resource Type' } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - startTime: 0, - endTime: 299.7849999810569, - finished: true, - transferSize: 5851, - resourceSize: 17862, - statusCode: 200, - mimeType: 'text/html', - resourceType: 'Document' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/classic.css', - startTime: 317.60700000450015, - endTime: 399.6509999851696, - finished: true, - transferSize: 1394, - resourceSize: 4142, - statusCode: 200, - mimeType: 'text/css', - resourceType: 'Stylesheet' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/pygments.css', - startTime: 319.0949999843724, - endTime: 402.5219999602996, - finished: true, - transferSize: 1197, - resourceSize: 4395, - statusCode: 200, - mimeType: 'text/css', - resourceType: 'Stylesheet' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - startTime: 319.39499999862164, - endTime: 479.67499995138496, - finished: true, - transferSize: 30348, - resourceSize: 86351, - statusCode: 200, - mimeType: 'application/x-javascript', - resourceType: 'Script' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/underscore.js', - startTime: 319.65199997648597, - endTime: 482.0929999696091, - finished: true, - transferSize: 4369, - resourceSize: 12140, - statusCode: 200, - mimeType: 'application/x-javascript', - resourceType: 'Script' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/doctools.js', - startTime: 319.8409999604337, - endTime: 484.4679999514483, - finished: true, - transferSize: 3562, - resourceSize: 9131, - statusCode: 200, - mimeType: 'application/x-javascript', - resourceType: 'Script' - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/basic.css', - startTime: 406.55299997888505, - endTime: 487.1669999556616, - finished: true, - transferSize: 2777, - resourceSize: 10362, - statusCode: 200, - mimeType: 'text/css', - resourceType: 'Stylesheet' - } - ] - } - }, - 'network-rtt': { - id: 'network-rtt', - title: 'Network Round Trip Times', - description: - "Network round trip times (RTT) have a large impact on performance. If the RTT to an origin is high, it's an indication that servers closer to the user could improve performance. [Learn more](https://hpbn.co/primer-on-latency-and-bandwidth/).", - score: null, - scoreDisplayMode: 'informative', - numericValue: 77.463, - numericUnit: 'millisecond', - displayValue: '80 ms', - details: { - type: 'table', - headings: [ - { key: 'origin', itemType: 'text', text: 'URL' }, - { key: 'rtt', itemType: 'ms', granularity: 1, text: 'Time Spent' } - ], - items: [{ origin: 'https://varnish-cache.org', rtt: 77.463 }] - } - }, - 'network-server-latency': { - id: 'network-server-latency', - title: 'Server Backend Latencies', - description: - "Server latencies can impact web performance. If the server latency of an origin is high, it's an indication the server is overloaded or has poor backend performance. [Learn more](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall).", - score: null, - scoreDisplayMode: 'informative', - numericValue: 1.5600000000000165, - numericUnit: 'millisecond', - displayValue: '0 ms', - details: { - type: 'table', - headings: [ - { key: 'origin', itemType: 'text', text: 'URL' }, - { - key: 'serverResponseTime', - itemType: 'ms', - granularity: 1, - text: 'Time Spent' - } - ], - items: [ - { - origin: 'https://varnish-cache.org', - serverResponseTime: 1.5600000000000165 - } - ] - } - }, - 'main-thread-tasks': { - id: 'main-thread-tasks', - title: 'Tasks', - description: - 'Lists the toplevel main thread tasks that executed during page load.', - score: null, - scoreDisplayMode: 'informative', - details: { - type: 'table', - headings: [ - { - key: 'startTime', - itemType: 'ms', - granularity: 1, - text: 'Start Time' - }, - { - key: 'duration', - itemType: 'ms', - granularity: 1, - text: 'End Time' - } - ], - items: [ - { duration: 7.996, startTime: 312.457 }, - { duration: 5.404, startTime: 409.034 }, - { duration: 55.698, startTime: 495.974 }, - { duration: 52.592, startTime: 551.991 } - ] - } - }, - metrics: { - id: 'metrics', - title: 'Metrics', - description: 'Collects all available metrics.', - score: null, - scoreDisplayMode: 'informative', - numericValue: 1215, - numericUnit: 'millisecond', - details: { - type: 'debugdata', - items: [ - { - firstContentfulPaint: 1163, - firstMeaningfulPaint: 1215, - largestContentfulPaint: 1215, - firstCPUIdle: 1215, - interactive: 1215, - speedIndex: 1346, - estimatedInputLatency: 13, - totalBlockingTime: 28, - maxPotentialFID: 111, - cumulativeLayoutShift: 0, - observedNavigationStart: 0, - observedNavigationStartTs: 272095354750, - observedFirstPaint: 584, - observedFirstPaintTs: 272095938263, - observedFirstContentfulPaint: 584, - observedFirstContentfulPaintTs: 272095938263, - observedFirstMeaningfulPaint: 584, - observedFirstMeaningfulPaintTs: 272095938263, - observedLargestContentfulPaint: 584, - observedLargestContentfulPaintTs: 272095938263, - observedTraceEnd: 1658, - observedTraceEndTs: 272097012365, - observedLoad: 592, - observedLoadTs: 272095947097, - observedDomContentLoaded: 592, - observedDomContentLoadedTs: 272095946415, - observedCumulativeLayoutShift: 0, - observedFirstVisualChange: 560, - observedFirstVisualChangeTs: 272095914750, - observedLastVisualChange: 610, - observedLastVisualChangeTs: 272095964750, - observedSpeedIndex: 576, - observedSpeedIndexTs: 272095930726 - }, - { lcpInvalidated: false } - ] - } - }, - 'performance-budget': { - id: 'performance-budget', - title: 'Performance budget', - description: - 'Keep the quantity and size of network requests under the targets set by the provided performance budget. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'timing-budget': { - id: 'timing-budget', - title: 'Timing budget', - description: - 'Set a timing budget to help you keep an eye on the performance of your site. Performant sites load fast and respond to user input events quickly. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'resource-summary': { - id: 'resource-summary', - title: 'Keep request counts low and transfer sizes small', - description: - 'To set budgets for the quantity and size of page resources, add a budget.json file. [Learn more](https://web.dev/use-lighthouse-for-performance-budgets/).', - score: null, - scoreDisplayMode: 'informative', - displayValue: '7 requests • 48 KiB', - details: { - type: 'table', - headings: [ - { key: 'label', itemType: 'text', text: 'Resource Type' }, - { key: 'requestCount', itemType: 'numeric', text: 'Requests' }, - { key: 'transferSize', itemType: 'bytes', text: 'Transfer Size' } - ], - items: [ - { - resourceType: 'total', - label: 'Total', - requestCount: 7, - transferSize: 49498 - }, - { - resourceType: 'script', - label: 'Script', - requestCount: 3, - transferSize: 38279 - }, - { - resourceType: 'document', - label: 'Document', - requestCount: 1, - transferSize: 5851 - }, - { - resourceType: 'stylesheet', - label: 'Stylesheet', - requestCount: 3, - transferSize: 5368 - }, - { - resourceType: 'image', - label: 'Image', - requestCount: 0, - transferSize: 0 - }, - { - resourceType: 'media', - label: 'Media', - requestCount: 0, - transferSize: 0 - }, - { - resourceType: 'font', - label: 'Font', - requestCount: 0, - transferSize: 0 - }, - { - resourceType: 'other', - label: 'Other', - requestCount: 0, - transferSize: 0 - }, - { - resourceType: 'third-party', - label: 'Third-party', - requestCount: 0, - transferSize: 0 - } - ] - } - }, - 'third-party-summary': { - id: 'third-party-summary', - title: 'Minimize third-party usage', - description: - 'Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'largest-contentful-paint-element': { - id: 'largest-contentful-paint-element', - title: 'Largest Contentful Paint element', - description: - 'This is the largest contentful element painted within the viewport. [Learn More](https://web.dev/lighthouse-largest-contentful-paint/)', - score: null, - scoreDisplayMode: 'informative', - displayValue: '1 element found', - details: { - type: 'table', - headings: [{ key: 'node', itemType: 'node', text: 'Element' }], - items: [ - { - node: { - type: 'node', - path: '1,HTML,1,BODY,1,DIV,0,DIV,0,DIV,0,DIV,0,DIV,18,DIV,2,P', - selector: - 'div.body > div#going-fast-slowly > div#anyway-what-do-programmers-do-all-day > p', - nodeLabel: - 'Back before the dot-com disaster, people had actually spent considerable time a…', - snippet: '<p>' - } - } - ] - } - }, - 'layout-shift-elements': { - id: 'layout-shift-elements', - title: 'Avoid large layout shifts', - description: - 'These DOM elements contribute most to the CLS of the page.', - score: null, - scoreDisplayMode: 'notApplicable', - details: { type: 'table', headings: [], items: [] } - }, - 'long-tasks': { - id: 'long-tasks', - title: 'Avoid long main-thread tasks', - description: - 'Lists the longest tasks on the main thread, useful for identifying worst contributors to input delay. [Learn more](https://web.dev/long-tasks-devtools/)', - score: null, - scoreDisplayMode: 'informative', - displayValue: '2 long tasks found', - details: { - type: 'table', - headings: [ - { key: 'url', itemType: 'url', text: 'URL' }, - { - key: 'startTime', - itemType: 'ms', - granularity: 1, - text: 'Start Time' - }, - { - key: 'duration', - itemType: 'ms', - granularity: 1, - text: 'Duration' - } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - duration: 111, - startTime: 1156.56 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - duration: 105, - startTime: 1051.56 - } - ] - } - }, - accesskeys: { - id: 'accesskeys', - title: '`[accesskey]` values are unique', - description: - 'Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://web.dev/accesskeys/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-allowed-attr': { - id: 'aria-allowed-attr', - title: '`[aria-*]` attributes match their roles', - description: - 'Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn more](https://web.dev/aria-allowed-attr/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-hidden-body': { - id: 'aria-hidden-body', - title: '`[aria-hidden="true"]` is not present on the document `<body>`', - description: - 'Assistive technologies, like screen readers, work inconsistently when `aria-hidden="true"` is set on the document `<body>`. [Learn more](https://web.dev/aria-hidden-body/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-hidden-focus': { - id: 'aria-hidden-focus', - title: - '`[aria-hidden="true"]` elements do not contain focusable descendents', - description: - 'Focusable descendents within an `[aria-hidden="true"]` element prevent those interactive elements from being available to users of assistive technologies like screen readers. [Learn more](https://web.dev/aria-hidden-focus/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'aria-input-field-name': { - id: 'aria-input-field-name', - title: 'ARIA input fields have accessible names', - description: - "When an input field doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more](https://web.dev/aria-input-field-name/).", - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'aria-required-attr': { - id: 'aria-required-attr', - title: '`[role]`s have all required `[aria-*]` attributes', - description: - 'Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more](https://web.dev/aria-required-attr/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-required-children': { - id: 'aria-required-children', - title: - 'Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children.', - description: - 'Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-children/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-required-parent': { - id: 'aria-required-parent', - title: '`[role]`s are contained by their required parent element', - description: - 'Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-parent/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-roles': { - id: 'aria-roles', - title: '`[role]` values are valid', - description: - 'ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more](https://web.dev/aria-roles/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-toggle-field-name': { - id: 'aria-toggle-field-name', - title: 'ARIA toggle fields have accessible names', - description: - "When a toggle field doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more](https://web.dev/aria-toggle-field-name/).", - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'aria-valid-attr-value': { - id: 'aria-valid-attr-value', - title: '`[aria-*]` attributes have valid values', - description: - "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid values. [Learn more](https://web.dev/aria-valid-attr-value/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'aria-valid-attr': { - id: 'aria-valid-attr', - title: '`[aria-*]` attributes are valid and not misspelled', - description: - "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid names. [Learn more](https://web.dev/aria-valid-attr/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'button-name': { - id: 'button-name', - title: 'Buttons have an accessible name', - description: - 'When a button doesn\'t have an accessible name, screen readers announce it as "button", making it unusable for users who rely on screen readers. [Learn more](https://web.dev/button-name/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - bypass: { - id: 'bypass', - title: 'The page contains a heading, skip link, or landmark region', - description: - 'Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more](https://web.dev/bypass/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'color-contrast': { - id: 'color-contrast', - title: - 'Background and foreground colors do not have a sufficient contrast ratio.', - description: - 'Low-contrast text is difficult or impossible for many users to read. [Learn more](https://web.dev/color-contrast/).', - score: 0, - scoreDisplayMode: 'binary', - details: { - type: 'table', - headings: [ - { key: 'node', itemType: 'node', text: 'Failing Elements' } - ], - items: [ - { - node: { - type: 'node', - selector: 'a[accesskey="I"]', - path: '1,HTML,1,BODY,0,DIV,1,UL,0,LI,0,A', - snippet: - '<a href="../genindex.html" title="General Index" accesskey="I">index</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'index' - } - }, - { - node: { - type: 'node', - selector: 'a[accesskey="N"]', - path: '1,HTML,1,BODY,0,DIV,1,UL,1,LI,0,A', - snippet: - '<a href="firstdesign.html" title="The first design of Varnish" accesskey="N">next</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'next' - } - }, - { - node: { - type: 'node', - selector: 'a[accesskey="P"]', - path: '1,HTML,1,BODY,0,DIV,1,UL,2,LI,0,A', - snippet: - '<a href="farfaraway.html" title="Far, far away" accesskey="P">previous</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'previous' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(1) > ul > .nav-item-0.nav-item > a[href="\\.\\.\\/index\\.html"]', - path: '1,HTML,1,BODY,0,DIV,1,UL,3,LI,0,A', - snippet: - '<a href="../index.html">Varnish version 6.2.3 documentation</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'Varnish version 6.2.3 documentation' - } - }, - { - node: { - type: 'node', - selector: 'a[accesskey="U"]', - path: '1,HTML,1,BODY,0,DIV,1,UL,4,LI,0,A', - snippet: - '<a href="index.html" accesskey="U">Poul-Hennings random outbursts</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'Poul-Hennings random outbursts' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(3) > ul > .right:nth-child(1) > a[title="General\\ Index"][href="\\.\\.\\/genindex\\.html"]', - path: '1,HTML,1,BODY,2,DIV,1,UL,0,LI,0,A', - snippet: - '<a href="../genindex.html" title="General Index">index</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'index' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(3) > ul > .right:nth-child(2) > a[title="The\\ first\\ design\\ of\\ Varnish"][href$="firstdesign\\.html"]', - path: '1,HTML,1,BODY,2,DIV,1,UL,1,LI,0,A', - snippet: - '<a href="firstdesign.html" title="The first design of Varnish">next</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'next' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(3) > ul > .right:nth-child(3) > a[title="Far\\,\\ far\\ away"][href$="farfaraway\\.html"]', - path: '1,HTML,1,BODY,2,DIV,1,UL,2,LI,0,A', - snippet: - '<a href="farfaraway.html" title="Far, far away">previous</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'previous' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(3) > ul > .nav-item-0.nav-item > a[href="\\.\\.\\/index\\.html"]', - path: '1,HTML,1,BODY,2,DIV,1,UL,3,LI,0,A', - snippet: - '<a href="../index.html">Varnish version 6.2.3 documentation</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'Varnish version 6.2.3 documentation' - } - }, - { - node: { - type: 'node', - selector: - '.related[aria-label="related\\ navigation"][role="navigation"]:nth-child(3) > ul > .nav-item-1.nav-item > a[href="index\\.html"]', - path: '1,HTML,1,BODY,2,DIV,1,UL,4,LI,0,A', - snippet: - '<a href="index.html">Poul-Hennings random outbursts</a>', - explanation: - 'Fix any of the following:\n Element has insufficient color contrast of 4.31 (foreground color: #ffffff, background color: #437eb2, font size: 10.8pt (14.4px), font weight: normal). Expected contrast ratio of 4.5:1', - nodeLabel: 'Poul-Hennings random outbursts' - } - } - ], - debugData: { - type: 'debugdata', - impact: 'serious', - tags: ['cat.color', 'wcag2aa', 'wcag143'] - } - } - }, - 'definition-list': { - id: 'definition-list', - title: - "`<dl>`'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>`, `<template>` or `<div>` elements.", - description: - 'When definition lists are not properly marked up, screen readers may produce confusing or inaccurate output. [Learn more](https://web.dev/definition-list/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - dlitem: { - id: 'dlitem', - title: 'Definition list items are wrapped in `<dl>` elements', - description: - 'Definition list items (`<dt>` and `<dd>`) must be wrapped in a parent `<dl>` element to ensure that screen readers can properly announce them. [Learn more](https://web.dev/dlitem/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'document-title': { - id: 'document-title', - title: 'Document has a `<title>` element', - description: - 'The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://web.dev/document-title/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'duplicate-id-active': { - id: 'duplicate-id-active', - title: '`[id]` attributes on active, focusable elements are unique', - description: - "All focusable elements must have a unique `id` to ensure that they're visible to assistive technologies. [Learn more](https://web.dev/duplicate-id-active/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'duplicate-id-aria': { - id: 'duplicate-id-aria', - title: 'ARIA IDs are unique', - description: - 'The value of an ARIA ID must be unique to prevent other instances from being overlooked by assistive technologies. [Learn more](https://web.dev/duplicate-id-aria/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'form-field-multiple-labels': { - id: 'form-field-multiple-labels', - title: 'No form fields have multiple labels', - description: - 'Form fields with multiple labels can be confusingly announced by assistive technologies like screen readers which use either the first, the last, or all of the labels. [Learn more](https://web.dev/form-field-multiple-labels/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'frame-title': { - id: 'frame-title', - title: '`<frame>` or `<iframe>` elements have a title', - description: - 'Screen reader users rely on frame titles to describe the contents of frames. [Learn more](https://web.dev/frame-title/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'heading-order': { - id: 'heading-order', - title: 'Heading elements appear in a sequentially-descending order', - description: - 'Properly ordered headings that do not skip levels convey the semantic structure of the page, making it easier to navigate and understand when using assistive technologies. [Learn more](https://web.dev/heading-order/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'html-has-lang': { - id: 'html-has-lang', - title: '`<html>` element does not have a `[lang]` attribute', - description: - "If a page doesn't specify a lang attribute, a screen reader assumes that the page is in the default language that the user chose when setting up the screen reader. If the page isn't actually in the default language, then the screen reader might not announce the page's text correctly. [Learn more](https://web.dev/html-has-lang/).", - score: 0, - scoreDisplayMode: 'binary', - details: { - type: 'table', - headings: [ - { key: 'node', itemType: 'node', text: 'Failing Elements' } - ], - items: [ - { - node: { - type: 'node', - selector: 'html', - path: '1,HTML', - snippet: '<html xmlns="http://www.w3.org/1999/xhtml">', - explanation: - 'Fix any of the following:\n The <html> element does not have a lang attribute', - nodeLabel: 'html' - } - } - ], - debugData: { - type: 'debugdata', - impact: 'serious', - tags: ['cat.language', 'wcag2a', 'wcag311'] - } - } - }, - 'html-lang-valid': { - id: 'html-lang-valid', - title: '`<html>` element has a valid value for its `[lang]` attribute', - description: - 'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) helps screen readers announce text properly. [Learn more](https://web.dev/html-lang-valid/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'image-alt': { - id: 'image-alt', - title: 'Image elements have `[alt]` attributes', - description: - 'Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://web.dev/image-alt/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'input-image-alt': { - id: 'input-image-alt', - title: '`<input type="image">` elements have `[alt]` text', - description: - 'When an image is being used as an `<input>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn more](https://web.dev/input-image-alt/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - label: { - id: 'label', - title: 'Form elements do not have associated labels', - description: - 'Labels ensure that form controls are announced properly by assistive technologies, like screen readers. [Learn more](https://web.dev/label/).', - score: 0, - scoreDisplayMode: 'binary', - details: { - type: 'table', - headings: [ - { key: 'node', itemType: 'node', text: 'Failing Elements' } - ], - items: [ - { - node: { - type: 'node', - selector: 'input[type="text"]', - path: - '1,HTML,1,BODY,1,DIV,1,DIV,0,DIV,7,DIV,1,FORM,0,DIV,0,INPUT', - snippet: '<input type="text" name="q">', - explanation: - 'Fix any of the following:\n aria-label attribute does not exist or is empty\n aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty\n Form element does not have an implicit (wrapped) <label>\n Form element does not have an explicit <label>\n Element has no title attribute or the title attribute is empty', - nodeLabel: 'input' - } - } - ], - debugData: { - type: 'debugdata', - impact: 'critical', - tags: [ - 'cat.forms', - 'wcag2a', - 'wcag412', - 'wcag131', - 'section508', - 'section508.22.n' - ] - } - } - }, - 'layout-table': { - id: 'layout-table', - title: - 'Presentational `<table>` elements avoid using `<th>`, `<caption>` or the `[summary]` attribute.', - description: - 'A table being used for layout purposes should not include data elements, such as the th or caption elements or the summary attribute, because this can create a confusing experience for screen reader users. [Learn more](https://web.dev/layout-table/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'link-name': { - id: 'link-name', - title: 'Links have a discernible name', - description: - 'Link text (and alternate text for images, when used as links) that is discernible, unique, and focusable improves the navigation experience for screen reader users. [Learn more](https://web.dev/link-name/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - list: { - id: 'list', - title: - 'Lists contain only `<li>` elements and script supporting elements (`<script>` and `<template>`).', - description: - 'Screen readers have a specific way of announcing lists. Ensuring proper list structure aids screen reader output. [Learn more](https://web.dev/list/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - listitem: { - id: 'listitem', - title: - 'List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements', - description: - 'Screen readers require list items (`<li>`) to be contained within a parent `<ul>` or `<ol>` to be announced properly. [Learn more](https://web.dev/listitem/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'meta-refresh': { - id: 'meta-refresh', - title: 'The document does not use `<meta http-equiv="refresh">`', - description: - 'Users do not expect a page to refresh automatically, and doing so will move focus back to the top of the page. This may create a frustrating or confusing experience. [Learn more](https://web.dev/meta-refresh/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'meta-viewport': { - id: 'meta-viewport', - title: - '`[user-scalable="no"]` is not used in the `<meta name="viewport">` element and the `[maximum-scale]` attribute is not less than 5.', - description: - 'Disabling zooming is problematic for users with low vision who rely on screen magnification to properly see the contents of a web page. [Learn more](https://web.dev/meta-viewport/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'object-alt': { - id: 'object-alt', - title: '`<object>` elements have `[alt]` text', - description: - 'Screen readers cannot translate non-text content. Adding alt text to `<object>` elements helps screen readers convey meaning to users. [Learn more](https://web.dev/object-alt/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - tabindex: { - id: 'tabindex', - title: 'No element has a `[tabindex]` value greater than 0', - description: - 'A value greater than 0 implies an explicit navigation ordering. Although technically valid, this often creates frustrating experiences for users who rely on assistive technologies. [Learn more](https://web.dev/tabindex/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'td-headers-attr': { - id: 'td-headers-attr', - title: - 'Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table.', - description: - 'Screen readers have features to make navigating tables easier. Ensuring `<td>` cells using the `[headers]` attribute only refer to other cells in the same table may improve the experience for screen reader users. [Learn more](https://web.dev/td-headers-attr/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'th-has-data-cells': { - id: 'th-has-data-cells', - title: - '`<th>` elements and elements with `[role="columnheader"/"rowheader"]` have data cells they describe.', - description: - 'Screen readers have features to make navigating tables easier. Ensuring table headers always refer to some set of cells may improve the experience for screen reader users. [Learn more](https://web.dev/th-has-data-cells/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'valid-lang': { - id: 'valid-lang', - title: '`[lang]` attributes have a valid value', - description: - 'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) on elements helps ensure that text is pronounced correctly by a screen reader. [Learn more](https://web.dev/valid-lang/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'video-caption': { - id: 'video-caption', - title: - '`<video>` elements contain a `<track>` element with `[kind="captions"]`', - description: - 'When a video provides a caption it is easier for deaf and hearing impaired users to access its information. [Learn more](https://web.dev/video-caption/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'video-description': { - id: 'video-description', - title: - '`<video>` elements contain a `<track>` element with `[kind="description"]`', - description: - 'Audio descriptions provide relevant information for videos that dialogue cannot, such as facial expressions and scenes. [Learn more](https://web.dev/video-description/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'custom-controls-labels': { - id: 'custom-controls-labels', - title: 'Custom controls have associated labels', - description: - 'Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://web.dev/custom-controls-labels/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'custom-controls-roles': { - id: 'custom-controls-roles', - title: 'Custom controls have ARIA roles', - description: - 'Custom interactive controls have appropriate ARIA roles. [Learn more](https://web.dev/custom-control-roles/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'focus-traps': { - id: 'focus-traps', - title: 'User focus is not accidentally trapped in a region', - description: - 'A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://web.dev/focus-traps/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'focusable-controls': { - id: 'focusable-controls', - title: 'Interactive controls are keyboard focusable', - description: - 'Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://web.dev/focusable-controls/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'interactive-element-affordance': { - id: 'interactive-element-affordance', - title: 'Interactive elements indicate their purpose and state', - description: - 'Interactive elements, such as links and buttons, should indicate their state and be distinguishable from non-interactive elements. [Learn more](https://web.dev/interactive-element-affordance/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'logical-tab-order': { - id: 'logical-tab-order', - title: 'The page has a logical tab order', - description: - 'Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://web.dev/logical-tab-order/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'managed-focus': { - id: 'managed-focus', - title: "The user's focus is directed to new content added to the page", - description: - "If new content, such as a dialog, is added to the page, the user's focus is directed to it. [Learn more](https://web.dev/managed-focus/).", - score: null, - scoreDisplayMode: 'manual' - }, - 'offscreen-content-hidden': { - id: 'offscreen-content-hidden', - title: 'Offscreen content is hidden from assistive technology', - description: - 'Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://web.dev/offscreen-content-hidden/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'use-landmarks': { - id: 'use-landmarks', - title: 'HTML5 landmark elements are used to improve navigation', - description: - 'Landmark elements (<main>, <nav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://web.dev/use-landmarks/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'visual-order-follows-dom': { - id: 'visual-order-follows-dom', - title: 'Visual order on the page follows DOM order', - description: - 'DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://web.dev/visual-order-follows-dom/).', - score: null, - scoreDisplayMode: 'manual' - }, - 'uses-long-cache-ttl': { - id: 'uses-long-cache-ttl', - title: 'Serve static assets with an efficient cache policy', - description: - 'A long cache lifetime can speed up repeat visits to your page. [Learn more](https://web.dev/uses-long-cache-ttl/).', - score: 0.89, - scoreDisplayMode: 'numeric', - numericValue: 29679.96, - numericUnit: 'byte', - displayValue: '6 resources found', - details: { - type: 'table', - headings: [ - { key: 'url', itemType: 'url', text: 'URL' }, - { - key: 'cacheLifetimeMs', - itemType: 'ms', - text: 'Cache TTL', - displayUnit: 'duration' - }, - { - key: 'totalBytes', - itemType: 'bytes', - text: 'Transfer Size', - displayUnit: 'kb', - granularity: 1 - } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 30348, - wastedBytes: 20636.64 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/underscore.js', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 4369, - wastedBytes: 2970.9199999999996 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/doctools.js', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 3562, - wastedBytes: 2422.16 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/basic.css', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 2777, - wastedBytes: 1888.36 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/classic.css', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 1394, - wastedBytes: 947.92 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/pygments.css', - debugData: { type: 'debugdata', public: true, 'max-age': 14400 }, - cacheLifetimeMs: 14400000, - cacheHitProbability: 0.32, - totalBytes: 1197, - wastedBytes: 813.9599999999999 - } - ], - summary: { wastedBytes: 29679.96 } - } - }, - 'total-byte-weight': { - id: 'total-byte-weight', - title: 'Avoids enormous network payloads', - description: - 'Large network payloads cost users real money and are highly correlated with long load times. [Learn more](https://web.dev/total-byte-weight/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 49498, - numericUnit: 'byte', - displayValue: 'Total size was 48 KiB', - details: { - type: 'table', - headings: [ - { key: 'url', itemType: 'url', text: 'URL' }, - { key: 'totalBytes', itemType: 'bytes', text: 'Transfer Size' } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - totalBytes: 30348 - }, - { - url: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html', - totalBytes: 5851 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/underscore.js', - totalBytes: 4369 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/doctools.js', - totalBytes: 3562 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/basic.css', - totalBytes: 2777 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/classic.css', - totalBytes: 1394 - }, - { - url: 'https://varnish-cache.org/docs/6.2/_static/pygments.css', - totalBytes: 1197 - } - ] - } - }, - 'offscreen-images': { - id: 'offscreen-images', - title: 'Defer offscreen images', - description: - 'Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. [Learn more](https://web.dev/offscreen-images/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'render-blocking-resources': { - id: 'render-blocking-resources', - title: 'Eliminate render-blocking resources', - description: - 'Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles. [Learn more](https://web.dev/render-blocking-resources/).', - score: 0.7, - scoreDisplayMode: 'numeric', - numericValue: 395, - numericUnit: 'millisecond', - displayValue: 'Potential savings of 400 ms', - details: { - type: 'opportunity', - headings: [ - { key: 'url', valueType: 'url', label: 'URL' }, - { key: 'totalBytes', valueType: 'bytes', label: 'Transfer Size' }, - { - key: 'wastedMs', - valueType: 'timespanMs', - label: 'Potential Savings' - } - ], - items: [ - { - url: 'https://varnish-cache.org/docs/6.2/_static/jquery.js', - totalBytes: 30348, - wastedMs: 300 - } - ], - overallSavingsMs: 395 - } - }, - 'unminified-css': { - id: 'unminified-css', - title: 'Minify CSS', - description: - 'Minifying CSS files can reduce network payload sizes. [Learn more](https://web.dev/unminified-css/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'unminified-javascript': { - id: 'unminified-javascript', - title: 'Minify JavaScript', - description: - 'Minifying JavaScript files can reduce payload sizes and script parse time. [Learn more](https://web.dev/unminified-javascript/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'unused-css-rules': { - id: 'unused-css-rules', - title: 'Remove unused CSS', - description: - 'Remove dead rules from stylesheets and defer the loading of CSS not used for above-the-fold content to reduce unnecessary bytes consumed by network activity. [Learn more](https://web.dev/unused-css-rules/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'unused-javascript': { - id: 'unused-javascript', - title: 'Remove unused JavaScript', - description: - 'Remove unused JavaScript to reduce bytes consumed by network activity. [Learn more](https://web.dev/remove-unused-code/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'uses-webp-images': { - id: 'uses-webp-images', - title: 'Serve images in next-gen formats', - description: - 'Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more](https://web.dev/uses-webp-images/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'uses-optimized-images': { - id: 'uses-optimized-images', - title: 'Efficiently encode images', - description: - 'Optimized images load faster and consume less cellular data. [Learn more](https://web.dev/uses-optimized-images/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'uses-text-compression': { - id: 'uses-text-compression', - title: 'Enable text compression', - description: - 'Text-based resources should be served with compression (gzip, deflate or brotli) to minimize total network bytes. [Learn more](https://web.dev/uses-text-compression/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'uses-responsive-images': { - id: 'uses-responsive-images', - title: 'Properly size images', - description: - 'Serve images that are appropriately-sized to save cellular data and improve load time. [Learn more](https://web.dev/uses-responsive-images/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - warnings: [], - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'efficient-animated-content': { - id: 'efficient-animated-content', - title: 'Use video formats for animated content', - description: - 'Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more](https://web.dev/efficient-animated-content/)', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 0, - numericUnit: 'millisecond', - displayValue: '', - details: { - type: 'opportunity', - headings: [], - items: [], - overallSavingsMs: 0, - overallSavingsBytes: 0 - } - }, - 'appcache-manifest': { - id: 'appcache-manifest', - title: 'Avoids Application Cache', - description: - 'Application Cache is deprecated. [Learn more](https://web.dev/appcache-manifest/).', - score: 1, - scoreDisplayMode: 'binary' - }, - doctype: { - id: 'doctype', - title: 'Page lacks the HTML doctype, thus triggering quirks-mode', - description: - 'Specifying a doctype prevents the browser from switching to quirks-mode. [Learn more](https://web.dev/doctype/).', - score: 0, - scoreDisplayMode: 'binary', - explanation: 'Expected publicId to be an empty string' - }, - charset: { - id: 'charset', - title: 'Properly defines charset', - description: - 'A character encoding declaration is required. It can be done with a <meta> tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more](https://web.dev/charset/).', - score: 1, - scoreDisplayMode: 'binary' - }, - 'dom-size': { - id: 'dom-size', - title: 'Avoids an excessive DOM size', - description: - 'A large DOM will increase memory usage, cause longer [style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://web.dev/dom-size/).', - score: 1, - scoreDisplayMode: 'numeric', - numericValue: 319, - numericUnit: 'element', - displayValue: '319 elements', - details: { - type: 'table', - headings: [ - { key: 'statistic', itemType: 'text', text: 'Statistic' }, - { key: 'element', itemType: 'code', text: 'Element' }, - { key: 'value', itemType: 'numeric', text: 'Value' } - ], - items: [ - { statistic: 'Total DOM Elements', element: '', value: '319' }, - { - statistic: 'Maximum DOM Depth', - element: { - type: 'code', - value: '<a class="fn-backref" href="#id1">' - }, - value: '12' - }, - { - statistic: 'Maximum Child Elements', - element: { type: 'code', value: '<pre>' }, - value: '31' - } - ] - } - }, - 'external-anchors-use-rel-noopener': { - id: 'external-anchors-use-rel-noopener', - title: 'Links to cross-origin destinations are safe', - description: - 'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve performance and prevent security vulnerabilities. [Learn more](https://web.dev/external-anchors-use-rel-noopener/).', - score: 1, - scoreDisplayMode: 'binary', - warnings: [], - details: { type: 'table', headings: [], items: [] } - }, - 'geolocation-on-start': { - id: 'geolocation-on-start', - title: 'Avoids requesting the geolocation permission on page load', - description: - 'Users are mistrustful of or confused by sites that request their location without context. Consider tying the request to a user action instead. [Learn more](https://web.dev/geolocation-on-start/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'no-document-write': { - id: 'no-document-write', - title: 'Avoids `document.write()`', - description: - 'For users on slow connections, external scripts dynamically injected via `document.write()` can delay page load by tens of seconds. [Learn more](https://web.dev/no-document-write/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'no-vulnerable-libraries': { - id: 'no-vulnerable-libraries', - title: - 'Includes front-end JavaScript libraries with known security vulnerabilities', - description: - 'Some third-party scripts may contain known security vulnerabilities that are easily identified and exploited by attackers. [Learn more](https://web.dev/no-vulnerable-libraries/).', - score: 0, - scoreDisplayMode: 'binary', - displayValue: '3 vulnerabilities detected', - details: { - type: 'table', - headings: [ - { key: 'detectedLib', itemType: 'link', text: 'Library Version' }, - { key: 'vulnCount', itemType: 'text', text: 'Vulnerability Count' }, - { - key: 'highestSeverity', - itemType: 'text', - text: 'Highest Severity' - } - ], - items: [ - { - highestSeverity: 'Medium', - vulnCount: 3, - detectedLib: { - text: 'jQuery@3.1.0', - url: - 'https://snyk.io/vuln/npm:jquery?lh=3.1.0&utm_source=lighthouse&utm_medium=ref&utm_campaign=audit', - type: 'link' - } - } - ], - summary: {} - } - }, - 'js-libraries': { - id: 'js-libraries', - title: 'Detected JavaScript libraries', - description: - 'All front-end JavaScript libraries detected on the page. [Learn more](https://web.dev/js-libraries/).', - score: 1, - scoreDisplayMode: 'binary', - details: { - type: 'table', - headings: [ - { key: 'name', itemType: 'text', text: 'Name' }, - { key: 'version', itemType: 'text', text: 'Version' } - ], - items: [{ name: 'jQuery', version: '3.1.0', npm: 'jquery' }], - summary: {}, - debugData: { - type: 'debugdata', - stacks: [{ id: 'jquery', version: '3.1.0' }, { id: 'jquery-fast' }] - } - } - }, - 'notification-on-start': { - id: 'notification-on-start', - title: 'Avoids requesting the notification permission on page load', - description: - 'Users are mistrustful of or confused by sites that request to send notifications without context. Consider tying the request to user gestures instead. [Learn more](https://web.dev/notification-on-start/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'password-inputs-can-be-pasted-into': { - id: 'password-inputs-can-be-pasted-into', - title: 'Allows users to paste into password fields', - description: - 'Preventing password pasting undermines good security policy. [Learn more](https://web.dev/password-inputs-can-be-pasted-into/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'uses-http2': { - id: 'uses-http2', - title: 'Uses HTTP/2 for its own resources', - description: - 'HTTP/2 offers many benefits over HTTP/1.1, including binary headers, multiplexing, and server push. [Learn more](https://web.dev/uses-http2/).', - score: 1, - scoreDisplayMode: 'binary', - displayValue: '', - details: { type: 'table', headings: [], items: [] } - }, - 'uses-passive-event-listeners': { - id: 'uses-passive-event-listeners', - title: 'Uses passive listeners to improve scrolling performance', - description: - "Consider marking your touch and wheel event listeners as `passive` to improve your page's scroll performance. [Learn more](https://web.dev/uses-passive-event-listeners/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'meta-description': { - id: 'meta-description', - title: 'Document does not have a meta description', - description: - 'Meta descriptions may be included in search results to concisely summarize page content. [Learn more](https://web.dev/meta-description/).', - score: 0, - scoreDisplayMode: 'binary' - }, - 'http-status-code': { - id: 'http-status-code', - title: 'Page has successful HTTP status code', - description: - 'Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://web.dev/http-status-code/).', - score: 1, - scoreDisplayMode: 'binary' - }, - 'font-size': { - id: 'font-size', - title: 'Document uses legible font sizes', - description: - 'Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://web.dev/font-size/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'link-text': { - id: 'link-text', - title: 'Links have descriptive text', - description: - 'Descriptive link text helps search engines understand your content. [Learn more](https://web.dev/link-text/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [], summary: {} } - }, - 'crawlable-anchors': { - id: 'crawlable-anchors', - title: 'Links are crawlable', - description: - 'Search engines may use `href` attributes on links to crawl websites. Ensure that the `href` attribute of anchor elements links to an appropriate destination, so more pages of the site can be discovered. [Learn More](https://support.google.com/webmasters/answer/9112205)', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'is-crawlable': { - id: 'is-crawlable', - title: 'Page isn’t blocked from indexing', - description: - "Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://web.dev/is-crawable/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - 'robots-txt': { - id: 'robots-txt', - title: 'robots.txt is valid', - description: - 'If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed. [Learn more](https://web.dev/robots-txt/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [], summary: {} } - }, - 'tap-targets': { - id: 'tap-targets', - title: 'Tap targets are sized appropriately', - description: - 'Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://web.dev/tap-targets/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - hreflang: { - id: 'hreflang', - title: 'Document has a valid `hreflang`', - description: - 'hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://web.dev/hreflang/).', - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - plugins: { - id: 'plugins', - title: 'Document avoids plugins', - description: - "Search engines can't index plugin content, and many devices restrict plugins or don't support them. [Learn more](https://web.dev/plugins/).", - score: 1, - scoreDisplayMode: 'binary', - details: { type: 'table', headings: [], items: [] } - }, - canonical: { - id: 'canonical', - title: 'Document has a valid `rel=canonical`', - description: - 'Canonical links suggest which URL to show in search results. [Learn more](https://web.dev/canonical/).', - score: null, - scoreDisplayMode: 'notApplicable' - }, - 'structured-data': { - id: 'structured-data', - title: 'Structured data is valid', - description: - 'Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://web.dev/structured-data/).', - score: null, - scoreDisplayMode: 'manual' - } - }, - configSettings: { - output: 'json', - maxWaitForFcp: 30000, - maxWaitForLoad: 16666.4, - throttlingMethod: 'simulate', - throttling: { - rttMs: 150, - throughputKbps: 1638.4, - requestLatencyMs: 562.5, - downloadThroughputKbps: 1474.5600000000002, - uploadThroughputKbps: 675, - cpuSlowdownMultiplier: 4 - }, - auditMode: false, - gatherMode: false, - disableStorageReset: true, - emulatedFormFactor: 'desktop', - internalDisableDeviceScreenEmulation: false, - channel: 'node', - budgets: null, - locale: 'en-US', - blockedUrlPatterns: null, - additionalTraceCategories: null, - extraHeaders: null, - precomputedLanternData: null, - onlyAudits: null, - onlyCategories: ['performance', 'best-practices', 'accessibility', 'seo'], - skipAudits: null - }, - categories: { - performance: { - title: 'Performance', - auditRefs: [ - { id: 'first-contentful-paint', weight: 15, group: 'metrics' }, - { id: 'speed-index', weight: 15, group: 'metrics' }, - { id: 'largest-contentful-paint', weight: 25, group: 'metrics' }, - { id: 'interactive', weight: 15, group: 'metrics' }, - { id: 'total-blocking-time', weight: 25, group: 'metrics' }, - { id: 'cumulative-layout-shift', weight: 5, group: 'metrics' }, - { id: 'first-cpu-idle', weight: 0 }, - { id: 'max-potential-fid', weight: 0 }, - { id: 'first-meaningful-paint', weight: 0 }, - { id: 'estimated-input-latency', weight: 0 }, - { - id: 'render-blocking-resources', - weight: 0, - group: 'load-opportunities' - }, - { - id: 'uses-responsive-images', - weight: 0, - group: 'load-opportunities' - }, - { id: 'offscreen-images', weight: 0, group: 'load-opportunities' }, - { id: 'unminified-css', weight: 0, group: 'load-opportunities' }, - { - id: 'unminified-javascript', - weight: 0, - group: 'load-opportunities' - }, - { id: 'unused-css-rules', weight: 0, group: 'load-opportunities' }, - { id: 'unused-javascript', weight: 0, group: 'load-opportunities' }, - { - id: 'uses-optimized-images', - weight: 0, - group: 'load-opportunities' - }, - { id: 'uses-webp-images', weight: 0, group: 'load-opportunities' }, - { - id: 'uses-text-compression', - weight: 0, - group: 'load-opportunities' - }, - { id: 'uses-rel-preconnect', weight: 0, group: 'load-opportunities' }, - { - id: 'server-response-time', - weight: 0, - group: 'load-opportunities' - }, - { id: 'redirects', weight: 0, group: 'load-opportunities' }, - { id: 'uses-rel-preload', weight: 0, group: 'load-opportunities' }, - { - id: 'efficient-animated-content', - weight: 0, - group: 'load-opportunities' - }, - { id: 'total-byte-weight', weight: 0, group: 'diagnostics' }, - { id: 'uses-long-cache-ttl', weight: 0, group: 'diagnostics' }, - { id: 'dom-size', weight: 0, group: 'diagnostics' }, - { id: 'critical-request-chains', weight: 0, group: 'diagnostics' }, - { id: 'user-timings', weight: 0, group: 'diagnostics' }, - { id: 'bootup-time', weight: 0, group: 'diagnostics' }, - { id: 'mainthread-work-breakdown', weight: 0, group: 'diagnostics' }, - { id: 'font-display', weight: 0, group: 'diagnostics' }, - { id: 'performance-budget', weight: 0, group: 'budgets' }, - { id: 'timing-budget', weight: 0, group: 'budgets' }, - { id: 'resource-summary', weight: 0, group: 'diagnostics' }, - { id: 'third-party-summary', weight: 0, group: 'diagnostics' }, - { - id: 'largest-contentful-paint-element', - weight: 0, - group: 'diagnostics' - }, - { id: 'layout-shift-elements', weight: 0, group: 'diagnostics' }, - { id: 'uses-http2', weight: 0, group: 'diagnostics' }, - { - id: 'uses-passive-event-listeners', - weight: 0, - group: 'diagnostics' - }, - { id: 'no-document-write', weight: 0, group: 'diagnostics' }, - { id: 'long-tasks', weight: 0, group: 'diagnostics' }, - { id: 'network-requests', weight: 0 }, - { id: 'network-rtt', weight: 0 }, - { id: 'network-server-latency', weight: 0 }, - { id: 'main-thread-tasks', weight: 0 }, - { id: 'diagnostics', weight: 0 }, - { id: 'metrics', weight: 0 }, - { id: 'screenshot-thumbnails', weight: 0 }, - { id: 'final-screenshot', weight: 0 } - ], - id: 'performance', - score: 0.93 - }, - accessibility: { - title: 'Accessibility', - description: - 'These checks highlight opportunities to [improve the accessibility of your web app](https://developers.google.com/web/fundamentals/accessibility). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged.', - manualDescription: - 'These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review).', - auditRefs: [ - { id: 'accesskeys', weight: 3, group: 'a11y-navigation' }, - { id: 'aria-allowed-attr', weight: 10, group: 'a11y-aria' }, - { id: 'aria-hidden-body', weight: 10, group: 'a11y-aria' }, - { id: 'aria-hidden-focus', weight: 0, group: 'a11y-aria' }, - { id: 'aria-input-field-name', weight: 0, group: 'a11y-aria' }, - { id: 'aria-required-attr', weight: 10, group: 'a11y-aria' }, - { id: 'aria-required-children', weight: 10, group: 'a11y-aria' }, - { id: 'aria-required-parent', weight: 10, group: 'a11y-aria' }, - { id: 'aria-roles', weight: 10, group: 'a11y-aria' }, - { id: 'aria-toggle-field-name', weight: 0, group: 'a11y-aria' }, - { id: 'aria-valid-attr-value', weight: 10, group: 'a11y-aria' }, - { id: 'aria-valid-attr', weight: 10, group: 'a11y-aria' }, - { id: 'button-name', weight: 0, group: 'a11y-names-labels' }, - { id: 'bypass', weight: 3, group: 'a11y-navigation' }, - { id: 'color-contrast', weight: 3, group: 'a11y-color-contrast' }, - { id: 'definition-list', weight: 0, group: 'a11y-tables-lists' }, - { id: 'dlitem', weight: 0, group: 'a11y-tables-lists' }, - { id: 'document-title', weight: 3, group: 'a11y-names-labels' }, - { id: 'duplicate-id-active', weight: 3, group: 'a11y-navigation' }, - { id: 'duplicate-id-aria', weight: 0, group: 'a11y-aria' }, - { - id: 'form-field-multiple-labels', - weight: 0, - group: 'a11y-names-labels' - }, - { id: 'frame-title', weight: 0, group: 'a11y-names-labels' }, - { id: 'heading-order', weight: 2, group: 'a11y-navigation' }, - { id: 'html-has-lang', weight: 3, group: 'a11y-language' }, - { id: 'html-lang-valid', weight: 0, group: 'a11y-language' }, - { id: 'image-alt', weight: 0, group: 'a11y-names-labels' }, - { id: 'input-image-alt', weight: 0, group: 'a11y-names-labels' }, - { id: 'label', weight: 10, group: 'a11y-names-labels' }, - { id: 'layout-table', weight: 0, group: 'a11y-tables-lists' }, - { id: 'link-name', weight: 3, group: 'a11y-names-labels' }, - { id: 'list', weight: 3, group: 'a11y-tables-lists' }, - { id: 'listitem', weight: 3, group: 'a11y-tables-lists' }, - { id: 'meta-refresh', weight: 0, group: 'a11y-best-practices' }, - { id: 'meta-viewport', weight: 0, group: 'a11y-best-practices' }, - { id: 'object-alt', weight: 0, group: 'a11y-names-labels' }, - { id: 'tabindex', weight: 0, group: 'a11y-navigation' }, - { id: 'td-headers-attr', weight: 3, group: 'a11y-tables-lists' }, - { id: 'th-has-data-cells', weight: 3, group: 'a11y-tables-lists' }, - { id: 'valid-lang', weight: 0, group: 'a11y-language' }, - { id: 'video-caption', weight: 0, group: 'a11y-audio-video' }, - { id: 'video-description', weight: 0, group: 'a11y-audio-video' }, - { id: 'logical-tab-order', weight: 0 }, - { id: 'focusable-controls', weight: 0 }, - { id: 'interactive-element-affordance', weight: 0 }, - { id: 'managed-focus', weight: 0 }, - { id: 'focus-traps', weight: 0 }, - { id: 'custom-controls-labels', weight: 0 }, - { id: 'custom-controls-roles', weight: 0 }, - { id: 'visual-order-follows-dom', weight: 0 }, - { id: 'offscreen-content-hidden', weight: 0 }, - { id: 'use-landmarks', weight: 0 } - ], - id: 'accessibility', - score: 0.87 - }, - 'best-practices': { - title: 'Best Practices', - auditRefs: [ - { - id: 'is-on-https', - weight: 1, - group: 'best-practices-trust-safety' - }, - { - id: 'external-anchors-use-rel-noopener', - weight: 1, - group: 'best-practices-trust-safety' - }, - { - id: 'geolocation-on-start', - weight: 1, - group: 'best-practices-trust-safety' - }, - { - id: 'notification-on-start', - weight: 1, - group: 'best-practices-trust-safety' - }, - { - id: 'no-vulnerable-libraries', - weight: 1, - group: 'best-practices-trust-safety' - }, - { - id: 'password-inputs-can-be-pasted-into', - weight: 1, - group: 'best-practices-ux' - }, - { id: 'image-aspect-ratio', weight: 1, group: 'best-practices-ux' }, - { - id: 'image-size-responsive', - weight: 1, - group: 'best-practices-ux' - }, - { id: 'doctype', weight: 1, group: 'best-practices-browser-compat' }, - { id: 'charset', weight: 1, group: 'best-practices-browser-compat' }, - { - id: 'appcache-manifest', - weight: 1, - group: 'best-practices-general' - }, - { id: 'js-libraries', weight: 0, group: 'best-practices-general' }, - { id: 'deprecations', weight: 1, group: 'best-practices-general' }, - { - id: 'errors-in-console', - weight: 1, - group: 'best-practices-general' - } - ], - id: 'best-practices', - score: 0.85 - }, - seo: { - title: 'SEO', - description: - 'These checks ensure that your page is optimized for search engine results ranking. There are additional factors Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769).', - manualDescription: - 'Run these additional validators on your site to check additional SEO best practices.', - auditRefs: [ - { id: 'viewport', weight: 1, group: 'seo-mobile' }, - { id: 'document-title', weight: 1, group: 'seo-content' }, - { id: 'meta-description', weight: 1, group: 'seo-content' }, - { id: 'http-status-code', weight: 1, group: 'seo-crawl' }, - { id: 'link-text', weight: 1, group: 'seo-content' }, - { id: 'crawlable-anchors', weight: 1, group: 'seo-crawl' }, - { id: 'is-crawlable', weight: 1, group: 'seo-crawl' }, - { id: 'robots-txt', weight: 1, group: 'seo-crawl' }, - { id: 'image-alt', weight: 0, group: 'seo-content' }, - { id: 'hreflang', weight: 1, group: 'seo-content' }, - { id: 'canonical', weight: 0, group: 'seo-content' }, - { id: 'font-size', weight: 0, group: 'seo-mobile' }, - { id: 'plugins', weight: 1, group: 'seo-content' }, - { id: 'tap-targets', weight: 0, group: 'seo-mobile' }, - { id: 'structured-data', weight: 0 } - ], - id: 'seo', - score: 0.8 - } - }, - categoryGroups: { - metrics: { title: 'Metrics' }, - 'load-opportunities': { - title: 'Opportunities', - description: - "These suggestions can help your page load faster. They don't [directly affect](https://web.dev/performance-scoring/) the Performance score." - }, - budgets: { - title: 'Budgets', - description: - 'Performance budgets set standards for the performance of your site.' - }, - diagnostics: { - title: 'Diagnostics', - description: - "More information about the performance of your application. These numbers don't [directly affect](https://web.dev/performance-scoring/) the Performance score." - }, - 'pwa-fast-reliable': { title: 'Fast and reliable' }, - 'pwa-installable': { title: 'Installable' }, - 'pwa-optimized': { title: 'PWA Optimized' }, - 'a11y-best-practices': { - title: 'Best practices', - description: - 'These items highlight common accessibility best practices.' - }, - 'a11y-color-contrast': { - title: 'Contrast', - description: - 'These are opportunities to improve the legibility of your content.' - }, - 'a11y-names-labels': { - title: 'Names and labels', - description: - 'These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader.' - }, - 'a11y-navigation': { - title: 'Navigation', - description: - 'These are opportunities to improve keyboard navigation in your application.' - }, - 'a11y-aria': { - title: 'ARIA', - description: - 'These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader.' - }, - 'a11y-language': { - title: 'Internationalization and localization', - description: - 'These are opportunities to improve the interpretation of your content by users in different locales.' - }, - 'a11y-audio-video': { - title: 'Audio and video', - description: - 'These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments.' - }, - 'a11y-tables-lists': { - title: 'Tables and lists', - description: - 'These are opportunities to to improve the experience of reading tabular or list data using assistive technology, like a screen reader.' - }, - 'seo-mobile': { - title: 'Mobile Friendly', - description: - 'Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/).' - }, - 'seo-content': { - title: 'Content Best Practices', - description: - 'Format your HTML in a way that enables crawlers to better understand your app’s content.' - }, - 'seo-crawl': { - title: 'Crawling and Indexing', - description: - 'To appear in search results, crawlers need access to your app.' - }, - 'best-practices-trust-safety': { title: 'Trust and Safety' }, - 'best-practices-ux': { title: 'User Experience' }, - 'best-practices-browser-compat': { title: 'Browser Compatibility' }, - 'best-practices-general': { title: 'General' } - }, - timing: { - entries: [ - { - startTime: 353.97, - name: 'lh:init:config', - duration: 303.73, - entryType: 'measure' - }, - { - startTime: 363.24, - name: 'lh:config:requireGatherers', - duration: 38.46, - entryType: 'measure' - }, - { - startTime: 402.13, - name: 'lh:config:requireAudits', - duration: 222.59, - entryType: 'measure' - }, - { - startTime: 658.37, - name: 'lh:runner:run', - duration: 4084.38, - entryType: 'measure' - }, - { - startTime: 660.19, - name: 'lh:init:connect', - duration: 36.62, - entryType: 'measure' - }, - { - startTime: 696.91, - name: 'lh:gather:loadBlank', - duration: 21.92, - entryType: 'measure' - }, - { - startTime: 719.06, - name: 'lh:gather:getVersion', - duration: 0.77, - entryType: 'measure' - }, - { - startTime: 719.96, - name: 'lh:gather:getBenchmarkIndex', - duration: 507.8, - entryType: 'measure' - }, - { - startTime: 1227.94, - name: 'lh:gather:setupDriver', - duration: 12.78, - entryType: 'measure' - }, - { - startTime: 1241.06, - name: 'lh:gather:runPass-defaultPass', - duration: 2549.56, - entryType: 'measure' - }, - { - startTime: 1241.08, - name: 'lh:gather:loadBlank', - duration: 13.79, - entryType: 'measure' - }, - { - startTime: 1255.03, - name: 'lh:gather:setupPassNetwork', - duration: 2.24, - entryType: 'measure' - }, - { - startTime: 1257.42, - name: 'lh:gather:beforePass', - duration: 19.85, - entryType: 'measure' - }, - { - startTime: 1257.47, - name: 'lh:gather:beforePass:CSSUsage', - duration: 0.07, - entryType: 'measure' - }, - { - startTime: 1257.57, - name: 'lh:gather:beforePass:JsUsage', - duration: 13.53, - entryType: 'measure' - }, - { - startTime: 1271.17, - name: 'lh:gather:beforePass:ViewportDimensions', - duration: 0.03, - entryType: 'measure' - }, - { - startTime: 1271.22, - name: 'lh:gather:beforePass:RuntimeExceptions', - duration: 0.14, - entryType: 'measure' - }, - { - startTime: 1271.38, - name: 'lh:gather:beforePass:ConsoleMessages', - duration: 3.74, - entryType: 'measure' - }, - { - startTime: 1275.18, - name: 'lh:gather:beforePass:AnchorElements', - duration: 0.04, - entryType: 'measure' - }, - { - startTime: 1275.24, - name: 'lh:gather:beforePass:ImageElements', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.27, - name: 'lh:gather:beforePass:LinkElements', - duration: 0.03, - entryType: 'measure' - }, - { - startTime: 1275.31, - name: 'lh:gather:beforePass:MetaElements', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.34, - name: 'lh:gather:beforePass:ScriptElements', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.37, - name: 'lh:gather:beforePass:MainDocumentContent', - duration: 0.01, - entryType: 'measure' - }, - { - startTime: 1275.39, - name: 'lh:gather:beforePass:AppCacheManifest', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.42, - name: 'lh:gather:beforePass:Doctype', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.44, - name: 'lh:gather:beforePass:DOMStats', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.47, - name: 'lh:gather:beforePass:OptimizedImages', - duration: 0.01, - entryType: 'measure' - }, - { - startTime: 1275.48, - name: 'lh:gather:beforePass:PasswordInputsWithPreventedPaste', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1275.51, - name: 'lh:gather:beforePass:ResponseCompression', - duration: 0.01, - entryType: 'measure' - }, - { - startTime: 1275.53, - name: 'lh:gather:beforePass:TagsBlockingFirstPaint', - duration: 1.31, - entryType: 'measure' - }, - { - startTime: 1276.87, - name: 'lh:gather:beforePass:FontSize', - duration: 0.03, - entryType: 'measure' - }, - { - startTime: 1276.92, - name: 'lh:gather:beforePass:EmbeddedContent', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1276.95, - name: 'lh:gather:beforePass:RobotsTxt', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1276.97, - name: 'lh:gather:beforePass:TapTargets', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 1277, - name: 'lh:gather:beforePass:Accessibility', - duration: 0.01, - entryType: 'measure' - }, - { - startTime: 1277.02, - name: 'lh:gather:beforePass:TraceElements', - duration: 0.01, - entryType: 'measure' - }, - { - startTime: 1277.05, - name: 'lh:gather:beforePass:SourceMaps', - duration: 0.21, - entryType: 'measure' - }, - { - startTime: 1277.36, - name: 'lh:gather:beginRecording', - duration: 7.4, - entryType: 'measure' - }, - { - startTime: 1277.6, - name: 'lh:gather:getVersion', - duration: 0.91, - entryType: 'measure' - }, - { - startTime: 1285, - name: 'lh:gather:loadPage-defaultPass', - duration: 1662.18, - entryType: 'measure' - }, - { - startTime: 2947.33, - name: 'lh:gather:pass', - duration: 0.33, - entryType: 'measure' - }, - { - startTime: 2947.74, - name: 'lh:gather:getTrace', - duration: 66.24, - entryType: 'measure' - }, - { - startTime: 3013.99, - name: 'lh:gather:getDevtoolsLog', - duration: 0.96, - entryType: 'measure' - }, - { - startTime: 3016.75, - name: 'lh:gather:afterPass', - duration: 773.69, - entryType: 'measure' - }, - { - startTime: 3021.91, - name: 'lh:gather:afterPass:CSSUsage', - duration: 22.87, - entryType: 'measure' - }, - { - startTime: 3044.82, - name: 'lh:gather:afterPass:JsUsage', - duration: 12.46, - entryType: 'measure' - }, - { - startTime: 3057.3, - name: 'lh:gather:afterPass:ViewportDimensions', - duration: 2.85, - entryType: 'measure' - }, - { - startTime: 3060.19, - name: 'lh:gather:afterPass:RuntimeExceptions', - duration: 1.31, - entryType: 'measure' - }, - { - startTime: 3061.52, - name: 'lh:gather:afterPass:ConsoleMessages', - duration: 2.12, - entryType: 'measure' - }, - { - startTime: 3063.67, - name: 'lh:gather:afterPass:AnchorElements', - duration: 50.04, - entryType: 'measure' - }, - { - startTime: 3113.74, - name: 'lh:gather:afterPass:ImageElements', - duration: 10.47, - entryType: 'measure' - }, - { - startTime: 3124.26, - name: 'lh:gather:afterPass:LinkElements', - duration: 4.35, - entryType: 'measure' - }, - { - startTime: 3128.63, - name: 'lh:gather:afterPass:MetaElements', - duration: 3.66, - entryType: 'measure' - }, - { - startTime: 3132.31, - name: 'lh:gather:afterPass:ScriptElements', - duration: 10.06, - entryType: 'measure' - }, - { - startTime: 3142.4, - name: 'lh:gather:afterPass:MainDocumentContent', - duration: 3.7, - entryType: 'measure' - }, - { - startTime: 3146.13, - name: 'lh:gather:afterPass:AppCacheManifest', - duration: 4.15, - entryType: 'measure' - }, - { - startTime: 3150.31, - name: 'lh:gather:afterPass:Doctype', - duration: 3.07, - entryType: 'measure' - }, - { - startTime: 3153.39, - name: 'lh:gather:afterPass:DOMStats', - duration: 8.31, - entryType: 'measure' - }, - { - startTime: 3161.73, - name: 'lh:gather:afterPass:OptimizedImages', - duration: 2.33, - entryType: 'measure' - }, - { - startTime: 3164.08, - name: 'lh:gather:afterPass:PasswordInputsWithPreventedPaste', - duration: 3.5, - entryType: 'measure' - }, - { - startTime: 3167.61, - name: 'lh:gather:afterPass:ResponseCompression', - duration: 3.76, - entryType: 'measure' - }, - { - startTime: 3171.4, - name: 'lh:gather:afterPass:TagsBlockingFirstPaint', - duration: 10.27, - entryType: 'measure' - }, - { - startTime: 3181.7, - name: 'lh:gather:afterPass:FontSize', - duration: 32.77, - entryType: 'measure' - }, - { - startTime: 3214.49, - name: 'lh:gather:afterPass:EmbeddedContent', - duration: 5.5, - entryType: 'measure' - }, - { - startTime: 3220.02, - name: 'lh:gather:afterPass:RobotsTxt', - duration: 83.77, - entryType: 'measure' - }, - { - startTime: 3303.81, - name: 'lh:gather:afterPass:TapTargets', - duration: 12.42, - entryType: 'measure' - }, - { - startTime: 3316.26, - name: 'lh:gather:afterPass:Accessibility', - duration: 462.38, - entryType: 'measure' - }, - { - startTime: 3778.66, - name: 'lh:gather:afterPass:TraceElements', - duration: 9.94, - entryType: 'measure' - }, - { - startTime: 3788.61, - name: 'lh:gather:afterPass:SourceMaps', - duration: 1.81, - entryType: 'measure' - }, - { - startTime: 3892.95, - name: 'lh:gather:disconnect', - duration: 2.39, - entryType: 'measure' - }, - { - startTime: 3895.63, - name: 'lh:runner:auditing', - duration: 844.81, - entryType: 'measure' - }, - { - startTime: 3899.34, - name: 'lh:audit:is-on-https', - duration: 1.21, - entryType: 'measure' - }, - { - startTime: 3899.63, - name: 'lh:computed:NetworkRecords', - duration: 0.47, - entryType: 'measure' - }, - { - startTime: 3900.98, - name: 'lh:audit:viewport', - duration: 0.39, - entryType: 'measure' - }, - { - startTime: 3901.12, - name: 'lh:computed:ViewportMeta', - duration: 0.12, - entryType: 'measure' - }, - { - startTime: 3901.61, - name: 'lh:audit:first-contentful-paint', - duration: 15.76, - entryType: 'measure' - }, - { - startTime: 3901.81, - name: 'lh:computed:FirstContentfulPaint', - duration: 15.25, - entryType: 'measure' - }, - { - startTime: 3901.92, - name: 'lh:computed:TraceOfTab', - duration: 4.69, - entryType: 'measure' - }, - { - startTime: 3906.8, - name: 'lh:computed:LanternFirstContentfulPaint', - duration: 10.25, - entryType: 'measure' - }, - { - startTime: 3906.99, - name: 'lh:computed:PageDependencyGraph', - duration: 3.22, - entryType: 'measure' - }, - { - startTime: 3910.26, - name: 'lh:computed:LoadSimulator', - duration: 1.66, - entryType: 'measure' - }, - { - startTime: 3910.36, - name: 'lh:computed:NetworkAnalysis', - duration: 1.33, - entryType: 'measure' - }, - { - startTime: 3917.69, - name: 'lh:audit:largest-contentful-paint', - duration: 2.4, - entryType: 'measure' - }, - { - startTime: 3917.88, - name: 'lh:computed:LargestContentfulPaint', - duration: 1.93, - entryType: 'measure' - }, - { - startTime: 3917.94, - name: 'lh:computed:LanternLargestContentfulPaint', - duration: 1.86, - entryType: 'measure' - }, - { - startTime: 3920.37, - name: 'lh:audit:first-meaningful-paint', - duration: 2.47, - entryType: 'measure' - }, - { - startTime: 3920.56, - name: 'lh:computed:FirstMeaningfulPaint', - duration: 2, - entryType: 'measure' - }, - { - startTime: 3920.62, - name: 'lh:computed:LanternFirstMeaningfulPaint', - duration: 1.93, - entryType: 'measure' - }, - { - startTime: 3923.08, - name: 'lh:audit:speed-index', - duration: 372.77, - entryType: 'measure' - }, - { - startTime: 3923.29, - name: 'lh:computed:SpeedIndex', - duration: 372.31, - entryType: 'measure' - }, - { - startTime: 3923.34, - name: 'lh:computed:LanternSpeedIndex', - duration: 372.24, - entryType: 'measure' - }, - { - startTime: 3923.39, - name: 'lh:computed:Speedline', - duration: 370.4, - entryType: 'measure' - }, - { - startTime: 4295.89, - name: 'lh:audit:screenshot-thumbnails', - duration: 211.23, - entryType: 'measure' - }, - { - startTime: 4507.16, - name: 'lh:audit:final-screenshot', - duration: 0.6, - entryType: 'measure' - }, - { - startTime: 4507.35, - name: 'lh:computed:Screenshots', - duration: 0.35, - entryType: 'measure' - }, - { - startTime: 4508.23, - name: 'lh:audit:estimated-input-latency', - duration: 2.61, - entryType: 'measure' - }, - { - startTime: 4508.44, - name: 'lh:computed:EstimatedInputLatency', - duration: 2.14, - entryType: 'measure' - }, - { - startTime: 4508.54, - name: 'lh:computed:LanternEstimatedInputLatency', - duration: 2.02, - entryType: 'measure' - }, - { - startTime: 4511.09, - name: 'lh:audit:total-blocking-time', - duration: 4.06, - entryType: 'measure' - }, - { - startTime: 4511.31, - name: 'lh:computed:TotalBlockingTime', - duration: 3.53, - entryType: 'measure' - }, - { - startTime: 4511.36, - name: 'lh:computed:LanternTotalBlockingTime', - duration: 3.46, - entryType: 'measure' - }, - { - startTime: 4511.45, - name: 'lh:computed:LanternInteractive', - duration: 1.54, - entryType: 'measure' - }, - { - startTime: 4515.42, - name: 'lh:audit:max-potential-fid', - duration: 1.84, - entryType: 'measure' - }, - { - startTime: 4515.6, - name: 'lh:computed:MaxPotentialFID', - duration: 1.4, - entryType: 'measure' - }, - { - startTime: 4515.66, - name: 'lh:computed:LanternMaxPotentialFID', - duration: 1.33, - entryType: 'measure' - }, - { - startTime: 4517.47, - name: 'lh:audit:cumulative-layout-shift', - duration: 0.93, - entryType: 'measure' - }, - { - startTime: 4517.66, - name: 'lh:computed:CumulativeLayoutShift', - duration: 0.35, - entryType: 'measure' - }, - { - startTime: 4518.69, - name: 'lh:audit:errors-in-console', - duration: 0.69, - entryType: 'measure' - }, - { - startTime: 4519.61, - name: 'lh:audit:server-response-time', - duration: 0.68, - entryType: 'measure' - }, - { - startTime: 4519.8, - name: 'lh:computed:MainResource', - duration: 0.2, - entryType: 'measure' - }, - { - startTime: 4520.48, - name: 'lh:audit:first-cpu-idle', - duration: 2.22, - entryType: 'measure' - }, - { - startTime: 4520.67, - name: 'lh:computed:FirstCPUIdle', - duration: 1.83, - entryType: 'measure' - }, - { - startTime: 4520.72, - name: 'lh:computed:LanternFirstCPUIdle', - duration: 1.76, - entryType: 'measure' - }, - { - startTime: 4522.91, - name: 'lh:audit:interactive', - duration: 0.47, - entryType: 'measure' - }, - { - startTime: 4523.1, - name: 'lh:computed:Interactive', - duration: 0.08, - entryType: 'measure' - }, - { - startTime: 4523.56, - name: 'lh:audit:user-timings', - duration: 1.05, - entryType: 'measure' - }, - { - startTime: 4523.73, - name: 'lh:computed:UserTimings', - duration: 0.55, - entryType: 'measure' - }, - { - startTime: 4524.8, - name: 'lh:audit:critical-request-chains', - duration: 1.27, - entryType: 'measure' - }, - { - startTime: 4524.96, - name: 'lh:computed:CriticalRequestChains', - duration: 0.44, - entryType: 'measure' - }, - { - startTime: 4526.3, - name: 'lh:audit:redirects', - duration: 0.68, - entryType: 'measure' - }, - { - startTime: 4527.28, - name: 'lh:audit:image-aspect-ratio', - duration: 0.38, - entryType: 'measure' - }, - { - startTime: 4527.96, - name: 'lh:audit:image-size-responsive', - duration: 0.59, - entryType: 'measure' - }, - { - startTime: 4528.75, - name: 'lh:audit:deprecations', - duration: 0.37, - entryType: 'measure' - }, - { - startTime: 4529.32, - name: 'lh:audit:mainthread-work-breakdown', - duration: 10.84, - entryType: 'measure' - }, - { - startTime: 4529.57, - name: 'lh:computed:MainThreadTasks', - duration: 9.25, - entryType: 'measure' - }, - { - startTime: 4540.59, - name: 'lh:audit:bootup-time', - duration: 1.78, - entryType: 'measure' - }, - { - startTime: 4542.67, - name: 'lh:audit:uses-rel-preload', - duration: 3.13, - entryType: 'measure' - }, - { - startTime: 4543.15, - name: 'lh:computed:LoadSimulator', - duration: 0.09, - entryType: 'measure' - }, - { - startTime: 4546.14, - name: 'lh:audit:uses-rel-preconnect', - duration: 1.12, - entryType: 'measure' - }, - { - startTime: 4547.59, - name: 'lh:audit:font-display', - duration: 0.96, - entryType: 'measure' - }, - { - startTime: 4548.57, - name: 'lh:audit:diagnostics', - duration: 0.47, - entryType: 'measure' - }, - { - startTime: 4549.06, - name: 'lh:audit:network-requests', - duration: 0.63, - entryType: 'measure' - }, - { - startTime: 4550.04, - name: 'lh:audit:network-rtt', - duration: 0.55, - entryType: 'measure' - }, - { - startTime: 4550.89, - name: 'lh:audit:network-server-latency', - duration: 0.46, - entryType: 'measure' - }, - { - startTime: 4551.36, - name: 'lh:audit:main-thread-tasks', - duration: 0.26, - entryType: 'measure' - }, - { - startTime: 4551.65, - name: 'lh:audit:metrics', - duration: 1.61, - entryType: 'measure' - }, - { - startTime: 4551.83, - name: 'lh:computed:TimingSummary', - duration: 1.23, - entryType: 'measure' - }, - { - startTime: 4553.55, - name: 'lh:audit:performance-budget', - duration: 1.47, - entryType: 'measure' - }, - { - startTime: 4553.81, - name: 'lh:computed:ResourceSummary', - duration: 1, - entryType: 'measure' - }, - { - startTime: 4555.24, - name: 'lh:audit:timing-budget', - duration: 0.45, - entryType: 'measure' - }, - { - startTime: 4555.99, - name: 'lh:audit:resource-summary', - duration: 0.82, - entryType: 'measure' - }, - { - startTime: 4557.07, - name: 'lh:audit:third-party-summary', - duration: 3.37, - entryType: 'measure' - }, - { - startTime: 4560.71, - name: 'lh:audit:largest-contentful-paint-element', - duration: 0.39, - entryType: 'measure' - }, - { - startTime: 4561.33, - name: 'lh:audit:layout-shift-elements', - duration: 0.32, - entryType: 'measure' - }, - { - startTime: 4561.83, - name: 'lh:audit:long-tasks', - duration: 1.51, - entryType: 'measure' - }, - { - startTime: 4563.57, - name: 'lh:audit:accesskeys', - duration: 1.22, - entryType: 'measure' - }, - { - startTime: 4565.08, - name: 'lh:audit:aria-allowed-attr', - duration: 0.94, - entryType: 'measure' - }, - { - startTime: 4566.3, - name: 'lh:audit:aria-hidden-body', - duration: 0.85, - entryType: 'measure' - }, - { - startTime: 4567.4, - name: 'lh:audit:aria-hidden-focus', - duration: 0.28, - entryType: 'measure' - }, - { - startTime: 4567.88, - name: 'lh:audit:aria-input-field-name', - duration: 0.25, - entryType: 'measure' - }, - { - startTime: 4568.34, - name: 'lh:audit:aria-required-attr', - duration: 0.97, - entryType: 'measure' - }, - { - startTime: 4569.68, - name: 'lh:audit:aria-required-children', - duration: 0.88, - entryType: 'measure' - }, - { - startTime: 4570.84, - name: 'lh:audit:aria-required-parent', - duration: 0.78, - entryType: 'measure' - }, - { - startTime: 4571.86, - name: 'lh:audit:aria-roles', - duration: 0.75, - entryType: 'measure' - }, - { - startTime: 4572.83, - name: 'lh:audit:aria-toggle-field-name', - duration: 0.36, - entryType: 'measure' - }, - { - startTime: 4573.53, - name: 'lh:audit:aria-valid-attr-value', - duration: 2.62, - entryType: 'measure' - }, - { - startTime: 4576.42, - name: 'lh:audit:aria-valid-attr', - duration: 1.04, - entryType: 'measure' - }, - { - startTime: 4577.68, - name: 'lh:audit:button-name', - duration: 0.35, - entryType: 'measure' - }, - { - startTime: 4578.28, - name: 'lh:audit:bypass', - duration: 0.86, - entryType: 'measure' - }, - { - startTime: 4579.43, - name: 'lh:audit:color-contrast', - duration: 1.21, - entryType: 'measure' - }, - { - startTime: 4581.1, - name: 'lh:audit:definition-list', - duration: 0.59, - entryType: 'measure' - }, - { - startTime: 4582.03, - name: 'lh:audit:dlitem', - duration: 3.25, - entryType: 'measure' - }, - { - startTime: 4585.63, - name: 'lh:audit:document-title', - duration: 1.28, - entryType: 'measure' - }, - { - startTime: 4587.27, - name: 'lh:audit:duplicate-id-active', - duration: 1.01, - entryType: 'measure' - }, - { - startTime: 4588.63, - name: 'lh:audit:duplicate-id-aria', - duration: 0.49, - entryType: 'measure' - }, - { - startTime: 4589.38, - name: 'lh:audit:form-field-multiple-labels', - duration: 1.05, - entryType: 'measure' - }, - { - startTime: 4590.71, - name: 'lh:audit:frame-title', - duration: 0.48, - entryType: 'measure' - }, - { - startTime: 4591.39, - name: 'lh:audit:heading-order', - duration: 0.66, - entryType: 'measure' - }, - { - startTime: 4592.22, - name: 'lh:audit:html-has-lang', - duration: 0.68, - entryType: 'measure' - }, - { - startTime: 4593.09, - name: 'lh:audit:html-lang-valid', - duration: 0.36, - entryType: 'measure' - }, - { - startTime: 4593.6, - name: 'lh:audit:image-alt', - duration: 0.35, - entryType: 'measure' - }, - { - startTime: 4594.15, - name: 'lh:audit:input-image-alt', - duration: 0.53, - entryType: 'measure' - }, - { - startTime: 4594.87, - name: 'lh:audit:label', - duration: 0.56, - entryType: 'measure' - }, - { - startTime: 4595.65, - name: 'lh:audit:layout-table', - duration: 0.33, - entryType: 'measure' - }, - { - startTime: 4596.13, - name: 'lh:audit:link-name', - duration: 0.51, - entryType: 'measure' - }, - { - startTime: 4596.85, - name: 'lh:audit:list', - duration: 0.52, - entryType: 'measure' - }, - { - startTime: 4597.56, - name: 'lh:audit:listitem', - duration: 0.51, - entryType: 'measure' - }, - { - startTime: 4598.37, - name: 'lh:audit:meta-refresh', - duration: 0.46, - entryType: 'measure' - }, - { - startTime: 4599.23, - name: 'lh:audit:meta-viewport', - duration: 0.35, - entryType: 'measure' - }, - { - startTime: 4599.78, - name: 'lh:audit:object-alt', - duration: 0.36, - entryType: 'measure' - }, - { - startTime: 4600.31, - name: 'lh:audit:tabindex', - duration: 0.39, - entryType: 'measure' - }, - { - startTime: 4600.91, - name: 'lh:audit:td-headers-attr', - duration: 0.52, - entryType: 'measure' - }, - { - startTime: 4602.4, - name: 'lh:audit:th-has-data-cells', - duration: 0.76, - entryType: 'measure' - }, - { - startTime: 4603.37, - name: 'lh:audit:valid-lang', - duration: 0.41, - entryType: 'measure' - }, - { - startTime: 4603.96, - name: 'lh:audit:video-caption', - duration: 0.41, - entryType: 'measure' - }, - { - startTime: 4604.56, - name: 'lh:audit:video-description', - duration: 0.43, - entryType: 'measure' - }, - { - startTime: 4605.03, - name: 'lh:audit:custom-controls-labels', - duration: 0.14, - entryType: 'measure' - }, - { - startTime: 4605.19, - name: 'lh:audit:custom-controls-roles', - duration: 0.03, - entryType: 'measure' - }, - { - startTime: 4605.23, - name: 'lh:audit:focus-traps', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.26, - name: 'lh:audit:focusable-controls', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.29, - name: 'lh:audit:interactive-element-affordance', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.32, - name: 'lh:audit:logical-tab-order', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.35, - name: 'lh:audit:managed-focus', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.38, - name: 'lh:audit:offscreen-content-hidden', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.41, - name: 'lh:audit:use-landmarks', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.44, - name: 'lh:audit:visual-order-follows-dom', - duration: 0.02, - entryType: 'measure' - }, - { - startTime: 4605.65, - name: 'lh:audit:uses-long-cache-ttl', - duration: 1.68, - entryType: 'measure' - }, - { - startTime: 4607.54, - name: 'lh:audit:total-byte-weight', - duration: 0.6, - entryType: 'measure' - }, - { - startTime: 4608.32, - name: 'lh:audit:offscreen-images', - duration: 2.29, - entryType: 'measure' - }, - { - startTime: 4610.89, - name: 'lh:audit:render-blocking-resources', - duration: 3.77, - entryType: 'measure' - }, - { - startTime: 4611.4, - name: 'lh:computed:UnusedCSS', - duration: 0.54, - entryType: 'measure' - }, - { - startTime: 4612, - name: 'lh:computed:FirstContentfulPaint', - duration: 1.76, - entryType: 'measure' - }, - { - startTime: 4612.05, - name: 'lh:computed:LanternFirstContentfulPaint', - duration: 1.69, - entryType: 'measure' - }, - { - startTime: 4614.87, - name: 'lh:audit:unminified-css', - duration: 8.31, - entryType: 'measure' - }, - { - startTime: 4623.39, - name: 'lh:audit:unminified-javascript', - duration: 30.35, - entryType: 'measure' - }, - { - startTime: 4653.98, - name: 'lh:audit:unused-css-rules', - duration: 1.29, - entryType: 'measure' - }, - { - startTime: 4655.46, - name: 'lh:audit:unused-javascript', - duration: 26.62, - entryType: 'measure' - }, - { - startTime: 4655.8, - name: 'lh:computed:JSBundles', - duration: 0.17, - entryType: 'measure' - }, - { - startTime: 4656.02, - name: 'lh:computed:UnusedJavascriptSummary', - duration: 0.29, - entryType: 'measure' - }, - { - startTime: 4656.36, - name: 'lh:computed:UnusedJavascriptSummary', - duration: 9.77, - entryType: 'measure' - }, - { - startTime: 4666.25, - name: 'lh:computed:UnusedJavascriptSummary', - duration: 13.6, - entryType: 'measure' - }, - { - startTime: 4680, - name: 'lh:computed:UnusedJavascriptSummary', - duration: 0.16, - entryType: 'measure' - }, - { - startTime: 4682.47, - name: 'lh:audit:uses-webp-images', - duration: 3.23, - entryType: 'measure' - }, - { - startTime: 4686.16, - name: 'lh:audit:uses-optimized-images', - duration: 12.09, - entryType: 'measure' - }, - { - startTime: 4698.63, - name: 'lh:audit:uses-text-compression', - duration: 2.07, - entryType: 'measure' - }, - { - startTime: 4701.09, - name: 'lh:audit:uses-responsive-images', - duration: 4.34, - entryType: 'measure' - }, - { - startTime: 4705.8, - name: 'lh:audit:efficient-animated-content', - duration: 2.35, - entryType: 'measure' - }, - { - startTime: 4708.5, - name: 'lh:audit:appcache-manifest', - duration: 0.51, - entryType: 'measure' - }, - { - startTime: 4709.32, - name: 'lh:audit:doctype', - duration: 0.41, - entryType: 'measure' - }, - { - startTime: 4709.99, - name: 'lh:audit:charset', - duration: 0.84, - entryType: 'measure' - }, - { - startTime: 4711.1, - name: 'lh:audit:dom-size', - duration: 0.96, - entryType: 'measure' - }, - { - startTime: 4712.33, - name: 'lh:audit:external-anchors-use-rel-noopener', - duration: 0.6, - entryType: 'measure' - }, - { - startTime: 4713.27, - name: 'lh:audit:geolocation-on-start', - duration: 0.47, - entryType: 'measure' - }, - { - startTime: 4713.96, - name: 'lh:audit:no-document-write', - duration: 0.46, - entryType: 'measure' - }, - { - startTime: 4714.77, - name: 'lh:audit:no-vulnerable-libraries', - duration: 8.14, - entryType: 'measure' - }, - { - startTime: 4723.29, - name: 'lh:audit:js-libraries', - duration: 0.54, - entryType: 'measure' - }, - { - startTime: 4724.2, - name: 'lh:audit:notification-on-start', - duration: 0.39, - entryType: 'measure' - }, - { - startTime: 4724.89, - name: 'lh:audit:password-inputs-can-be-pasted-into', - duration: 0.42, - entryType: 'measure' - }, - { - startTime: 4725.59, - name: 'lh:audit:uses-http2', - duration: 0.94, - entryType: 'measure' - }, - { - startTime: 4726.87, - name: 'lh:audit:uses-passive-event-listeners', - duration: 0.4, - entryType: 'measure' - }, - { - startTime: 4727.54, - name: 'lh:audit:meta-description', - duration: 0.38, - entryType: 'measure' - }, - { - startTime: 4728.21, - name: 'lh:audit:http-status-code', - duration: 0.44, - entryType: 'measure' - }, - { - startTime: 4728.89, - name: 'lh:audit:font-size', - duration: 0.55, - entryType: 'measure' - }, - { - startTime: 4729.69, - name: 'lh:audit:link-text', - duration: 1.65, - entryType: 'measure' - }, - { - startTime: 4731.58, - name: 'lh:audit:crawlable-anchors', - duration: 0.97, - entryType: 'measure' - }, - { - startTime: 4732.92, - name: 'lh:audit:is-crawlable', - duration: 2.06, - entryType: 'measure' - }, - { - startTime: 4735.29, - name: 'lh:audit:robots-txt', - duration: 0.79, - entryType: 'measure' - }, - { - startTime: 4736.37, - name: 'lh:audit:tap-targets', - duration: 0.49, - entryType: 'measure' - }, - { - startTime: 4737.13, - name: 'lh:audit:hreflang', - duration: 0.46, - entryType: 'measure' - }, - { - startTime: 4737.88, - name: 'lh:audit:plugins', - duration: 0.49, - entryType: 'measure' - }, - { - startTime: 4738.68, - name: 'lh:audit:canonical', - duration: 0.79, - entryType: 'measure' - }, - { - startTime: 4740.19, - name: 'lh:audit:structured-data', - duration: 0.24, - entryType: 'measure' - }, - { - startTime: 4740.46, - name: 'lh:runner:generate', - duration: 2.24, - entryType: 'measure' - } - ], - total: 4084.38 - }, - i18n: { - rendererFormattedStrings: { - auditGroupExpandTooltip: 'Show audits', - calculatorLink: 'See calculator.', - crcInitialNavigation: 'Initial Navigation', - crcLongestDurationLabel: 'Maximum critical path latency:', - dropdownCopyJSON: 'Copy JSON', - dropdownDarkTheme: 'Toggle Dark Theme', - dropdownPrintExpanded: 'Print Expanded', - dropdownPrintSummary: 'Print Summary', - dropdownSaveGist: 'Save as Gist', - dropdownSaveHTML: 'Save as HTML', - dropdownSaveJSON: 'Save as JSON', - dropdownViewer: 'Open in Viewer', - errorLabel: 'Error!', - errorMissingAuditInfo: 'Report error: no audit information', - footerIssue: 'File an issue', - labDataTitle: 'Lab Data', - lsPerformanceCategoryDescription: - '[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.', - manualAuditsGroupTitle: 'Additional items to manually check', - notApplicableAuditsGroupTitle: 'Not applicable', - opportunityResourceColumnLabel: 'Opportunity', - opportunitySavingsColumnLabel: 'Estimated Savings', - passedAuditsGroupTitle: 'Passed audits', - runtimeDesktopEmulation: 'Emulated Desktop', - runtimeMobileEmulation: 'Emulated Moto G4', - runtimeNoEmulation: 'No emulation', - runtimeSettingsBenchmark: 'CPU/Memory Power', - runtimeSettingsChannel: 'Channel', - runtimeSettingsCPUThrottling: 'CPU throttling', - runtimeSettingsDevice: 'Device', - runtimeSettingsFetchTime: 'Fetch Time', - runtimeSettingsNetworkThrottling: 'Network throttling', - runtimeSettingsTitle: 'Runtime Settings', - runtimeSettingsUA: 'User agent (host)', - runtimeSettingsUANetwork: 'User agent (network)', - runtimeSettingsUrl: 'URL', - runtimeUnknown: 'Unknown', - snippetCollapseButtonLabel: 'Collapse snippet', - snippetExpandButtonLabel: 'Expand snippet', - thirdPartyResourcesLabel: 'Show 3rd-party resources', - throttlingProvided: 'Provided by environment', - toplevelWarningsMessage: - 'There were issues affecting this run of Lighthouse:', - varianceDisclaimer: - 'Values are estimated and may vary. The [performance score is calculated](https://web.dev/performance-scoring/) directly from these metrics.', - warningAuditsGroupTitle: 'Passed audits but with warnings', - warningHeader: 'Warnings: ' - }, - icuMessagePaths: { - 'lighthouse-core/audits/is-on-https.js | title': [ - 'audits[is-on-https].title' - ], - 'lighthouse-core/audits/is-on-https.js | description': [ - 'audits[is-on-https].description' - ], - 'lighthouse-core/audits/viewport.js | failureTitle': [ - 'audits.viewport.title' - ], - 'lighthouse-core/audits/viewport.js | description': [ - 'audits.viewport.description' - ], - 'lighthouse-core/audits/viewport.js | explanationNoTag': [ - 'audits.viewport.explanation' - ], - 'lighthouse-core/lib/i18n/i18n.js | firstContentfulPaintMetric': [ - 'audits[first-contentful-paint].title' - ], - 'lighthouse-core/audits/metrics/first-contentful-paint.js | description': [ - 'audits[first-contentful-paint].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | seconds': [ - { - values: { timeInMs: 1162.56 }, - path: 'audits[first-contentful-paint].displayValue' - }, - { - values: { timeInMs: 1215.06 }, - path: 'audits[largest-contentful-paint].displayValue' - }, - { - values: { timeInMs: 1215.06 }, - path: 'audits[first-meaningful-paint].displayValue' - }, - { - values: { timeInMs: 1346.358482898538 }, - path: 'audits[speed-index].displayValue' - }, - { - values: { timeInMs: 1215.06 }, - path: 'audits[first-cpu-idle].displayValue' - }, - { - values: { timeInMs: 1215.06 }, - path: 'audits.interactive.displayValue' - }, - { - values: { timeInMs: 571.4760000000001 }, - path: 'audits[mainthread-work-breakdown].displayValue' - }, - { - values: { timeInMs: 265.94399999999996 }, - path: 'audits[bootup-time].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | largestContentfulPaintMetric': [ - 'audits[largest-contentful-paint].title' - ], - 'lighthouse-core/audits/metrics/largest-contentful-paint.js | description': [ - 'audits[largest-contentful-paint].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | firstMeaningfulPaintMetric': [ - 'audits[first-meaningful-paint].title' - ], - 'lighthouse-core/audits/metrics/first-meaningful-paint.js | description': [ - 'audits[first-meaningful-paint].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | speedIndexMetric': [ - 'audits[speed-index].title' - ], - 'lighthouse-core/audits/metrics/speed-index.js | description': [ - 'audits[speed-index].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | estimatedInputLatencyMetric': [ - 'audits[estimated-input-latency].title' - ], - 'lighthouse-core/audits/metrics/estimated-input-latency.js | description': [ - 'audits[estimated-input-latency].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | ms': [ - { - values: { timeInMs: 12.8 }, - path: 'audits[estimated-input-latency].displayValue' - }, - { - values: { timeInMs: 27.5 }, - path: 'audits[total-blocking-time].displayValue' - }, - { - values: { timeInMs: 111 }, - path: 'audits[max-potential-fid].displayValue' - }, - { - values: { timeInMs: 77.463 }, - path: 'audits[network-rtt].displayValue' - }, - { - values: { timeInMs: 1.5600000000000165 }, - path: 'audits[network-server-latency].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | totalBlockingTimeMetric': [ - 'audits[total-blocking-time].title' - ], - 'lighthouse-core/audits/metrics/total-blocking-time.js | description': [ - 'audits[total-blocking-time].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | maxPotentialFIDMetric': [ - 'audits[max-potential-fid].title' - ], - 'lighthouse-core/audits/metrics/max-potential-fid.js | description': [ - 'audits[max-potential-fid].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | cumulativeLayoutShiftMetric': [ - 'audits[cumulative-layout-shift].title' - ], - 'lighthouse-core/audits/metrics/cumulative-layout-shift.js | description': [ - 'audits[cumulative-layout-shift].description' - ], - 'lighthouse-core/audits/errors-in-console.js | title': [ - 'audits[errors-in-console].title' - ], - 'lighthouse-core/audits/errors-in-console.js | description': [ - 'audits[errors-in-console].description' - ], - 'lighthouse-core/audits/server-response-time.js | title': [ - 'audits[server-response-time].title' - ], - 'lighthouse-core/audits/server-response-time.js | description': [ - 'audits[server-response-time].description' - ], - 'lighthouse-core/audits/server-response-time.js | displayValue': [ - { - values: { timeInMs: 89.95400000000004 }, - path: 'audits[server-response-time].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | firstCPUIdleMetric': [ - 'audits[first-cpu-idle].title' - ], - 'lighthouse-core/audits/metrics/first-cpu-idle.js | description': [ - 'audits[first-cpu-idle].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | interactiveMetric': [ - 'audits.interactive.title' - ], - 'lighthouse-core/audits/metrics/interactive.js | description': [ - 'audits.interactive.description' - ], - 'lighthouse-core/audits/user-timings.js | title': [ - 'audits[user-timings].title' - ], - 'lighthouse-core/audits/user-timings.js | description': [ - 'audits[user-timings].description' - ], - 'lighthouse-core/audits/critical-request-chains.js | title': [ - 'audits[critical-request-chains].title' - ], - 'lighthouse-core/audits/critical-request-chains.js | description': [ - 'audits[critical-request-chains].description' - ], - 'lighthouse-core/audits/critical-request-chains.js | displayValue': [ - { - values: { itemCount: 5 }, - path: 'audits[critical-request-chains].displayValue' - } - ], - 'lighthouse-core/audits/redirects.js | title': [ - 'audits.redirects.title' - ], - 'lighthouse-core/audits/redirects.js | description': [ - 'audits.redirects.description' - ], - 'lighthouse-core/audits/image-aspect-ratio.js | title': [ - 'audits[image-aspect-ratio].title' - ], - 'lighthouse-core/audits/image-aspect-ratio.js | description': [ - 'audits[image-aspect-ratio].description' - ], - 'lighthouse-core/audits/image-size-responsive.js | title': [ - 'audits[image-size-responsive].title' - ], - 'lighthouse-core/audits/image-size-responsive.js | description': [ - 'audits[image-size-responsive].description' - ], - 'lighthouse-core/audits/deprecations.js | title': [ - 'audits.deprecations.title' - ], - 'lighthouse-core/audits/deprecations.js | description': [ - 'audits.deprecations.description' - ], - 'lighthouse-core/audits/mainthread-work-breakdown.js | title': [ - 'audits[mainthread-work-breakdown].title' - ], - 'lighthouse-core/audits/mainthread-work-breakdown.js | description': [ - 'audits[mainthread-work-breakdown].description' - ], - 'lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory': [ - 'audits[mainthread-work-breakdown].details.headings[0].text' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnTimeSpent': [ - 'audits[mainthread-work-breakdown].details.headings[1].text', - 'audits[network-rtt].details.headings[1].text', - 'audits[network-server-latency].details.headings[1].text' - ], - 'lighthouse-core/audits/bootup-time.js | title': [ - 'audits[bootup-time].title' - ], - 'lighthouse-core/audits/bootup-time.js | description': [ - 'audits[bootup-time].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnURL': [ - 'audits[bootup-time].details.headings[0].text', - 'audits[network-rtt].details.headings[0].text', - 'audits[network-server-latency].details.headings[0].text', - 'audits[long-tasks].details.headings[0].text', - 'audits[uses-long-cache-ttl].details.headings[0].text', - 'audits[total-byte-weight].details.headings[0].text', - 'audits[render-blocking-resources].details.headings[0].label' - ], - 'lighthouse-core/audits/bootup-time.js | columnTotal': [ - 'audits[bootup-time].details.headings[1].text' - ], - 'lighthouse-core/audits/bootup-time.js | columnScriptEval': [ - 'audits[bootup-time].details.headings[2].text' - ], - 'lighthouse-core/audits/bootup-time.js | columnScriptParse': [ - 'audits[bootup-time].details.headings[3].text' - ], - 'lighthouse-core/audits/uses-rel-preload.js | title': [ - 'audits[uses-rel-preload].title' - ], - 'lighthouse-core/audits/uses-rel-preload.js | description': [ - 'audits[uses-rel-preload].description' - ], - 'lighthouse-core/audits/uses-rel-preconnect.js | title': [ - 'audits[uses-rel-preconnect].title' - ], - 'lighthouse-core/audits/uses-rel-preconnect.js | description': [ - 'audits[uses-rel-preconnect].description' - ], - 'lighthouse-core/audits/font-display.js | title': [ - 'audits[font-display].title' - ], - 'lighthouse-core/audits/font-display.js | description': [ - 'audits[font-display].description' - ], - 'lighthouse-core/audits/network-rtt.js | title': [ - 'audits[network-rtt].title' - ], - 'lighthouse-core/audits/network-rtt.js | description': [ - 'audits[network-rtt].description' - ], - 'lighthouse-core/audits/network-server-latency.js | title': [ - 'audits[network-server-latency].title' - ], - 'lighthouse-core/audits/network-server-latency.js | description': [ - 'audits[network-server-latency].description' - ], - 'lighthouse-core/audits/performance-budget.js | title': [ - 'audits[performance-budget].title' - ], - 'lighthouse-core/audits/performance-budget.js | description': [ - 'audits[performance-budget].description' - ], - 'lighthouse-core/audits/timing-budget.js | title': [ - 'audits[timing-budget].title' - ], - 'lighthouse-core/audits/timing-budget.js | description': [ - 'audits[timing-budget].description' - ], - 'lighthouse-core/audits/resource-summary.js | title': [ - 'audits[resource-summary].title' - ], - 'lighthouse-core/audits/resource-summary.js | description': [ - 'audits[resource-summary].description' - ], - 'lighthouse-core/audits/resource-summary.js | displayValue': [ - { - values: { requestCount: 7, byteCount: 49498 }, - path: 'audits[resource-summary].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | columnResourceType': [ - 'audits[resource-summary].details.headings[0].text' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnRequests': [ - 'audits[resource-summary].details.headings[1].text' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnTransferSize': [ - 'audits[resource-summary].details.headings[2].text', - 'audits[uses-long-cache-ttl].details.headings[2].text', - 'audits[total-byte-weight].details.headings[1].text', - 'audits[render-blocking-resources].details.headings[1].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | totalResourceType': [ - 'audits[resource-summary].details.items[0].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | scriptResourceType': [ - 'audits[resource-summary].details.items[1].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | documentResourceType': [ - 'audits[resource-summary].details.items[2].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType': [ - 'audits[resource-summary].details.items[3].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | imageResourceType': [ - 'audits[resource-summary].details.items[4].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | mediaResourceType': [ - 'audits[resource-summary].details.items[5].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | fontResourceType': [ - 'audits[resource-summary].details.items[6].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | otherResourceType': [ - 'audits[resource-summary].details.items[7].label' - ], - 'lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType': [ - 'audits[resource-summary].details.items[8].label' - ], - 'lighthouse-core/audits/third-party-summary.js | title': [ - 'audits[third-party-summary].title' - ], - 'lighthouse-core/audits/third-party-summary.js | description': [ - 'audits[third-party-summary].description' - ], - 'lighthouse-core/audits/largest-contentful-paint-element.js | title': [ - 'audits[largest-contentful-paint-element].title' - ], - 'lighthouse-core/audits/largest-contentful-paint-element.js | description': [ - 'audits[largest-contentful-paint-element].description' - ], - 'lighthouse-core/audits/largest-contentful-paint-element.js | displayValue': [ - { - values: { itemCount: 1 }, - path: 'audits[largest-contentful-paint-element].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | columnElement': [ - 'audits[largest-contentful-paint-element].details.headings[0].text', - 'audits[dom-size].details.headings[1].text' - ], - 'lighthouse-core/audits/layout-shift-elements.js | title': [ - 'audits[layout-shift-elements].title' - ], - 'lighthouse-core/audits/layout-shift-elements.js | description': [ - 'audits[layout-shift-elements].description' - ], - 'lighthouse-core/audits/long-tasks.js | title': [ - 'audits[long-tasks].title' - ], - 'lighthouse-core/audits/long-tasks.js | description': [ - 'audits[long-tasks].description' - ], - 'lighthouse-core/audits/long-tasks.js | displayValue': [ - { values: { itemCount: 2 }, path: 'audits[long-tasks].displayValue' } - ], - 'lighthouse-core/lib/i18n/i18n.js | columnStartTime': [ - 'audits[long-tasks].details.headings[1].text' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnDuration': [ - 'audits[long-tasks].details.headings[2].text' - ], - 'lighthouse-core/audits/accessibility/accesskeys.js | title': [ - 'audits.accesskeys.title' - ], - 'lighthouse-core/audits/accessibility/accesskeys.js | description': [ - 'audits.accesskeys.description' - ], - 'lighthouse-core/audits/accessibility/aria-allowed-attr.js | title': [ - 'audits[aria-allowed-attr].title' - ], - 'lighthouse-core/audits/accessibility/aria-allowed-attr.js | description': [ - 'audits[aria-allowed-attr].description' - ], - 'lighthouse-core/audits/accessibility/aria-hidden-body.js | title': [ - 'audits[aria-hidden-body].title' - ], - 'lighthouse-core/audits/accessibility/aria-hidden-body.js | description': [ - 'audits[aria-hidden-body].description' - ], - 'lighthouse-core/audits/accessibility/aria-hidden-focus.js | title': [ - 'audits[aria-hidden-focus].title' - ], - 'lighthouse-core/audits/accessibility/aria-hidden-focus.js | description': [ - 'audits[aria-hidden-focus].description' - ], - 'lighthouse-core/audits/accessibility/aria-input-field-name.js | title': [ - 'audits[aria-input-field-name].title' - ], - 'lighthouse-core/audits/accessibility/aria-input-field-name.js | description': [ - 'audits[aria-input-field-name].description' - ], - 'lighthouse-core/audits/accessibility/aria-required-attr.js | title': [ - 'audits[aria-required-attr].title' - ], - 'lighthouse-core/audits/accessibility/aria-required-attr.js | description': [ - 'audits[aria-required-attr].description' - ], - 'lighthouse-core/audits/accessibility/aria-required-children.js | title': [ - 'audits[aria-required-children].title' - ], - 'lighthouse-core/audits/accessibility/aria-required-children.js | description': [ - 'audits[aria-required-children].description' - ], - 'lighthouse-core/audits/accessibility/aria-required-parent.js | title': [ - 'audits[aria-required-parent].title' - ], - 'lighthouse-core/audits/accessibility/aria-required-parent.js | description': [ - 'audits[aria-required-parent].description' - ], - 'lighthouse-core/audits/accessibility/aria-roles.js | title': [ - 'audits[aria-roles].title' - ], - 'lighthouse-core/audits/accessibility/aria-roles.js | description': [ - 'audits[aria-roles].description' - ], - 'lighthouse-core/audits/accessibility/aria-toggle-field-name.js | title': [ - 'audits[aria-toggle-field-name].title' - ], - 'lighthouse-core/audits/accessibility/aria-toggle-field-name.js | description': [ - 'audits[aria-toggle-field-name].description' - ], - 'lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title': [ - 'audits[aria-valid-attr-value].title' - ], - 'lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description': [ - 'audits[aria-valid-attr-value].description' - ], - 'lighthouse-core/audits/accessibility/aria-valid-attr.js | title': [ - 'audits[aria-valid-attr].title' - ], - 'lighthouse-core/audits/accessibility/aria-valid-attr.js | description': [ - 'audits[aria-valid-attr].description' - ], - 'lighthouse-core/audits/accessibility/button-name.js | title': [ - 'audits[button-name].title' - ], - 'lighthouse-core/audits/accessibility/button-name.js | description': [ - 'audits[button-name].description' - ], - 'lighthouse-core/audits/accessibility/bypass.js | title': [ - 'audits.bypass.title' - ], - 'lighthouse-core/audits/accessibility/bypass.js | description': [ - 'audits.bypass.description' - ], - 'lighthouse-core/audits/accessibility/color-contrast.js | failureTitle': [ - 'audits[color-contrast].title' - ], - 'lighthouse-core/audits/accessibility/color-contrast.js | description': [ - 'audits[color-contrast].description' - ], - 'lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader': [ - 'audits[color-contrast].details.headings[0].text', - 'audits[html-has-lang].details.headings[0].text', - 'audits.label.details.headings[0].text' - ], - 'lighthouse-core/audits/accessibility/definition-list.js | title': [ - 'audits[definition-list].title' - ], - 'lighthouse-core/audits/accessibility/definition-list.js | description': [ - 'audits[definition-list].description' - ], - 'lighthouse-core/audits/accessibility/dlitem.js | title': [ - 'audits.dlitem.title' - ], - 'lighthouse-core/audits/accessibility/dlitem.js | description': [ - 'audits.dlitem.description' - ], - 'lighthouse-core/audits/accessibility/document-title.js | title': [ - 'audits[document-title].title' - ], - 'lighthouse-core/audits/accessibility/document-title.js | description': [ - 'audits[document-title].description' - ], - 'lighthouse-core/audits/accessibility/duplicate-id-active.js | title': [ - 'audits[duplicate-id-active].title' - ], - 'lighthouse-core/audits/accessibility/duplicate-id-active.js | description': [ - 'audits[duplicate-id-active].description' - ], - 'lighthouse-core/audits/accessibility/duplicate-id-aria.js | title': [ - 'audits[duplicate-id-aria].title' - ], - 'lighthouse-core/audits/accessibility/duplicate-id-aria.js | description': [ - 'audits[duplicate-id-aria].description' - ], - 'lighthouse-core/audits/accessibility/form-field-multiple-labels.js | title': [ - 'audits[form-field-multiple-labels].title' - ], - 'lighthouse-core/audits/accessibility/form-field-multiple-labels.js | description': [ - 'audits[form-field-multiple-labels].description' - ], - 'lighthouse-core/audits/accessibility/frame-title.js | title': [ - 'audits[frame-title].title' - ], - 'lighthouse-core/audits/accessibility/frame-title.js | description': [ - 'audits[frame-title].description' - ], - 'lighthouse-core/audits/accessibility/heading-order.js | title': [ - 'audits[heading-order].title' - ], - 'lighthouse-core/audits/accessibility/heading-order.js | description': [ - 'audits[heading-order].description' - ], - 'lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle': [ - 'audits[html-has-lang].title' - ], - 'lighthouse-core/audits/accessibility/html-has-lang.js | description': [ - 'audits[html-has-lang].description' - ], - 'lighthouse-core/audits/accessibility/html-lang-valid.js | title': [ - 'audits[html-lang-valid].title' - ], - 'lighthouse-core/audits/accessibility/html-lang-valid.js | description': [ - 'audits[html-lang-valid].description' - ], - 'lighthouse-core/audits/accessibility/image-alt.js | title': [ - 'audits[image-alt].title' - ], - 'lighthouse-core/audits/accessibility/image-alt.js | description': [ - 'audits[image-alt].description' - ], - 'lighthouse-core/audits/accessibility/input-image-alt.js | title': [ - 'audits[input-image-alt].title' - ], - 'lighthouse-core/audits/accessibility/input-image-alt.js | description': [ - 'audits[input-image-alt].description' - ], - 'lighthouse-core/audits/accessibility/label.js | failureTitle': [ - 'audits.label.title' - ], - 'lighthouse-core/audits/accessibility/label.js | description': [ - 'audits.label.description' - ], - 'lighthouse-core/audits/accessibility/layout-table.js | title': [ - 'audits[layout-table].title' - ], - 'lighthouse-core/audits/accessibility/layout-table.js | description': [ - 'audits[layout-table].description' - ], - 'lighthouse-core/audits/accessibility/link-name.js | title': [ - 'audits[link-name].title' - ], - 'lighthouse-core/audits/accessibility/link-name.js | description': [ - 'audits[link-name].description' - ], - 'lighthouse-core/audits/accessibility/list.js | title': [ - 'audits.list.title' - ], - 'lighthouse-core/audits/accessibility/list.js | description': [ - 'audits.list.description' - ], - 'lighthouse-core/audits/accessibility/listitem.js | title': [ - 'audits.listitem.title' - ], - 'lighthouse-core/audits/accessibility/listitem.js | description': [ - 'audits.listitem.description' - ], - 'lighthouse-core/audits/accessibility/meta-refresh.js | title': [ - 'audits[meta-refresh].title' - ], - 'lighthouse-core/audits/accessibility/meta-refresh.js | description': [ - 'audits[meta-refresh].description' - ], - 'lighthouse-core/audits/accessibility/meta-viewport.js | title': [ - 'audits[meta-viewport].title' - ], - 'lighthouse-core/audits/accessibility/meta-viewport.js | description': [ - 'audits[meta-viewport].description' - ], - 'lighthouse-core/audits/accessibility/object-alt.js | title': [ - 'audits[object-alt].title' - ], - 'lighthouse-core/audits/accessibility/object-alt.js | description': [ - 'audits[object-alt].description' - ], - 'lighthouse-core/audits/accessibility/tabindex.js | title': [ - 'audits.tabindex.title' - ], - 'lighthouse-core/audits/accessibility/tabindex.js | description': [ - 'audits.tabindex.description' - ], - 'lighthouse-core/audits/accessibility/td-headers-attr.js | title': [ - 'audits[td-headers-attr].title' - ], - 'lighthouse-core/audits/accessibility/td-headers-attr.js | description': [ - 'audits[td-headers-attr].description' - ], - 'lighthouse-core/audits/accessibility/th-has-data-cells.js | title': [ - 'audits[th-has-data-cells].title' - ], - 'lighthouse-core/audits/accessibility/th-has-data-cells.js | description': [ - 'audits[th-has-data-cells].description' - ], - 'lighthouse-core/audits/accessibility/valid-lang.js | title': [ - 'audits[valid-lang].title' - ], - 'lighthouse-core/audits/accessibility/valid-lang.js | description': [ - 'audits[valid-lang].description' - ], - 'lighthouse-core/audits/accessibility/video-caption.js | title': [ - 'audits[video-caption].title' - ], - 'lighthouse-core/audits/accessibility/video-caption.js | description': [ - 'audits[video-caption].description' - ], - 'lighthouse-core/audits/accessibility/video-description.js | title': [ - 'audits[video-description].title' - ], - 'lighthouse-core/audits/accessibility/video-description.js | description': [ - 'audits[video-description].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle': [ - 'audits[uses-long-cache-ttl].title' - ], - 'lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description': [ - 'audits[uses-long-cache-ttl].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue': [ - { - values: { itemCount: 6 }, - path: 'audits[uses-long-cache-ttl].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | columnCacheTTL': [ - 'audits[uses-long-cache-ttl].details.headings[1].text' - ], - 'lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title': [ - 'audits[total-byte-weight].title' - ], - 'lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description': [ - 'audits[total-byte-weight].description' - ], - 'lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue': [ - { - values: { totalBytes: 49498 }, - path: 'audits[total-byte-weight].displayValue' - } - ], - 'lighthouse-core/audits/byte-efficiency/offscreen-images.js | title': [ - 'audits[offscreen-images].title' - ], - 'lighthouse-core/audits/byte-efficiency/offscreen-images.js | description': [ - 'audits[offscreen-images].description' - ], - 'lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title': [ - 'audits[render-blocking-resources].title' - ], - 'lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description': [ - 'audits[render-blocking-resources].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings': [ - { - values: { wastedMs: 395 }, - path: 'audits[render-blocking-resources].displayValue' - } - ], - 'lighthouse-core/lib/i18n/i18n.js | columnWastedBytes': [ - 'audits[render-blocking-resources].details.headings[2].label' - ], - 'lighthouse-core/audits/byte-efficiency/unminified-css.js | title': [ - 'audits[unminified-css].title' - ], - 'lighthouse-core/audits/byte-efficiency/unminified-css.js | description': [ - 'audits[unminified-css].description' - ], - 'lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title': [ - 'audits[unminified-javascript].title' - ], - 'lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description': [ - 'audits[unminified-javascript].description' - ], - 'lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title': [ - 'audits[unused-css-rules].title' - ], - 'lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description': [ - 'audits[unused-css-rules].description' - ], - 'lighthouse-core/audits/byte-efficiency/unused-javascript.js | title': [ - 'audits[unused-javascript].title' - ], - 'lighthouse-core/audits/byte-efficiency/unused-javascript.js | description': [ - 'audits[unused-javascript].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title': [ - 'audits[uses-webp-images].title' - ], - 'lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description': [ - 'audits[uses-webp-images].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title': [ - 'audits[uses-optimized-images].title' - ], - 'lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description': [ - 'audits[uses-optimized-images].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title': [ - 'audits[uses-text-compression].title' - ], - 'lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description': [ - 'audits[uses-text-compression].description' - ], - 'lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title': [ - 'audits[uses-responsive-images].title' - ], - 'lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description': [ - 'audits[uses-responsive-images].description' - ], - 'lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title': [ - 'audits[efficient-animated-content].title' - ], - 'lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description': [ - 'audits[efficient-animated-content].description' - ], - 'lighthouse-core/audits/dobetterweb/appcache-manifest.js | title': [ - 'audits[appcache-manifest].title' - ], - 'lighthouse-core/audits/dobetterweb/appcache-manifest.js | description': [ - 'audits[appcache-manifest].description' - ], - 'lighthouse-core/audits/dobetterweb/doctype.js | failureTitle': [ - 'audits.doctype.title' - ], - 'lighthouse-core/audits/dobetterweb/doctype.js | description': [ - 'audits.doctype.description' - ], - 'lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId': [ - 'audits.doctype.explanation' - ], - 'lighthouse-core/audits/dobetterweb/charset.js | title': [ - 'audits.charset.title' - ], - 'lighthouse-core/audits/dobetterweb/charset.js | description': [ - 'audits.charset.description' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | title': [ - 'audits[dom-size].title' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | description': [ - 'audits[dom-size].description' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | displayValue': [ - { values: { itemCount: 319 }, path: 'audits[dom-size].displayValue' } - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic': [ - 'audits[dom-size].details.headings[0].text' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | columnValue': [ - 'audits[dom-size].details.headings[2].text' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements': [ - 'audits[dom-size].details.items[0].statistic' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth': [ - 'audits[dom-size].details.items[1].statistic' - ], - 'lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth': [ - 'audits[dom-size].details.items[2].statistic' - ], - 'lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title': [ - 'audits[external-anchors-use-rel-noopener].title' - ], - 'lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description': [ - 'audits[external-anchors-use-rel-noopener].description' - ], - 'lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title': [ - 'audits[geolocation-on-start].title' - ], - 'lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description': [ - 'audits[geolocation-on-start].description' - ], - 'lighthouse-core/audits/dobetterweb/no-document-write.js | title': [ - 'audits[no-document-write].title' - ], - 'lighthouse-core/audits/dobetterweb/no-document-write.js | description': [ - 'audits[no-document-write].description' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle': [ - 'audits[no-vulnerable-libraries].title' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description': [ - 'audits[no-vulnerable-libraries].description' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue': [ - { - values: { itemCount: 3 }, - path: 'audits[no-vulnerable-libraries].displayValue' - } - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion': [ - 'audits[no-vulnerable-libraries].details.headings[0].text' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln': [ - 'audits[no-vulnerable-libraries].details.headings[1].text' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity': [ - 'audits[no-vulnerable-libraries].details.headings[2].text' - ], - 'lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium': [ - 'audits[no-vulnerable-libraries].details.items[0].highestSeverity' - ], - 'lighthouse-core/audits/dobetterweb/js-libraries.js | title': [ - 'audits[js-libraries].title' - ], - 'lighthouse-core/audits/dobetterweb/js-libraries.js | description': [ - 'audits[js-libraries].description' - ], - 'lighthouse-core/lib/i18n/i18n.js | columnName': [ - 'audits[js-libraries].details.headings[0].text' - ], - 'lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion': [ - 'audits[js-libraries].details.headings[1].text' - ], - 'lighthouse-core/audits/dobetterweb/notification-on-start.js | title': [ - 'audits[notification-on-start].title' - ], - 'lighthouse-core/audits/dobetterweb/notification-on-start.js | description': [ - 'audits[notification-on-start].description' - ], - 'lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title': [ - 'audits[password-inputs-can-be-pasted-into].title' - ], - 'lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description': [ - 'audits[password-inputs-can-be-pasted-into].description' - ], - 'lighthouse-core/audits/dobetterweb/uses-http2.js | title': [ - 'audits[uses-http2].title' - ], - 'lighthouse-core/audits/dobetterweb/uses-http2.js | description': [ - 'audits[uses-http2].description' - ], - 'lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title': [ - 'audits[uses-passive-event-listeners].title' - ], - 'lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description': [ - 'audits[uses-passive-event-listeners].description' - ], - 'lighthouse-core/audits/seo/meta-description.js | failureTitle': [ - 'audits[meta-description].title' - ], - 'lighthouse-core/audits/seo/meta-description.js | description': [ - 'audits[meta-description].description' - ], - 'lighthouse-core/audits/seo/http-status-code.js | title': [ - 'audits[http-status-code].title' - ], - 'lighthouse-core/audits/seo/http-status-code.js | description': [ - 'audits[http-status-code].description' - ], - 'lighthouse-core/audits/seo/font-size.js | title': [ - 'audits[font-size].title' - ], - 'lighthouse-core/audits/seo/font-size.js | description': [ - 'audits[font-size].description' - ], - 'lighthouse-core/audits/seo/link-text.js | title': [ - 'audits[link-text].title' - ], - 'lighthouse-core/audits/seo/link-text.js | description': [ - 'audits[link-text].description' - ], - 'lighthouse-core/audits/seo/crawlable-anchors.js | title': [ - 'audits[crawlable-anchors].title' - ], - 'lighthouse-core/audits/seo/crawlable-anchors.js | description': [ - 'audits[crawlable-anchors].description' - ], - 'lighthouse-core/audits/seo/is-crawlable.js | title': [ - 'audits[is-crawlable].title' - ], - 'lighthouse-core/audits/seo/is-crawlable.js | description': [ - 'audits[is-crawlable].description' - ], - 'lighthouse-core/audits/seo/robots-txt.js | title': [ - 'audits[robots-txt].title' - ], - 'lighthouse-core/audits/seo/robots-txt.js | description': [ - 'audits[robots-txt].description' - ], - 'lighthouse-core/audits/seo/tap-targets.js | title': [ - 'audits[tap-targets].title' - ], - 'lighthouse-core/audits/seo/tap-targets.js | description': [ - 'audits[tap-targets].description' - ], - 'lighthouse-core/audits/seo/hreflang.js | title': [ - 'audits.hreflang.title' - ], - 'lighthouse-core/audits/seo/hreflang.js | description': [ - 'audits.hreflang.description' - ], - 'lighthouse-core/audits/seo/plugins.js | title': [ - 'audits.plugins.title' - ], - 'lighthouse-core/audits/seo/plugins.js | description': [ - 'audits.plugins.description' - ], - 'lighthouse-core/audits/seo/canonical.js | title': [ - 'audits.canonical.title' - ], - 'lighthouse-core/audits/seo/canonical.js | description': [ - 'audits.canonical.description' - ], - 'lighthouse-core/audits/seo/manual/structured-data.js | title': [ - 'audits[structured-data].title' - ], - 'lighthouse-core/audits/seo/manual/structured-data.js | description': [ - 'audits[structured-data].description' - ], - 'lighthouse-core/config/default-config.js | performanceCategoryTitle': [ - 'categories.performance.title' - ], - 'lighthouse-core/config/default-config.js | a11yCategoryTitle': [ - 'categories.accessibility.title' - ], - 'lighthouse-core/config/default-config.js | a11yCategoryDescription': [ - 'categories.accessibility.description' - ], - 'lighthouse-core/config/default-config.js | a11yCategoryManualDescription': [ - 'categories.accessibility.manualDescription' - ], - 'lighthouse-core/config/default-config.js | bestPracticesCategoryTitle': [ - 'categories[best-practices].title' - ], - 'lighthouse-core/config/default-config.js | seoCategoryTitle': [ - 'categories.seo.title' - ], - 'lighthouse-core/config/default-config.js | seoCategoryDescription': [ - 'categories.seo.description' - ], - 'lighthouse-core/config/default-config.js | seoCategoryManualDescription': [ - 'categories.seo.manualDescription' - ], - 'lighthouse-core/config/default-config.js | metricGroupTitle': [ - 'categoryGroups.metrics.title' - ], - 'lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle': [ - 'categoryGroups[load-opportunities].title' - ], - 'lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription': [ - 'categoryGroups[load-opportunities].description' - ], - 'lighthouse-core/config/default-config.js | budgetsGroupTitle': [ - 'categoryGroups.budgets.title' - ], - 'lighthouse-core/config/default-config.js | budgetsGroupDescription': [ - 'categoryGroups.budgets.description' - ], - 'lighthouse-core/config/default-config.js | diagnosticsGroupTitle': [ - 'categoryGroups.diagnostics.title' - ], - 'lighthouse-core/config/default-config.js | diagnosticsGroupDescription': [ - 'categoryGroups.diagnostics.description' - ], - 'lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle': [ - 'categoryGroups[pwa-fast-reliable].title' - ], - 'lighthouse-core/config/default-config.js | pwaInstallableGroupTitle': [ - 'categoryGroups[pwa-installable].title' - ], - 'lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle': [ - 'categoryGroups[pwa-optimized].title' - ], - 'lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle': [ - 'categoryGroups[a11y-best-practices].title' - ], - 'lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription': [ - 'categoryGroups[a11y-best-practices].description' - ], - 'lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle': [ - 'categoryGroups[a11y-color-contrast].title' - ], - 'lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription': [ - 'categoryGroups[a11y-color-contrast].description' - ], - 'lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle': [ - 'categoryGroups[a11y-names-labels].title' - ], - 'lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription': [ - 'categoryGroups[a11y-names-labels].description' - ], - 'lighthouse-core/config/default-config.js | a11yNavigationGroupTitle': [ - 'categoryGroups[a11y-navigation].title' - ], - 'lighthouse-core/config/default-config.js | a11yNavigationGroupDescription': [ - 'categoryGroups[a11y-navigation].description' - ], - 'lighthouse-core/config/default-config.js | a11yAriaGroupTitle': [ - 'categoryGroups[a11y-aria].title' - ], - 'lighthouse-core/config/default-config.js | a11yAriaGroupDescription': [ - 'categoryGroups[a11y-aria].description' - ], - 'lighthouse-core/config/default-config.js | a11yLanguageGroupTitle': [ - 'categoryGroups[a11y-language].title' - ], - 'lighthouse-core/config/default-config.js | a11yLanguageGroupDescription': [ - 'categoryGroups[a11y-language].description' - ], - 'lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle': [ - 'categoryGroups[a11y-audio-video].title' - ], - 'lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription': [ - 'categoryGroups[a11y-audio-video].description' - ], - 'lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle': [ - 'categoryGroups[a11y-tables-lists].title' - ], - 'lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription': [ - 'categoryGroups[a11y-tables-lists].description' - ], - 'lighthouse-core/config/default-config.js | seoMobileGroupTitle': [ - 'categoryGroups[seo-mobile].title' - ], - 'lighthouse-core/config/default-config.js | seoMobileGroupDescription': [ - 'categoryGroups[seo-mobile].description' - ], - 'lighthouse-core/config/default-config.js | seoContentGroupTitle': [ - 'categoryGroups[seo-content].title' - ], - 'lighthouse-core/config/default-config.js | seoContentGroupDescription': [ - 'categoryGroups[seo-content].description' - ], - 'lighthouse-core/config/default-config.js | seoCrawlingGroupTitle': [ - 'categoryGroups[seo-crawl].title' - ], - 'lighthouse-core/config/default-config.js | seoCrawlingGroupDescription': [ - 'categoryGroups[seo-crawl].description' - ], - 'lighthouse-core/config/default-config.js | bestPracticesTrustSafetyGroupTitle': [ - 'categoryGroups[best-practices-trust-safety].title' - ], - 'lighthouse-core/config/default-config.js | bestPracticesUXGroupTitle': [ - 'categoryGroups[best-practices-ux].title' - ], - 'lighthouse-core/config/default-config.js | bestPracticesBrowserCompatGroupTitle': [ - 'categoryGroups[best-practices-browser-compat].title' - ], - 'lighthouse-core/config/default-config.js | bestPracticesGeneralGroupTitle': [ - 'categoryGroups[best-practices-general].title' - ] - } - }, - stackPacks: [] - }, - url: 'https://varnish-cache.org/docs/6.2/phk/thatslow.html' -} diff --git a/src/components/patterns/MQLEditor/html.js b/src/components/patterns/MQLEditor/html.js deleted file mode 100644 index 48053d872..000000000 --- a/src/components/patterns/MQLEditor/html.js +++ /dev/null @@ -1,33 +0,0 @@ -import { mqlCode } from 'helpers' -import * as json from './json' - -export const meta = () => mqlCode.html() - -export const iframe = ({ url }) => ` -<!-- HTML markup --> -<iframe src='https://api.microlink.io/?url=${url}${json.iframe}&embed=iframe.html'></iframe> - -<!-- Add third party iframe scripts --> -<script> - fetch('https://api.microlink.io/?url=${url}${json.iframe}') - .then(response => response.json()) - .then(data => { - data.iframe.scripts.forEach(attrs => { - const script = document.createElement('script') - Object.keys(attrs).forEach(key => (script[key] = attrs[key])) - document.body.appendChild(script) - }) - }); -</script> -` - -export const insights = ({ url }) => - `<Iframe src='https://lighthouse.microlink.io/?url=${encodeURI( - `https://api.microlink.io/?url=${url}${json.insights}` - )}' />` - -export const screenshot = ({ url }) => `<img -src="http://api.microilink.io?url=${url}${json.screenshot}&embed=screenshot">` - -export const pdf = ({ url }) => - `<iframe src='https://api.microlink.io/?url=${url}${json.pdf}&embed=pdf'></iframe>` diff --git a/src/components/patterns/MQLEditor/json.js b/src/components/patterns/MQLEditor/json.js deleted file mode 100644 index 1b5ad6c18..000000000 --- a/src/components/patterns/MQLEditor/json.js +++ /dev/null @@ -1,5 +0,0 @@ -export const meta = '&audio&video&iframe' -export const iframe = '&meta=false&iframe' -export const screenshot = '&meta=false&screenshot&overlay.browser=dark' -export const pdf = '&meta=false&pdf' -export const insights = '&meta=false&insights' diff --git a/src/components/patterns/index.js b/src/components/patterns/index.js index 842d9970c..c01618732 100644 --- a/src/components/patterns/index.js +++ b/src/components/patterns/index.js @@ -18,7 +18,6 @@ import Legend from './Legend/Legend' import List from './List/List' import Average from './Average/Average' import Microlink from './Microlink/Microlink' -import MQLEditor from './MQLEditor/MQLEditor' import PricingTable from './PricingTable/PricingTable' import ClusterMonitor from './ClusterMonitor/ClusterMonitor' import Healthcheck from './Healthcheck/Healthcheck' @@ -51,7 +50,6 @@ export { Legend, List, Microlink, - MQLEditor, PricingTable, Toolbar } From 33517781ac043c77dbd32681ca45e9e4b43d51d7 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:29:10 +0200 Subject: [PATCH 54/57] fix: linter --- src/components/patterns/Chat/Chat.js | 3 +-- src/pages/screenshot.js | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/patterns/Chat/Chat.js b/src/components/patterns/Chat/Chat.js index 2c0b44061..f1f357490 100644 --- a/src/components/patterns/Chat/Chat.js +++ b/src/components/patterns/Chat/Chat.js @@ -12,8 +12,7 @@ const Chat = () => { 'https://join.slack.com/t/microlinkhq/shared_invite/zt-3oe805om-HzexWW5yQNcF6cJs3dFM_A', '_blank', 'noopener noreferrer' - ) - } + )} > <Caps css={theme({ fontSize: 0, px: 3, py: 2 })}> Join in the community diff --git a/src/pages/screenshot.js b/src/pages/screenshot.js index 158a9792d..6dbe5934c 100644 --- a/src/pages/screenshot.js +++ b/src/pages/screenshot.js @@ -178,10 +178,9 @@ const Screenshot = ({ data, style }) => { isLoading ? imageStyle : { - ...imageStyle, - filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' - } - } + ...imageStyle, + filter: 'drop-shadow(rgba(0, 0, 0, 0.2) 0 16px 12px)' + }} /> </Box> </Link> From 7e1a1d7105df9cea1acd9b4566e11d7baf623bab Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:37:35 +0200 Subject: [PATCH 55/57] fix: react warnings --- src/components/elements/Video/Video.js | 2 +- src/components/icons/Jekyll.js | 2 +- src/components/patterns/Aside/AsideBase.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/elements/Video/Video.js b/src/components/elements/Video/Video.js index 0c54473b9..2b1d4ac7f 100644 --- a/src/components/elements/Video/Video.js +++ b/src/components/elements/Video/Video.js @@ -3,7 +3,7 @@ import Box from '../Box' import React from 'react' const Video = props => ( - <Box as='video' controls autoPlay muted loop playsinline {...props} /> + <Box as='video' controls autoPlay muted loop playsInline {...props} /> ) export default Video diff --git a/src/components/icons/Jekyll.js b/src/components/icons/Jekyll.js index 8983b3d1f..407245bd0 100644 --- a/src/components/icons/Jekyll.js +++ b/src/components/icons/Jekyll.js @@ -8,7 +8,7 @@ export const Jekyll = ({ color = '#333333', ...props }) => ( x='0px' y='0px' viewBox='0 0 512 512' - enable-background='new 0 0 512 512' + enableBackground='new 0 0 512 512' {...props} > <g id='logo-bg-dark'> diff --git a/src/components/patterns/Aside/AsideBase.js b/src/components/patterns/Aside/AsideBase.js index 12dd5b4e2..16ca518f9 100644 --- a/src/components/patterns/Aside/AsideBase.js +++ b/src/components/patterns/Aside/AsideBase.js @@ -71,7 +71,7 @@ const AsideWrapper = styled(Box)` width: ${ASIDE_WIDTH}; transition: transform ${transition.medium}; - ${isNot('isOpen')` + ${isNot('$isOpen')` transform: translateX(-100%); `}; } @@ -114,7 +114,7 @@ const Aside = ({ pt: [0, 0, 0, 5], pr: [0, 0, 0, '14px'] })} - isOpen={isOpen} + $isOpen={isOpen} {...props} > <Flex From c9d8e67b60b487d04b17507de18f2c477a17ae18 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 13:39:24 +0200 Subject: [PATCH 56/57] fix(markdown): iframe max-width --- src/components/markdown/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/markdown/index.js b/src/components/markdown/index.js index 38f57ea43..f9fc8d3b3 100644 --- a/src/components/markdown/index.js +++ b/src/components/markdown/index.js @@ -257,9 +257,9 @@ export const Video = withContainer(_VideoBase) const _IframeBase = styled(IframeBase)` ${theme({ mx: 'auto' })} - width: ${CodeEditor.width}; height: ${CodeEditor.height}; + max-width: ${layout.small}; ` export const Iframe = withContainer(_IframeBase) From 66c41d1aba4f717259331141dc39a01202968060 Mon Sep 17 00:00:00 2001 From: Kiko Beats <josefrancisco.verdu@gmail.com> Date: Sat, 20 Jul 2024 17:57:49 +0200 Subject: [PATCH 57/57] fix: linter --- .../elements/MultiCodeEditor/MultiCodeEditor.js | 5 ++--- src/pages/sdk.js | 2 +- src/templates/index.js | 15 ++++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js index c74afe8c9..34654ad47 100644 --- a/src/components/elements/MultiCodeEditor/MultiCodeEditor.js +++ b/src/components/elements/MultiCodeEditor/MultiCodeEditor.js @@ -81,13 +81,12 @@ const MultiCodeEditor = ({ document.dispatchEvent(event) } - const updateLanguageIndex = event => setLanguageIndex(event.detail) - useEffect(() => { + const updateLanguageIndex = event => setLanguageIndex(event.detail) document.addEventListener(LOCALSTORAGE_KEY, updateLanguageIndex) return () => document.removeEventListener(LOCALSTORAGE_KEY, updateLanguageIndex) - }, []) + }, [setLanguageIndex]) return ( <CodeEditor diff --git a/src/pages/sdk.js b/src/pages/sdk.js index f6ad5139c..913200951 100644 --- a/src/pages/sdk.js +++ b/src/pages/sdk.js @@ -101,7 +101,7 @@ const LiveDemo = React.memo(function LiveDemo ({ if (card) { setMinHeight(card.getBoundingClientRect().height - 36 * 2 - 8 * 2) } - }) + }, []) const [inputUrl, setInputUrl] = useState(query.url || '') diff --git a/src/templates/index.js b/src/templates/index.js index 5079dc9c5..7da0d521a 100644 --- a/src/templates/index.js +++ b/src/templates/index.js @@ -8,11 +8,7 @@ import React from 'react' import PageTemplate from './page' import DocTemplate from './doc' -export const Head = ({ pageContext, location, data }) => { - if (!pageContext.isDocPage) { - return <Meta {...data.markdownRemark.frontmatter} /> - } - +const HeadDoc = ({ data, location, pageContext }) => { const { name } = useSiteMetadata() const activeRouteName = getActiveRouteName(location) @@ -26,6 +22,15 @@ export const Head = ({ pageContext, location, data }) => { ) } +export const Head = ({ pageContext, location, data }) => + pageContext.isDocPage + ? ( + HeadDoc({ location, pageContext, data }) + ) + : ( + <Meta {...data.markdownRemark.frontmatter} /> + ) + const Template = ({ pageContext, data, ...props }) => { const { isDocPage, isBlogPage, lastEdited, githubUrl } = pageContext const { frontmatter, rawMarkdownBody } = data.markdownRemark