diff --git a/package.json b/package.json index 3177b0cb..6c8f40b9 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "react-dom": "16.7.0", "react-helmet": "5.2.0", "react-pose": "4.0.4", + "semver": "5.6.0", "styled-components": "4.1.3", "styled-modern-normalize": ">=0.2.0 <1.0.0", "styled-theming": "2.2.0", diff --git a/src/assets/images/icons/eva-icons/heart-fill.svg b/src/assets/images/icons/eva-icons/heart-fill.svg new file mode 100755 index 00000000..b37023aa --- /dev/null +++ b/src/assets/images/icons/eva-icons/heart-fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/eva-icons/heart-outline.svg b/src/assets/images/icons/eva-icons/heart-outline.svg new file mode 100755 index 00000000..aec33fe9 --- /dev/null +++ b/src/assets/images/icons/eva-icons/heart-outline.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/simple-icons/discord.svg b/src/assets/images/icons/simple-icons/discord.svg new file mode 100755 index 00000000..4380f9f6 --- /dev/null +++ b/src/assets/images/icons/simple-icons/discord.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/simple-icons/github.svg b/src/assets/images/icons/simple-icons/github.svg new file mode 100755 index 00000000..922b47b6 --- /dev/null +++ b/src/assets/images/icons/simple-icons/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/simple-icons/keybase.svg b/src/assets/images/icons/simple-icons/keybase.svg new file mode 100755 index 00000000..08018c59 --- /dev/null +++ b/src/assets/images/icons/simple-icons/keybase.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/images/icons/simple-icons/reddit.svg b/src/assets/images/icons/simple-icons/reddit.svg new file mode 100755 index 00000000..ef3b25d3 --- /dev/null +++ b/src/assets/images/icons/simple-icons/reddit.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/simple-icons/slack.svg b/src/assets/images/icons/simple-icons/slack.svg new file mode 100755 index 00000000..88801ae1 --- /dev/null +++ b/src/assets/images/icons/simple-icons/slack.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/images/icons/simple-icons/stackoverflow.svg b/src/assets/images/icons/simple-icons/stackoverflow.svg new file mode 100755 index 00000000..3695aa2d --- /dev/null +++ b/src/assets/images/icons/simple-icons/stackoverflow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/simple-icons/twitter.svg b/src/assets/images/icons/simple-icons/twitter.svg new file mode 100755 index 00000000..8c49818b --- /dev/null +++ b/src/assets/images/icons/simple-icons/twitter.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons/spectrum.svg b/src/assets/images/icons/spectrum.svg new file mode 100644 index 00000000..a1de462c --- /dev/null +++ b/src/assets/images/icons/spectrum.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/logos/arcticicestudio.svg b/src/assets/images/logos/arcticicestudio.svg new file mode 100644 index 00000000..62affec4 --- /dev/null +++ b/src/assets/images/logos/arcticicestudio.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/atoms/core/Link/styles.js b/src/components/atoms/core/Link/styles.js index 9a3aaf97..978bc8cf 100644 --- a/src/components/atoms/core/Link/styles.js +++ b/src/components/atoms/core/Link/styles.js @@ -17,7 +17,7 @@ import { css } from "styled-components"; import { lighten, rgba } from "polished"; -import { colors, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; +import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; const backgroundColorHover = themedMode({ [MODE_BRIGHT_SNOW_FLURRY]: rgba(colors.nord6, 0.45), @@ -46,7 +46,8 @@ const fontColorHoverMinimal = themedMode({ const calmly = css` border-radius: 0.25em; color: ${fontColor}; - transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out; + transition: color ${motion.speed.duration.transition.text.fade}ms ease-in-out, + background-color ${motion.speed.duration.transition.text.fade}ms ease-in-out; &:hover, &:active, @@ -59,7 +60,7 @@ const calmly = css` const decent = css` border-bottom: 1px solid ${fontColor}; color: ${fontColorDecent}; - transition: color 0.2s ease-in-out; + transition: color ${motion.speed.duration.transition.text.fade}ms ease-in-out; &:hover, &:active, @@ -70,7 +71,7 @@ const decent = css` const minimal = css` border-bottom: 1px solid ${fontColor}; - transition: border-bottom-color 0.2s ease-in-out; + transition: border-bottom-color ${motion.speed.duration.transition.text.fade}ms ease-in-out; &:hover, &:active, diff --git a/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx b/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx index 8701a089..f2eacd87 100644 --- a/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx +++ b/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx @@ -26,7 +26,9 @@ const PureSiteMetadata = ({ description, keywords: keywordsNord, links: { - social: { twitter } + organization: { + social: { twitter } + } }, title }, @@ -38,7 +40,7 @@ const PureSiteMetadata = ({ }) => ( - + @@ -110,9 +112,11 @@ const SiteMetadata = ({ pathName, ...passProp }) => ( description keywords links { - social { - twitter { - id + organization { + social { + twitter { + id + } } } } diff --git a/src/components/atoms/core/vectors/divider/DividerSvg.jsx b/src/components/atoms/core/vectors/divider/DividerSvg.jsx new file mode 100644 index 00000000..1280f6f4 --- /dev/null +++ b/src/components/atoms/core/vectors/divider/DividerSvg.jsx @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A styled SVG element with essential styles for divider vector graphic components. + * + * It applies two CSS styles to render problems and ensure SVG vector graphic components are handled as block-elements. + * Setting `dislay: block` is required to prevent gaps within the container caused by the SVG being treated as text + * element (`inline-block`) by default which gets affected by the `line-height` property. This can also be fixed by + * setting `line-height: 0` instead. + * + * Due to a bug or difference between Firefox and other browser rendering engines there is a `1px` gap between rendered + * SVGs elements and the following element. + * Applying `bottom: -1px` prevents these gaps, but unfortunately also requires following elements in the DOM to + * compensate for the resulting gap. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://developer.mozilla.org/de/docs/Web/SVG + * @since 0.5.0 + */ +const DividerSvg = styled.svg` + display: block; + bottom: -1px; + left: 0; + right: 0; + width: 100%; + background-color: transparent; + pointer-events: none; + user-select: none; + vertical-align: middle; + overflow: hidden; +`; + +export default DividerSvg; diff --git a/src/components/atoms/core/vectors/divider/WaveFooter.jsx b/src/components/atoms/core/vectors/divider/WaveFooter.jsx new file mode 100644 index 00000000..608aa58d --- /dev/null +++ b/src/components/atoms/core/vectors/divider/WaveFooter.jsx @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { css } from "styled-components"; +import { darken, lighten } from "polished"; + +import { colors, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +import { themeModeFillColorStyles } from "../shared/styles"; +import DividerSvg from "./DividerSvg"; + +const fillColorWave1 = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: lighten(0.025, colors.nord6), + [MODE_DARK_NIGHT_FROST]: darken(0.02, colors.nord1) +}); + +const fillColorWave2 = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: lighten(0.035, colors.nord6), + [MODE_DARK_NIGHT_FROST]: darken(0.01, colors.nord1) +}); + +const fillColorWave3 = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.background.sectioning.primary[MODE_BRIGHT_SNOW_FLURRY], + [MODE_DARK_NIGHT_FROST]: colors.background.sectioning.primary[MODE_DARK_NIGHT_FROST] +}); + +/** + * A SVG vector graphic divider component consisting of three overlapping waves. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://developer.mozilla.org/de/docs/Web/SVG + * @since 0.5.0 + */ +const WaveFooter = props => ( + + + + + +); + +export default WaveFooter; diff --git a/src/components/atoms/core/vectors/divider/index.js b/src/components/atoms/core/vectors/divider/index.js new file mode 100644 index 00000000..e324f19f --- /dev/null +++ b/src/components/atoms/core/vectors/divider/index.js @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +/** + * @file Provides SVG vector graphic divider components. + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://developer.mozilla.org/de/docs/Web/SVG + * @since 0.5.0 + */ + +import WaveFooter from "./WaveFooter"; + +/* eslint-disable-next-line import/prefer-default-export */ +export { WaveFooter }; diff --git a/src/components/atoms/core/vectors/icons/Discord.jsx b/src/components/atoms/core/vectors/icons/Discord.jsx new file mode 100644 index 00000000..121cd9e1 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Discord.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as DiscordSVG } from "assets/images/icons/simple-icons/discord.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const DiscordIcon = styled(DiscordSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Discord" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const Discord = ({ className, svgRef }) => ; + +Discord.propTypes = iconPropTypes; + +Discord.defaultProps = iconDefaultProps; + +export default Discord; diff --git a/src/components/atoms/core/vectors/icons/GitHub.jsx b/src/components/atoms/core/vectors/icons/GitHub.jsx new file mode 100644 index 00000000..4a92e560 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/GitHub.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as GitHubSVG } from "assets/images/icons/simple-icons/github.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const GitHubIcon = styled(GitHubSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "GitHub" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const GitHub = ({ className, svgRef }) => ; + +GitHub.propTypes = iconPropTypes; + +GitHub.defaultProps = iconDefaultProps; + +export default GitHub; diff --git a/src/components/atoms/core/vectors/icons/Heart.jsx b/src/components/atoms/core/vectors/icons/Heart.jsx new file mode 100644 index 00000000..d64acfcc --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Heart.jsx @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as HeartSVGFill } from "assets/images/icons/eva-icons/heart-fill.svg"; +import { ReactComponent as HeartSVGOutline } from "assets/images/icons/eva-icons/heart-outline.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const HeartIconFill = styled(HeartSVGFill)` + ${themeModeFillColorStyles}; +`; + +const HeartIconOutline = styled(HeartSVGOutline)` + ${themeModeFillColorStyles}; +`; + +/** + * The "heart" icon from "Eva Icons" as styled SVG vector graphic component. + * The "outline" variant can be used by passing the `outlined` boolean prop. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://akveo.github.io/eva-icons + * @since 0.5.0 + */ +const Heart = ({ className, outlined, svgRef }) => + outlined ? ( + + ) : ( + + ); + +Heart.propTypes = iconPropTypes; + +Heart.defaultProps = iconDefaultProps; + +export default Heart; diff --git a/src/components/atoms/core/vectors/icons/Keybase.jsx b/src/components/atoms/core/vectors/icons/Keybase.jsx new file mode 100644 index 00000000..9ca6c410 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Keybase.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as KeybaseSVG } from "assets/images/icons/simple-icons/keybase.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const KeybaseIcon = styled(KeybaseSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Keybase" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const Keybase = ({ className, svgRef }) => ; + +Keybase.propTypes = iconPropTypes; + +Keybase.defaultProps = iconDefaultProps; + +export default Keybase; diff --git a/src/components/atoms/core/vectors/icons/Menu.jsx b/src/components/atoms/core/vectors/icons/Menu.jsx index 5bdcdd28..c0f8f7d8 100644 --- a/src/components/atoms/core/vectors/icons/Menu.jsx +++ b/src/components/atoms/core/vectors/icons/Menu.jsx @@ -19,7 +19,7 @@ const MenuIconOutline = styled(MenuSVGOutline)` `; /** - * The "menu" icon from "Eva Icons" as SVG vector graphic component. + * The "menu" icon from "Eva Icons" as styled SVG vector graphic component. * By default, it uses the fill color and transition based on the current active global theme mode. * * @author Arctic Ice Studio @@ -27,7 +27,7 @@ const MenuIconOutline = styled(MenuSVGOutline)` * @see https://akveo.github.io/eva-icons * @since 0.3.0 */ -const Menu = ({ svgRef }) => ; +const Menu = ({ className, svgRef }) => ; Menu.propTypes = iconPropTypes; diff --git a/src/components/atoms/core/vectors/icons/Moon.jsx b/src/components/atoms/core/vectors/icons/Moon.jsx index f7f7d3b7..a165a444 100644 --- a/src/components/atoms/core/vectors/icons/Moon.jsx +++ b/src/components/atoms/core/vectors/icons/Moon.jsx @@ -24,7 +24,7 @@ const MoonIconOutline = styled(MoonSVGOutline)` `; /** - * The "moon" icon from "Eva Icons" as SVG vector graphic component. + * The "moon" icon from "Eva Icons" as styled SVG vector graphic component. * The "outline" variant can be used by passing the `outlined` boolean prop. * By default, it uses the fill color and transition based on the current active global theme mode. * @@ -33,8 +33,12 @@ const MoonIconOutline = styled(MoonSVGOutline)` * @see https://akveo.github.io/eva-icons * @since 0.3.0 */ -const Moon = ({ outlined, svgRef }) => - outlined ? : ; +const Moon = ({ className, outlined, svgRef }) => + outlined ? ( + + ) : ( + + ); Moon.propTypes = iconPropTypes; diff --git a/src/components/atoms/core/vectors/icons/Reddit.jsx b/src/components/atoms/core/vectors/icons/Reddit.jsx new file mode 100644 index 00000000..b61b55f9 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Reddit.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as RedditSVG } from "assets/images/icons/simple-icons/reddit.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const RedditIcon = styled(RedditSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Reddit" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const Reddit = ({ className, svgRef }) => ; + +Reddit.propTypes = iconPropTypes; + +Reddit.defaultProps = iconDefaultProps; + +export default Reddit; diff --git a/src/components/atoms/core/vectors/icons/Slack.jsx b/src/components/atoms/core/vectors/icons/Slack.jsx new file mode 100644 index 00000000..d47bb75a --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Slack.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as SlackSVG } from "assets/images/icons/simple-icons/slack.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const SlackIcon = styled(SlackSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Slack" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const Slack = ({ className, svgRef }) => ; + +Slack.propTypes = iconPropTypes; + +Slack.defaultProps = iconDefaultProps; + +export default Slack; diff --git a/src/components/atoms/core/vectors/icons/Spectrum.jsx b/src/components/atoms/core/vectors/icons/Spectrum.jsx new file mode 100644 index 00000000..e1f265ae --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Spectrum.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as SpectrumSVG } from "assets/images/icons/spectrum.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const SpectrumIcon = styled(SpectrumSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Spectrum" logo icon as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://github.com/withspectrum/spectrum/blob/alpha/public/img/mark.svg + * @since 0.5.0 + */ +const Spectrum = ({ className, svgRef }) => ; + +Spectrum.propTypes = iconPropTypes; + +Spectrum.defaultProps = iconDefaultProps; + +export default Spectrum; diff --git a/src/components/atoms/core/vectors/icons/StackOverflow.jsx b/src/components/atoms/core/vectors/icons/StackOverflow.jsx new file mode 100644 index 00000000..50d753a7 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/StackOverflow.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as StackOverflowSVG } from "assets/images/icons/simple-icons/stackoverflow.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const StackOverflowIcon = styled(StackOverflowSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "StackOverflow" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const StackOverflow = ({ className, svgRef }) => ; + +StackOverflow.propTypes = iconPropTypes; + +StackOverflow.defaultProps = iconDefaultProps; + +export default StackOverflow; diff --git a/src/components/atoms/core/vectors/icons/Sun.jsx b/src/components/atoms/core/vectors/icons/Sun.jsx index 69a0bce4..f5ba4331 100644 --- a/src/components/atoms/core/vectors/icons/Sun.jsx +++ b/src/components/atoms/core/vectors/icons/Sun.jsx @@ -24,7 +24,7 @@ const SunIconOutline = styled(SunSVGOutline)` `; /** - * The "sun" icon from "Eva Icons" as SVG vector graphic component. + * The "sun" icon from "Eva Icons" as styled SVG vector graphic component. * The "outline" variant can be used by passing the `outlined` boolean prop. * By default, it uses the fill color and transition based on the current active global theme mode. * @@ -33,7 +33,12 @@ const SunIconOutline = styled(SunSVGOutline)` * @see https://akveo.github.io/eva-icons * @since 0.3.0 */ -const Sun = ({ outlined, svgRef }) => (outlined ? : ); +const Sun = ({ className, outlined, svgRef }) => + outlined ? ( + + ) : ( + + ); Sun.propTypes = iconPropTypes; diff --git a/src/components/atoms/core/vectors/icons/Twitter.jsx b/src/components/atoms/core/vectors/icons/Twitter.jsx new file mode 100644 index 00000000..205eb7f3 --- /dev/null +++ b/src/components/atoms/core/vectors/icons/Twitter.jsx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import styled from "styled-components"; + +import { ReactComponent as TwitterSVG } from "assets/images/icons/simple-icons/twitter.svg"; + +import { iconDefaultProps, iconPropTypes, themeModeFillColorStyles } from "../shared"; + +const TwitterIcon = styled(TwitterSVG)` + ${themeModeFillColorStyles}; +`; + +/** + * The "Twitter" logo icon from the "Simple Icons" project as styled SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://simpleicons.org + * @since 0.5.0 + */ +const Twitter = ({ className, svgRef }) => ; + +Twitter.propTypes = iconPropTypes; + +Twitter.defaultProps = iconDefaultProps; + +export default Twitter; diff --git a/src/components/atoms/core/vectors/icons/index.js b/src/components/atoms/core/vectors/icons/index.js index f1c8e068..6581bf7a 100644 --- a/src/components/atoms/core/vectors/icons/index.js +++ b/src/components/atoms/core/vectors/icons/index.js @@ -15,8 +15,17 @@ * @since 0.3.0 */ +import Discord from "./Discord"; +import GitHub from "./GitHub"; +import Heart from "./Heart"; +import Keybase from "./Keybase"; import Menu from "./Menu"; import Moon from "./Moon"; +import Reddit from "./Reddit"; +import Slack from "./Slack"; +import Spectrum from "./Spectrum"; +import StackOverflow from "./StackOverflow"; import Sun from "./Sun"; +import Twitter from "./Twitter"; -export { Menu, Moon, Sun }; +export { Discord, GitHub, Heart, Keybase, Menu, Moon, Reddit, Slack, Spectrum, StackOverflow, Sun, Twitter }; diff --git a/src/components/atoms/core/vectors/logos/ArcticIceStudio.jsx b/src/components/atoms/core/vectors/logos/ArcticIceStudio.jsx new file mode 100644 index 00000000..a1919b42 --- /dev/null +++ b/src/components/atoms/core/vectors/logos/ArcticIceStudio.jsx @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +import { ReactComponent as ArcticIceStudioSVG } from "assets/images/logos/arcticicestudio.svg"; + +import { themeModeFillColorStyles } from "../shared"; + +/** + * The Arctic Ice Studio logo as SVG vector graphic component. + * By default, it uses the fill color and transition based on the current active global theme mode. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://arcticicestudio.com + * @since 0.5.0 + */ +const ArcticIceStudio = styled(ArcticIceStudioSVG)` + ${themeModeFillColorStyles}; +`; + +export default ArcticIceStudio; diff --git a/src/components/atoms/core/vectors/logos/index.js b/src/components/atoms/core/vectors/logos/index.js index 9aff104b..68f7bc0d 100644 --- a/src/components/atoms/core/vectors/logos/index.js +++ b/src/components/atoms/core/vectors/logos/index.js @@ -15,7 +15,7 @@ * @since 0.3.0 */ +import ArcticIceStudio from "./ArcticIceStudio"; import Nord from "./Nord"; -/* eslint-disable-next-line import/prefer-default-export */ -export { Nord }; +export { ArcticIceStudio, Nord }; diff --git a/src/components/containers/core/Section/Content.jsx b/src/components/containers/core/Section/Content.jsx index 3e7bb80f..959669ad 100644 --- a/src/components/containers/core/Section/Content.jsx +++ b/src/components/containers/core/Section/Content.jsx @@ -19,8 +19,8 @@ import CoreContent from "containers/core/Content"; * @since 0.3.0 */ const Content = styled(CoreContent)` - margin-top: ${({ compact }) => !compact && "5em"}; - margin-bottom: ${({ compact }) => !compact && "5em"}; + padding-top: ${({ compact }) => !compact && "5em"}; + padding-bottom: ${({ compact }) => !compact && "5em"}; `; export default Content; diff --git a/src/components/layouts/core/BaseLayout/BaseLayout.jsx b/src/components/layouts/core/BaseLayout/BaseLayout.jsx index 7e339530..68d94e6b 100644 --- a/src/components/layouts/core/BaseLayout/BaseLayout.jsx +++ b/src/components/layouts/core/BaseLayout/BaseLayout.jsx @@ -10,6 +10,7 @@ import React, { Fragment } from "react"; import PropTypes from "prop-types"; +import Footer from "organisms/core/Footer"; import Header from "organisms/core/Header"; import Page from "containers/core/Page"; import Root from "containers/core/Root"; @@ -28,6 +29,7 @@ const BaseLayout = ({ children, pathName }) => ( {children} + ); diff --git a/src/components/organisms/core/Footer/Footer.jsx b/src/components/organisms/core/Footer/Footer.jsx new file mode 100644 index 00000000..dae07b06 --- /dev/null +++ b/src/components/organisms/core/Footer/Footer.jsx @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React, { Fragment } from "react"; +import { css } from "styled-components"; +/* eslint-disable-next-line import/no-extraneous-dependencies */ +import { Match } from "@reach/router"; +import { StaticQuery, graphql } from "gatsby"; + +import Link from "atoms/core/Link"; +import { A } from "atoms/core/HTMLElements"; +import { GitHub, Heart, Keybase, Reddit, Slack, Spectrum, StackOverflow, Twitter } from "atoms/core/vectors/icons"; +import { ArcticIceStudio } from "atoms/core/vectors/logos"; +import Section, { Content } from "containers/core/Section"; +import { isRoutePartiallyMatch } from "utils"; +import sitemapCategories from "data/components/organisms/core/Footer/sitemapCategories"; +import { links as projectLinks } from "data/project"; +import { + COPYRIGHT_YEAR, + GIT_BRANCH, + GIT_COMMITHASH, + GIT_COMMITS_AHEAD, + VERSION, + VERSION_CHANNEL, + VERSION_STABILITY_STATUS +} from "config/project/constants"; + +import { heartIconStyles, organizationBrandLogoHeight, socialNetworkingIconStyles } from "./styles"; +import { + Category, + Copyright, + Grid, + Metadata, + OrganizationBrand, + OrganizationBrandCaption, + Sitemap, + SitemapCategory, + SitemapLink, + SitemapList, + SocialNetworking +} from "./styled"; + +/** + * Renders the sitemap category links. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const renderSitemapCategories = sitemapCategories.map(({ name, url = "", links }, idx) => ( + + + + {({ location, match }) => ( + + {!url ? {name} : {name}} + + )} + + + + {links.map(({ title: linkTitle, url: linkURL }) => ( + + {linkTitle} + + ))} + + +)); + +/** + * The essential footer component that provides the Arctic Ice Studio's organization branding logo and caption, + * networking & social media links as well as the copyright paragraph including version information. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer + * @since 0.5.0 + */ +const Footer = () => ( + ( + + + + + + + Arctic Ice Studio + + + + + + + + + + + + + + + + + + + + + + + + + + + + © 2016- + {COPYRIGHT_YEAR} Arctic Ice Studio &{" "} + Sven Greb + + + Made with{" "} + {" "} + in Germany + + + + {VERSION} + + + + + + {renderSitemapCategories} + + + + )} + /> + /* eslint-enable react/jsx-no-bind */ +); + +export default Footer; diff --git a/src/components/organisms/core/Footer/index.js b/src/components/organisms/core/Footer/index.js new file mode 100644 index 00000000..dfe8043c --- /dev/null +++ b/src/components/organisms/core/Footer/index.js @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +export { default } from "./Footer"; diff --git a/src/components/organisms/core/Footer/styled/Category.jsx b/src/components/organisms/core/Footer/styled/Category.jsx new file mode 100644 index 00000000..a1721820 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/Category.jsx @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import PropTypes from "prop-types"; +import styled from "styled-components"; + +import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +import { sitemapCategoryFontSize } from "../styles"; + +const fontColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: ({ isActiveRouteMatch }) => + isActiveRouteMatch ? colors.font.base[MODE_BRIGHT_SNOW_FLURRY] : colors.font.faded[MODE_BRIGHT_SNOW_FLURRY], + [MODE_DARK_NIGHT_FROST]: ({ isActiveRouteMatch }) => + isActiveRouteMatch ? colors.font.base[MODE_DARK_NIGHT_FROST] : colors.font.faded[MODE_DARK_NIGHT_FROST] +}); + +const borderBottomColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: ({ isActiveRouteMatch }) => + isActiveRouteMatch ? colors.font.base[MODE_BRIGHT_SNOW_FLURRY] : "transparent", + [MODE_DARK_NIGHT_FROST]: ({ isActiveRouteMatch }) => + isActiveRouteMatch ? colors.font.base[MODE_DARK_NIGHT_FROST] : "transparent" +}); + +/** + * A container for the heading of a sitemap category. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Category = styled.div` + align-self: center; + font-size: ${sitemapCategoryFontSize}; + color: ${fontColor}; + border-bottom: 2px solid ${borderBottomColor}; + transition: border-bottom ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out, + color ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out; +`; + +Category.propTypes = { + /** + * Indicates if the category matches the currently active route. + */ + isActiveRouteMatch: PropTypes.bool +}; + +Category.defaultProps = { + isActiveRouteMatch: false +}; + +export default Category; diff --git a/src/components/organisms/core/Footer/styled/Copyright.jsx b/src/components/organisms/core/Footer/styled/Copyright.jsx new file mode 100644 index 00000000..5f571a64 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/Copyright.jsx @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +const fontColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.font.faded[MODE_BRIGHT_SNOW_FLURRY], + [MODE_DARK_NIGHT_FROST]: colors.font.faded[MODE_DARK_NIGHT_FROST] +}); + +/** + * A container for copyright related metadata components. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Copyright = styled.div` + display: flex; + flex-direction: column; + text-align: center; + font-size: 0.8em; + color: ${fontColor}; + transition: color ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out; + margin-top: 1.125em; + + ${({ theme }) => theme.media.tabletLandscape` + display: block; + text-align: start; + `}; +`; + +export default Copyright; diff --git a/src/components/organisms/core/Footer/styled/Grid.jsx b/src/components/organisms/core/Footer/styled/Grid.jsx new file mode 100644 index 00000000..be1f2c1c --- /dev/null +++ b/src/components/organisms/core/Footer/styled/Grid.jsx @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A footer container that defines the grid layout. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Grid = styled.div` + display: flex; + flex-direction: column; + + ${({ theme }) => theme.media.tabletPortrait` + display: grid; + grid-template-columns: repeat(${({ categoryCount }) => categoryCount}, 1fr); + grid-template-rows: auto; + grid-row-gap: 1em; + `}; + + ${({ theme }) => theme.media.tabletLandscape` + grid-template-columns: 30% repeat(${({ categoryCount }) => categoryCount}, 1fr); + `}; +`; + +export default Grid; diff --git a/src/components/organisms/core/Footer/styled/Metadata.jsx b/src/components/organisms/core/Footer/styled/Metadata.jsx new file mode 100644 index 00000000..bb2ea635 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/Metadata.jsx @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A container for the grid cell that contains metadata components. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Metadata = styled.div` + display: flex; + grid-column: span ${({ categoryCount }) => categoryCount}; + flex-direction: column; + align-items: center; + + ${({ theme }) => theme.media.tabletLandscape` + grid-column: unset; + justify-content: space-between; + align-items: unset; + `}; +`; + +export default Metadata; diff --git a/src/components/organisms/core/Footer/styled/OrganizationBrand.jsx b/src/components/organisms/core/Footer/styled/OrganizationBrand.jsx new file mode 100644 index 00000000..d80bcf31 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/OrganizationBrand.jsx @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A container for the grid cell that contains branding components. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const OrganizationBrand = styled.div` + display: flex; + align-items: center; + margin-bottom: 2em; +`; + +export default OrganizationBrand; diff --git a/src/components/organisms/core/Footer/styled/OrganizationBrandCaption.jsx b/src/components/organisms/core/Footer/styled/OrganizationBrandCaption.jsx new file mode 100644 index 00000000..1ad92bee --- /dev/null +++ b/src/components/organisms/core/Footer/styled/OrganizationBrandCaption.jsx @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +import { organizationBrandCaptionFontSize } from "../styles"; + +/** + * A brand caption. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const OrganizationBrandCaption = styled.span` + font-size: ${organizationBrandCaptionFontSize}; + font-weight: 400; + margin-left: 0.7em; +`; + +export default OrganizationBrandCaption; diff --git a/src/components/organisms/core/Footer/styled/Sitemap.jsx b/src/components/organisms/core/Footer/styled/Sitemap.jsx new file mode 100644 index 00000000..8ff59a4c --- /dev/null +++ b/src/components/organisms/core/Footer/styled/Sitemap.jsx @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A container for sitemap components. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Sitemap = styled.div` + display: flex; + flex-direction: column; + align-items: center; + margin-top: 1em; + margin-bottom: 1em; + + ${({ theme }) => theme.media.tabletPortrait` + align-items: unset; + margin-top: 0; + margin-bottom: 0; + `}; +`; + +export default Sitemap; diff --git a/src/components/organisms/core/Footer/styled/SitemapCategory.jsx b/src/components/organisms/core/Footer/styled/SitemapCategory.jsx new file mode 100644 index 00000000..8b6be8c9 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/SitemapCategory.jsx @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +const borderBottomColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.nord4, + [MODE_DARK_NIGHT_FROST]: colors.nord3 +}); + +/** + * A container for a sitemap category. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const SitemapCategory = styled.div` + display: flex; + justify-content: center; + border-bottom: 1px solid ${borderBottomColor}; + transition: border-bottom ${motion.speed.duration.transition.base.themeModeSwitch}ms ease-in-out; + margin-bottom: 1em; + width: 70%; + user-select: none; + + ${({ theme }) => theme.media.tabletPortrait` + width: unset; + `}; + + ${({ theme }) => theme.media.tabletLandscape` + justify-content: unset; + `}; +`; + +export default SitemapCategory; diff --git a/src/components/organisms/core/Footer/styled/SitemapLink.jsx b/src/components/organisms/core/Footer/styled/SitemapLink.jsx new file mode 100644 index 00000000..7d61883f --- /dev/null +++ b/src/components/organisms/core/Footer/styled/SitemapLink.jsx @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +import { A } from "atoms/core/HTMLElements"; +import { colors, motion, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +const fontColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.font.faded[MODE_BRIGHT_SNOW_FLURRY], + [MODE_DARK_NIGHT_FROST]: colors.font.faded[MODE_DARK_NIGHT_FROST] +}); + +const fontColorHover = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.font.base[MODE_BRIGHT_SNOW_FLURRY], + [MODE_DARK_NIGHT_FROST]: colors.font.base[MODE_DARK_NIGHT_FROST] +}); + +/** + * A link for a sitemap page link. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const SitemapLink = styled(A)` + display: block; + padding: 0.4em 0; + font-size: 0.9em; + color: ${fontColor}; + transition: color ${motion.speed.duration.transition.text.fade}ms ease-in-out; + + &:active, + &:focus, + &:hover { + color: ${fontColorHover}; + } + + &:first-child { + padding-top: 0; + } + + &:last-child { + padding-bottom: 0; + } +`; + +export default SitemapLink; diff --git a/src/components/organisms/core/Footer/styled/SitemapList.jsx b/src/components/organisms/core/Footer/styled/SitemapList.jsx new file mode 100644 index 00000000..7eef7cee --- /dev/null +++ b/src/components/organisms/core/Footer/styled/SitemapList.jsx @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A container for sitemap page links. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const SitemapList = styled.div` + text-align: center; + + ${({ theme }) => theme.media.tabletLandscape` + text-align: start; + `}; +`; + +export default SitemapList; diff --git a/src/components/organisms/core/Footer/styled/SocialNetworking.jsx b/src/components/organisms/core/Footer/styled/SocialNetworking.jsx new file mode 100644 index 00000000..9f62c525 --- /dev/null +++ b/src/components/organisms/core/Footer/styled/SocialNetworking.jsx @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import styled from "styled-components"; + +/** + * A container for the grid cell that contains social media & networking related components. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const SocialNetworking = styled.div` + display: flex; + justify-content: space-between; + + ${({ theme }) => theme.media.tabletLandscape` + justify-content: unset; + + * { + margin: 0 0.625em; + + &:last-child { + margin-right: 0; + } + + &:first-child { + margin-left: 0; + } + } + `}; +`; + +export default SocialNetworking; diff --git a/src/components/organisms/core/Footer/styled/index.js b/src/components/organisms/core/Footer/styled/index.js new file mode 100644 index 00000000..87fe26ae --- /dev/null +++ b/src/components/organisms/core/Footer/styled/index.js @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import Category from "./Category"; +import Copyright from "./Copyright"; +import Grid from "./Grid"; +import Metadata from "./Metadata"; +import OrganizationBrand from "./OrganizationBrand"; +import OrganizationBrandCaption from "./OrganizationBrandCaption"; +import Sitemap from "./Sitemap"; +import SitemapCategory from "./SitemapCategory"; +import SitemapLink from "./SitemapLink"; +import SitemapList from "./SitemapList"; +import SocialNetworking from "./SocialNetworking"; + +export { + Category, + Copyright, + Grid, + Metadata, + OrganizationBrand, + OrganizationBrandCaption, + Sitemap, + SitemapCategory, + SitemapLink, + SitemapList, + SocialNetworking +}; diff --git a/src/components/organisms/core/Footer/styles.js b/src/components/organisms/core/Footer/styles.js new file mode 100644 index 00000000..bfa705bb --- /dev/null +++ b/src/components/organisms/core/Footer/styles.js @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +/** + * @file Provides component styles. + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ + +import { css } from "styled-components"; +import { darken, lighten } from "polished"; + +import { colors, motion, ms, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +const socialNetworkingIconFillColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: lighten(0.15, colors.font.base[MODE_BRIGHT_SNOW_FLURRY]), + [MODE_DARK_NIGHT_FROST]: darken(0.1, colors.font.base[MODE_DARK_NIGHT_FROST]) +}); + +const socialNetworkingIconStyles = css` + display: inline-block; + width: 1em; + height: 1em; + fill: ${socialNetworkingIconFillColor}; + transition: fill ${motion.speed.duration.transition.text.fade}ms ease-in-out; + + &:active, + &:focus, + &:hover { + fill: ${colors.nord8}; + } +`; + +const heartIconStyles = css` + width: 0.8em; + height: 0.8em; + vertical-align: middle; + fill: ${({ theme }) => lighten(0.2, theme.colors.nord11)}; +`; + +const organizationBrandLogoHeight = ms(4); + +const organizationBrandCaptionFontSize = ms(3); + +const sitemapCategoryFontSize = ms(1); + +export { + heartIconStyles, + organizationBrandCaptionFontSize, + organizationBrandLogoHeight, + sitemapCategoryFontSize, + socialNetworkingIconStyles +}; diff --git a/src/components/organisms/page/404/SectionLanding/SectionLanding.jsx b/src/components/organisms/page/404/SectionLanding/SectionLanding.jsx index aaaaabdb..ef88d83a 100644 --- a/src/components/organisms/page/404/SectionLanding/SectionLanding.jsx +++ b/src/components/organisms/page/404/SectionLanding/SectionLanding.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import ErrorState404 from "molecules/core/ErrorState404"; @@ -30,6 +31,7 @@ const SectionLanding = () => ( subline="…but that's not the place to find the page you were looking for." /> + ); diff --git a/src/components/organisms/page/blog/SectionBlogPosts/SectionBlogPosts.jsx b/src/components/organisms/page/blog/SectionBlogPosts/SectionBlogPosts.jsx index 3f6f9ad6..65f05739 100644 --- a/src/components/organisms/page/blog/SectionBlogPosts/SectionBlogPosts.jsx +++ b/src/components/organisms/page/blog/SectionBlogPosts/SectionBlogPosts.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import EmptyState from "molecules/core/EmptyState"; @@ -30,6 +31,7 @@ const SectionBlogPosts = () => ( subline="Please check back later, we're working hard on this page!" /> + ); diff --git a/src/components/organisms/page/community/SectionLanding/SectionLanding.jsx b/src/components/organisms/page/community/SectionLanding/SectionLanding.jsx index 10e2fb55..e52a8d6b 100644 --- a/src/components/organisms/page/community/SectionLanding/SectionLanding.jsx +++ b/src/components/organisms/page/community/SectionLanding/SectionLanding.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import EmptyState from "molecules/core/EmptyState"; @@ -30,6 +31,7 @@ const SectionLanding = () => ( subline="Please check back later, we're working hard on this page!" /> + ); diff --git a/src/components/organisms/page/docs/SectionLanding/SectionLanding.jsx b/src/components/organisms/page/docs/SectionLanding/SectionLanding.jsx index d009f38f..ecb532a3 100644 --- a/src/components/organisms/page/docs/SectionLanding/SectionLanding.jsx +++ b/src/components/organisms/page/docs/SectionLanding/SectionLanding.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import EmptyState from "molecules/core/EmptyState"; @@ -30,6 +31,7 @@ const SectionLanding = () => ( subline="Please check back later, we're working hard on this page!" /> + ); diff --git a/src/components/organisms/page/landing/SectionHero/SectionHero.jsx b/src/components/organisms/page/landing/SectionHero/SectionHero.jsx index de645530..7f19c61f 100644 --- a/src/components/organisms/page/landing/SectionHero/SectionHero.jsx +++ b/src/components/organisms/page/landing/SectionHero/SectionHero.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import EmptyState from "molecules/core/EmptyState"; @@ -30,6 +31,7 @@ const SectionHero = () => ( subline="Please check back later, we're working hard on this page!" /> + ); diff --git a/src/components/organisms/page/ports/SectionLanding/SectionLanding.jsx b/src/components/organisms/page/ports/SectionLanding/SectionLanding.jsx index e0227239..86074b76 100644 --- a/src/components/organisms/page/ports/SectionLanding/SectionLanding.jsx +++ b/src/components/organisms/page/ports/SectionLanding/SectionLanding.jsx @@ -9,6 +9,7 @@ import React from "react"; +import { WaveFooter } from "atoms/core/vectors/divider"; import Section, { Content } from "containers/core/Section"; import EmptyState from "molecules/core/EmptyState"; @@ -30,6 +31,7 @@ const SectionLanding = () => ( subline="Please check back later, we're working hard on this page!" /> + ); diff --git a/src/config/project/constants.js b/src/config/project/constants.js new file mode 100644 index 00000000..ff50559e --- /dev/null +++ b/src/config/project/constants.js @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +/** + * @file Provides general project constants. + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ + +import { metadataNordDocs } from "data/project"; +import { getSemVerFromGitDescribe } from "utils"; + +/** + * The current copyright year. + * + * @constant {string} + */ +const COPYRIGHT_YEAR = new Date().getFullYear(); + +/** + * The date format for the "date-fns" library according to ISO 8601. + * + * @constant {string} + * @see https://date-fns.org/v1.29.0/docs/format + * @see https://en.wikipedia.org/wiki/ISO_8601 + */ +const DATE_FORMAT = "yyyy-MM-ddTHH:mm:ssxx"; + +/** + * The name of the current Git branch extracted from the local Git repository. + * + * @constant {string} + */ +const GIT_BRANCH = process.env.NORD_DOCS_GIT_BRANCH || ""; + +/** + * The full SHA hash of the latest Git commit extracted from the local Git repository. + * + * @constant {string} + */ +const GIT_COMMITHASH = process.env.NORD_DOCS_GIT_COMMITHASH || ""; + +/** + * The count of additional commits on top of the latest tag extracted from the local Git repository. + * + * @constant {string} + */ +const GIT_COMMITS_AHEAD = getSemVerFromGitDescribe(process.env.NORD_DOCS_GIT_VERSION)?.commitsAhead; + +/** + * The version (SemVer) extracted from the local Git repository. Defaults to the version of the package metadata if the + * "NORD_DOCS_GIT_VERSION" environment variable is not set or empty. + * + * @constant {string} + */ +const VERSION = getSemVerFromGitDescribe(process.env.NORD_DOCS_GIT_VERSION)?.raw || metadataNordDocs.version; + +/** + * The version (SemVer) channel extracted from the {@link VERSION}. + * + * @constant {string} + */ +const VERSION_CHANNEL = getSemVerFromGitDescribe(process.env.NORD_DOCS_GIT_VERSION)?.channel; + +/** + * The version (SemVer) channel extracted from the {@link VERSION}. + * + * @constant {string} + */ +const VERSION_STABILITY_STATUS = getSemVerFromGitDescribe(process.env.NORD_DOCS_GIT_VERSION)?.stabilityStatus; + +export { + COPYRIGHT_YEAR, + DATE_FORMAT, + GIT_BRANCH, + GIT_COMMITHASH, + GIT_COMMITS_AHEAD, + VERSION, + VERSION_CHANNEL, + VERSION_STABILITY_STATUS +}; diff --git a/src/data/components/organisms/core/Footer/sitemapCategories.js b/src/data/components/organisms/core/Footer/sitemapCategories.js new file mode 100644 index 00000000..d9a7a445 --- /dev/null +++ b/src/data/components/organisms/core/Footer/sitemapCategories.js @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import { ROUTE_BLOG, ROUTE_COMMUNITY, ROUTE_DOCS, ROUTE_PORTS, ROUTE_ROOT } from "config/routes/mappings"; + +/** + * The mapping of categories for the sitemap. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const sitemapCategories = [ + { + name: "Nord", + url: ROUTE_ROOT, + links: [] + }, + { + name: "Ports", + url: ROUTE_PORTS, + links: [] + }, + { + name: "Docs", + url: ROUTE_DOCS, + links: [] + }, + { + name: "Blog", + url: ROUTE_BLOG, + links: [] + }, + { + name: "Community", + url: ROUTE_COMMUNITY, + links: [] + } +]; + +export default sitemapCategories; diff --git a/src/data/project.js b/src/data/project.js index ebe91b3b..a9c40580 100644 --- a/src/data/project.js +++ b/src/data/project.js @@ -38,30 +38,37 @@ const links = { url: "https://spectrum.chat/arcticicestudio" } }, - social: { - github: { - id: "arcticicestudio", - url: "https://github.com/arcticicestudio" - }, - keybase: { - id: "arcticicestudio", - url: "https://keybase.io/arcticicestudio" - }, - reddit: { - id: "arcticicestudio", - url: "https://www.reddit.com/user/arcticicestudio" - }, - spectrum: { - id: "arcticicestudio", - url: "https://spectrum.chat/users/arcticicestudio" - }, - stackoverflow: { - id: "4568698", - url: "https://stackoverflow.com/users/4568698/arctic-ice-studio" - }, - twitter: { - id: "arcticicestudio", - url: "https://twitter.com/arcticicestudio" + organization: { + url: "https://arcticicestudio.com", + social: { + github: { + id: "arcticicestudio", + url: "https://github.com/arcticicestudio" + }, + keybase: { + id: "arcticicestudio", + url: "https://keybase.io/arcticicestudio" + }, + reddit: { + id: "arcticicestudio", + url: "https://www.reddit.com/user/arcticicestudio" + }, + slack: { + id: "arcticicestudio", + url: "https://arcticicestudio.slack.com" + }, + spectrum: { + id: "arcticicestudio", + url: "https://spectrum.chat/users/arcticicestudio" + }, + stackoverflow: { + id: "4568698", + url: "https://stackoverflow.com/users/4568698/arctic-ice-studio" + }, + twitter: { + id: "arcticicestudio", + url: "https://twitter.com/arcticicestudio" + } } } }; diff --git a/src/styles/theme/colors/font.js b/src/styles/theme/colors/font.js index f5523a8c..fb7452b8 100644 --- a/src/styles/theme/colors/font.js +++ b/src/styles/theme/colors/font.js @@ -14,6 +14,8 @@ * @since 0.2.0 */ +import { darken, lighten } from "polished"; + import nord from "./nord"; import { MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "../constants"; @@ -22,6 +24,11 @@ const base = { [MODE_DARK_NIGHT_FROST]: nord.nord6 }; -const font = { base }; +const faded = { + [MODE_BRIGHT_SNOW_FLURRY]: lighten(0.2, base[MODE_BRIGHT_SNOW_FLURRY]), + [MODE_DARK_NIGHT_FROST]: darken(0.2, base[MODE_DARK_NIGHT_FROST]) +}; + +const font = { base, faded }; export default font; diff --git a/src/utils/getSemVerFromGitDescribe.js b/src/utils/getSemVerFromGitDescribe.js new file mode 100644 index 00000000..4d2dd15d --- /dev/null +++ b/src/utils/getSemVerFromGitDescribe.js @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +/** + * @file Provides utility functions to get Git SemVer version information. + * @author Arctic Ice Studio + * @author Sven Greb + * @see https://git-scm.com/docs/git-describe + * @see https://semver.org + * @since 0.5.0 + */ + +import semver from "semver"; + +/** + * Returns the channel based on the passed build metadata and pre-release version. + * + * @private + * @method getVersionChannel + * @param {Array} build The build metadata of the version from which the channel should be extracted. + * @param {Array<(string|number)>} prerelease The pre-release version from which the channel should be + * extracted. + * @return {string} The channel of the passed version. + */ +const getVersionChannel = (build, prerelease) => { + if (build.length !== 0) { + if (prerelease.length !== 0) { + return "pre-release-snapshot"; + } + return "snapshot"; + } + + if (prerelease.length !== 0) { + return "pre-release"; + } + return "release"; +}; + +/** + * Returns the stability status of the passed (SemVer) version. + * + * @private + * @method getVersionStabilityStatus + * @param {Array} build The build metadata of the version from which the channel should be extracted. + * @param {Array<(string|number)>} prerelease The pre-release version from which the channel should be + * extracted. + * @return {string} The stability status of the passed version. + */ +const getVersionStabilityStatus = (build, prerelease) => { + if (build.length === 0 && prerelease.length === 0) { + return "stable"; + } + return "unstable"; +}; + +/** + * Converts the output from the Git "describe --always" command to a SemVer version. + * + * @method getSemVerFromGitDescribe + * @param {string} gitVersion The output of the Git "describe --always" command + * @return {?Object} The SemVer information, `null` otherwise if the passed `gitVersion` is not compatible with SemVer. + * @see https://semver.org + */ +const getSemVerFromGitDescribe = gitVersion => { + /* + * Split the Git version output where the array index + * + * - [0] contains the value of the recent tag that is reachable from the latest commit, or the hash of the latest + * commit if no tags have been found, e.g. "v0.1.8" or "9b205b0". + * - [1]/[2] contains, separated with a dash character, either + * - the pre-release string + * - the count of additional commits on top of the tag string (when found). + * - [2]/[3] contains, separated with a dash character, either + * - the contain the count of additional commits (if not already contained in index [1]) + * - the hash of the latest commit prefixed with the "g" character + */ + const gitVersionElements = gitVersion.split("-"); + + /* Reject invalid strings and single commit SHA hashs not compatible with SemVer. */ + if (gitVersionElements.length === 1 && !semver.valid(gitVersionElements[0])) return null; + + const tagElement = gitVersionElements[0]; + let buildMetadataElement = ""; + let commitsAhead = 0; + let preReleaseElement = ""; + let scmPrefix = ""; + + /* Extract necessary elements from array and remove count of ahead commits afterwards. */ + if (gitVersionElements.length >= 3) { + buildMetadataElement = gitVersionElements[gitVersionElements.length - 1]; + commitsAhead = Number.parseInt(gitVersionElements[gitVersionElements.length - 2], 10); + + /* + * Remove the prefix character added by "git describe" that indicates the SCM type (where "g" means "Git"). + * + * @see https://git-scm.com/docs/git-describe + */ + if (buildMetadataElement.charAt(0) === "g") { + buildMetadataElement = buildMetadataElement.substring(1); + scmPrefix = "g"; + + /* + * Prepend the separator character for build metadata as defined in the SemVer specification. + * + * @see https://semver.org/#spec-item-10 + */ + buildMetadataElement = `+${buildMetadataElement}`; + } + + gitVersionElements.splice(gitVersionElements.length - 2, 1); + } + + /* + * Extract the pre-release element and prepend the separator as defined in the SemVer specification. + * + * @see https://semver.org/#spec-item-9 + */ + if (gitVersionElements.length > 2) { + preReleaseElement = gitVersionElements[gitVersionElements.length - 2]; + preReleaseElement = `-${preReleaseElement}`; + } + + const parsedSemVer = semver.parse(`${tagElement}${preReleaseElement}${buildMetadataElement}`, { + includePrerelease: true + }); + + /* Append additional useful information about the version. */ + parsedSemVer.commitsAhead = commitsAhead; + parsedSemVer.channel = getVersionChannel(parsedSemVer.build, parsedSemVer.prerelease); + parsedSemVer.scmPrefix = scmPrefix; + parsedSemVer.stabilityStatus = getVersionStabilityStatus(parsedSemVer.build, parsedSemVer.prerelease); + + return parsedSemVer; +}; + +export default getSemVerFromGitDescribe; diff --git a/src/utils/index.js b/src/utils/index.js index c895b1b0..e5d1a04d 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -14,8 +14,9 @@ * @since 0.2.0 */ +import getSemVerFromGitDescribe from "./getSemVerFromGitDescribe"; import isRouteInternal from "./isRouteInternal"; import isRoutePartiallyMatch from "./isRoutePartiallyMatch"; import { readSessionCache, writeSessionCache } from "./sessionCache"; -export { isRouteInternal, isRoutePartiallyMatch, readSessionCache, writeSessionCache }; +export { getSemVerFromGitDescribe, isRouteInternal, isRoutePartiallyMatch, readSessionCache, writeSessionCache }; diff --git a/test/babel-config.js b/test/babel-config.js index bccbdbaf..e91bb2b6 100644 --- a/test/babel-config.js +++ b/test/babel-config.js @@ -17,7 +17,8 @@ */ const jestBabelConfig = { - presets: ["babel-preset-gatsby"] + presets: ["babel-preset-gatsby"], + plugins: ["@babel/plugin-proposal-optional-chaining", "@babel/plugin-proposal-export-default-from"] }; module.exports = require("babel-jest").createTransformer(jestBabelConfig); diff --git a/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap b/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap index 1bce632a..5a337222 100644 --- a/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap +++ b/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap @@ -18,8 +18,8 @@ exports[`theme styles matches the snapshot with \`calmly\` variant 1`] = ` .c0 { border-radius: 0.25em; color: #5e81ac; - -webkit-transition: color 0.2s ease-in-out,background-color 0.2s ease-in-out; - transition: color 0.2s ease-in-out,background-color 0.2s ease-in-out; + -webkit-transition: color 200ms ease-in-out, background-color 200ms ease-in-out; + transition: color 200ms ease-in-out, background-color 200ms ease-in-out; } .c0:hover, @@ -55,8 +55,8 @@ exports[`theme styles matches the snapshot with \`decent\` variant 1`] = ` .c0 { border-bottom: 1px solid #5e81ac; color: #2e3440; - -webkit-transition: color 0.2s ease-in-out; - transition: color 0.2s ease-in-out; + -webkit-transition: color 200ms ease-in-out; + transition: color 200ms ease-in-out; } .c0:hover, @@ -90,8 +90,8 @@ exports[`theme styles matches the snapshot with \`minimal\` variant 1`] = ` .c0 { border-bottom: 1px solid #5e81ac; - -webkit-transition: border-bottom-color 0.2s ease-in-out; - transition: border-bottom-color 0.2s ease-in-out; + -webkit-transition: border-bottom-color 200ms ease-in-out; + transition: border-bottom-color 200ms ease-in-out; } .c0:hover, @@ -126,8 +126,8 @@ exports[`theme styles matches the snapshot with default variant 1`] = ` .c0 { border-radius: 0.25em; color: #5e81ac; - -webkit-transition: color 0.2s ease-in-out,background-color 0.2s ease-in-out; - transition: color 0.2s ease-in-out,background-color 0.2s ease-in-out; + -webkit-transition: color 200ms ease-in-out, background-color 200ms ease-in-out; + transition: color 200ms ease-in-out, background-color 200ms ease-in-out; } .c0:hover, diff --git a/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx b/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx index 4d57a662..957e6afd 100644 --- a/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx +++ b/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx @@ -26,8 +26,10 @@ const staticQueryResultDataMock = { description: metadataNord.description, keywords: metadataNord.keywords, links: { - social: { - twitter: metadataNord.links.social.twitter + organization: { + social: { + twitter: metadataNord.links.organization.social.twitter + } } }, title: metadataNord.title @@ -98,7 +100,7 @@ describe("data consistency", () => { }), expect.objectContaining({ name: "twitter:site", - content: expect.stringContaining(metadataNord.links.social.twitter.id) + content: expect.stringContaining(metadataNord.links.organization.social.twitter.id) }), expect.objectContaining({ name: "twitter:description", @@ -130,17 +132,6 @@ describe("data consistency", () => { ); }); - test("contains Open Graph Protocol HTML schema `prefix` attribute", () => { - renderWithTheme(); - const generatedHelmetData = Helmet.peek(); - - expect(generatedHelmetData.htmlAttributes).toEqual( - expect.objectContaining({ - prefix: expect.stringContaining("ogp.me") - }) - ); - }); - test("contains JSON-LD schema linked data `script` tag", () => { renderWithTheme(); const generatedHelmetData = Helmet.peek(); diff --git a/test/components/containers/core/Section/Content.test.jsx b/test/components/containers/core/Section/Content.test.jsx index 7a0f968c..dd5666b1 100644 --- a/test/components/containers/core/Section/Content.test.jsx +++ b/test/components/containers/core/Section/Content.test.jsx @@ -14,23 +14,23 @@ import { Content } from "containers/core/Section"; import { renderWithTheme } from "nord-docs-test-utils"; describe("theme styles", () => { - test("has top and bottom margin", () => { + test("has top and bottom padding", () => { const { container } = renderWithTheme(Nord); - const marginTop = stripUnit(getComputedStyle(container.firstChild).marginTop); - const marginBottom = stripUnit(getComputedStyle(container.firstChild).marginBottom); + const paddingTop = stripUnit(getComputedStyle(container.firstChild).paddingTop); + const paddingBottom = stripUnit(getComputedStyle(container.firstChild).paddingBottom); - expect(marginTop).toBeGreaterThan(0); - expect(marginBottom).toBeGreaterThan(0); + expect(paddingTop).toBeGreaterThan(0); + expect(paddingBottom).toBeGreaterThan(0); expect(container.firstChild).toMatchSnapshot(); }); - test("adjusts top and bottom margin to passed props", () => { + test("adjusts top and bottom padding to passed props", () => { const { container } = renderWithTheme(Nord); - const marginTop = stripUnit(getComputedStyle(container.firstChild).marginTop); - const marginBottom = stripUnit(getComputedStyle(container.firstChild).marginBottom); + const paddingTop = stripUnit(getComputedStyle(container.firstChild).paddingTop); + const paddingBottom = stripUnit(getComputedStyle(container.firstChild).paddingBottom); - expect(marginTop).toBeFalsy(); - expect(marginBottom).toBeFalsy(); + expect(paddingTop).toBeFalsy(); + expect(paddingBottom).toBeFalsy(); expect(container.firstChild).toMatchSnapshot(); }); }); diff --git a/test/components/containers/core/Section/__snapshots__/Content.test.jsx.snap b/test/components/containers/core/Section/__snapshots__/Content.test.jsx.snap index 644adda2..ffd34279 100644 --- a/test/components/containers/core/Section/__snapshots__/Content.test.jsx.snap +++ b/test/components/containers/core/Section/__snapshots__/Content.test.jsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`theme styles adjusts top and bottom margin to passed props 1`] = ` +exports[`theme styles adjusts top and bottom padding to passed props 1`] = ` .c0 { width: 100%; } @@ -18,11 +18,11 @@ exports[`theme styles adjusts top and bottom margin to passed props 1`] = ` `; -exports[`theme styles has top and bottom margin 1`] = ` +exports[`theme styles has top and bottom padding 1`] = ` .c0 { width: 100%; - margin-top: 5em; - margin-bottom: 5em; + padding-top: 5em; + padding-bottom: 5em; } @media (min-width:75em) { diff --git a/test/components/layouts/core/BaseLayout/BaseLayout.test.jsx b/test/components/layouts/core/BaseLayout/BaseLayout.test.jsx deleted file mode 100644 index 7d06d90e..00000000 --- a/test/components/layouts/core/BaseLayout/BaseLayout.test.jsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2018-present Arctic Ice Studio - * Copyright (C) 2018-present Sven Greb - * - * Project: Nord Docs - * Repository: https://github.com/arcticicestudio/nord-docs - * License: MIT - */ - -import React, { Fragment } from "react"; -import { render } from "react-testing-library"; - -import BaseLayout from "layouts/core/BaseLayout"; - -/* - * This test is disabled because it will be covered by E2E tests with Cypress later on. - * It is also skipped due to problems with mocking transitive modules and components. - */ -test.skip("snapshot", () => { - const { container } = render( - - - - ); - expect(container).toMatchSnapshot(); -}); diff --git a/test/components/layouts/core/BaseLayout/__snapshots__/BaseLayout.test.jsx.snap b/test/components/layouts/core/BaseLayout/__snapshots__/BaseLayout.test.jsx.snap deleted file mode 100644 index 3a2e181c..00000000 --- a/test/components/layouts/core/BaseLayout/__snapshots__/BaseLayout.test.jsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`snapshot 1`] = ` - - - -`; diff --git a/test/components/organisms/core/Footer/styled/Category.test.jsx b/test/components/organisms/core/Footer/styled/Category.test.jsx new file mode 100644 index 00000000..6e3e02b8 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/Category.test.jsx @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { Category } from "organisms/core/Footer/styled"; + +describe("theme styles", () => { + test("has visible border-bottom when matching the active route", () => { + const { container } = renderWithTheme(Nord); + + expect(container.firstChild).toHaveStyleRule("border-bottom", expect.not.stringContaining("transparent")); + expect(container.firstChild).toMatchSnapshot(); + }); + + test("has invisible border-bottom when not matching the active route", () => { + const { container } = renderWithTheme(Nord); + + expect(container.firstChild).toHaveStyleRule("border-bottom", expect.stringContaining("transparent")); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/Copyright.test.jsx b/test/components/organisms/core/Footer/styled/Copyright.test.jsx new file mode 100644 index 00000000..f45b427f --- /dev/null +++ b/test/components/organisms/core/Footer/styled/Copyright.test.jsx @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em, stripUnit } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { Copyright } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + test("has required CSS breakpoints", () => { + const { container } = renderWithTheme(); + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + + expect(container.firstChild).toHaveStyleRule("display", "block", { + media: mediaQuery + }); + expect(container.firstChild).toHaveStyleRule("text-align", "start", { + media: mediaQuery + }); + }); + + test("has reduced font size", () => { + const { container } = renderWithTheme(); + const fontSize = stripUnit(getComputedStyle(container.firstChild).fontSize); + + expect(fontSize).toBeLessThan(1); + expect(container.firstChild).toHaveStyleRule("font-size", `${fontSize}em`); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/Grid.test.jsx b/test/components/organisms/core/Footer/styled/Grid.test.jsx new file mode 100644 index 00000000..6f4850a4 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/Grid.test.jsx @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { Grid } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + test("has grid layout styles for defined CSS breakpoints", () => { + const categoryCount = "5"; + const mediaQueryTabletPortrait = `(min-width: ${em(media.breakpoints.tabletPortraitLowerBoundary)})`; + const mediaQueryTabletLandscape = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "grid", { + media: mediaQueryTabletPortrait + }); + + expect(container.firstChild).toHaveStyleRule("grid-template-columns", expect.stringContaining(categoryCount), { + media: mediaQueryTabletPortrait + }); + + expect(container.firstChild).toHaveStyleRule("grid-template-rows", expect.stringContaining("auto"), { + media: mediaQueryTabletPortrait + }); + + expect(container.firstChild).toHaveStyleRule("grid-template-columns", expect.stringContaining("%"), { + media: mediaQueryTabletLandscape + }); + }); + + test("has flexbox layout styles", () => { + const { container } = renderWithTheme(); + expect(container.firstChild).toHaveStyleRule("display", "flex"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/Metadata.test.jsx b/test/components/organisms/core/Footer/styled/Metadata.test.jsx new file mode 100644 index 00000000..265f3ccf --- /dev/null +++ b/test/components/organisms/core/Footer/styled/Metadata.test.jsx @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { Metadata } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + const categoryCount = "5"; + + test("uses automatic grid column assignment for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("grid-column", "unset", { + media: mediaQuery + }); + }); + + test("spans all grid columns", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("grid-column", expect.stringContaining(categoryCount)); + }); + + test("has flexbox column layout styles", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "flex"); + expect(container.firstChild).toHaveStyleRule("flex-direction", "column"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/OrganizationBrand.test.jsx b/test/components/organisms/core/Footer/styled/OrganizationBrand.test.jsx new file mode 100644 index 00000000..07d7eb2c --- /dev/null +++ b/test/components/organisms/core/Footer/styled/OrganizationBrand.test.jsx @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { stripUnit } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { OrganizationBrand } from "organisms/core/Footer/styled"; + +describe("theme styles", () => { + test("has flexbox layout styles", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "flex"); + }); + + test("has bottom margin", () => { + const { container } = renderWithTheme(); + const marginBottom = stripUnit(getComputedStyle(container.firstChild).marginBottom); + + expect(marginBottom).toBeGreaterThan(0); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/Sitemap.test.jsx b/test/components/organisms/core/Footer/styled/Sitemap.test.jsx new file mode 100644 index 00000000..8e105bba --- /dev/null +++ b/test/components/organisms/core/Footer/styled/Sitemap.test.jsx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { stripUnit } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { Sitemap } from "organisms/core/Footer/styled"; + +describe("theme styles", () => { + test("has top and bottom margin", () => { + const { container } = renderWithTheme(); + const margingTop = stripUnit(getComputedStyle(container.firstChild).marginTop); + const marginBottom = stripUnit(getComputedStyle(container.firstChild).marginBottom); + + expect(margingTop).toBeGreaterThan(0); + expect(marginBottom).toBeGreaterThan(0); + }); + + test("has flexbox column layout styles", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "flex"); + expect(container.firstChild).toHaveStyleRule("flex-direction", "column"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/SitemapCategory.test.jsx b/test/components/organisms/core/Footer/styled/SitemapCategory.test.jsx new file mode 100644 index 00000000..212c6445 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/SitemapCategory.test.jsx @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em, stripUnit } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { SitemapCategory } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + test("resets width for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletPortraitLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("width", "unset", { + media: mediaQuery + }); + }); + + test("resets justified flexbox content for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("justify-content", "unset", { + media: mediaQuery + }); + }); + + test("has centered flexbox content layout", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "flex"); + expect(container.firstChild).toHaveStyleRule("justify-content", "center"); + }); + + test("has visible border-bottom", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("border-bottom", expect.not.stringContaining("transparent")); + }); + + test("has bottom margin", () => { + const { container } = renderWithTheme(); + const marginBottom = stripUnit(getComputedStyle(container.firstChild).marginBottom); + + expect(marginBottom).toBeGreaterThan(0); + }); + + test("has reduced width", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("width", expect.any(String)); + }); + + test("has disabled user selection", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("user-select", "none"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/SitemapLink.test.jsx b/test/components/organisms/core/Footer/styled/SitemapLink.test.jsx new file mode 100644 index 00000000..cdb2c26e --- /dev/null +++ b/test/components/organisms/core/Footer/styled/SitemapLink.test.jsx @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { stripUnit } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { SitemapLink } from "organisms/core/Footer/styled"; + +describe("theme styles", () => { + test("has top and bottom padding", () => { + const { container } = renderWithTheme(Nord); + + expect(container.firstChild).toHaveStyleRule("padding", expect.stringContaining("em")); + expect(container.firstChild).toHaveStyleRule("padding-bottom", "0", { + modifier: ":last-child" + }); + expect(container.firstChild).toHaveStyleRule("padding-top", "0", { + modifier: ":first-child" + }); + }); + + test("has reduced font size", () => { + const { container } = renderWithTheme(Nord); + const fontSize = stripUnit(getComputedStyle(container.firstChild).fontSize); + + expect(fontSize).toBeLessThan(1); + expect(container.firstChild).toHaveStyleRule("font-size", `${fontSize}em`); + }); + + test("changes color on hover", () => { + const { container } = renderWithTheme(Nord); + + expect(container.firstChild).toHaveStyleRule("color", expect.any(String), { + modifier: ":hover" + }); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(Nord); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/SitemapList.test.jsx b/test/components/organisms/core/Footer/styled/SitemapList.test.jsx new file mode 100644 index 00000000..2d7bfd5e --- /dev/null +++ b/test/components/organisms/core/Footer/styled/SitemapList.test.jsx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { SitemapList } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + test("has 'start' text alignment for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("text-align", "start", { + media: mediaQuery + }); + }); + + test("has centered text alignment", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("text-align", "center"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/SocialNetworking.test.jsx b/test/components/organisms/core/Footer/styled/SocialNetworking.test.jsx new file mode 100644 index 00000000..56e79ad9 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/SocialNetworking.test.jsx @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import React from "react"; +import { em } from "polished"; + +import { renderWithTheme } from "nord-docs-test-utils"; +import { SocialNetworking } from "organisms/core/Footer/styled"; +import { media } from "styles/theme"; + +describe("theme styles", () => { + test("sets children element margins for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("margin", expect.stringContaining("em"), { + media: mediaQuery, + modifier: "*" + }); + }); + + test("unsets justified flexbox content for defined CSS breakpoints", () => { + const mediaQuery = `(min-width: ${em(media.breakpoints.tabletLandscapeLowerBoundary)})`; + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("justify-content", "unset", { + media: mediaQuery + }); + }); + + test("has flexbox layout styles", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toHaveStyleRule("display", "flex"); + expect(container.firstChild).toHaveStyleRule("justify-content", "space-between"); + }); + + test("matches the snapshot", () => { + const { container } = renderWithTheme(); + + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/Category.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/Category.test.jsx.snap new file mode 100644 index 00000000..40393797 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/Category.test.jsx.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles has invisible border-bottom when not matching the active route 1`] = ` +.c0 { + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + font-size: 1.125em; + color: #7b88a1; + border-bottom: 2px solid transparent; + -webkit-transition: border-bottom 400ms ease-in-out, color 400ms ease-in-out; + transition: border-bottom 400ms ease-in-out, color 400ms ease-in-out; +} + + + Nord + +`; + +exports[`theme styles has visible border-bottom when matching the active route 1`] = ` +.c0 { + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; + font-size: 1.125em; + color: #4c566a; + border-bottom: 2px solid #4c566a; + -webkit-transition: border-bottom 400ms ease-in-out, color 400ms ease-in-out; + transition: border-bottom 400ms ease-in-out, color 400ms ease-in-out; +} + + + Nord + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/Copyright.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/Copyright.test.jsx.snap new file mode 100644 index 00000000..bf5585aa --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/Copyright.test.jsx.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + text-align: center; + font-size: 0.8em; + color: #7b88a1; + -webkit-transition: color 400ms ease-in-out; + transition: color 400ms ease-in-out; + margin-top: 1.125em; +} + +@media (min-width:56.25em) { + .c0 { + display: block; + text-align: start; + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/Grid.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/Grid.test.jsx.snap new file mode 100644 index 00000000..baccf296 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/Grid.test.jsx.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +@media (min-width:37.5em) { + .c0 { + display: grid; + grid-template-columns: repeat(,1fr); + grid-template-rows: auto; + grid-row-gap: 1em; + } +} + +@media (min-width:56.25em) { + .c0 { + grid-template-columns: 30% repeat(,1fr); + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/Metadata.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/Metadata.test.jsx.snap new file mode 100644 index 00000000..f318aff9 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/Metadata.test.jsx.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + grid-column: span 5; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +@media (min-width:56.25em) { + .c0 { + grid-column: unset; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + -webkit-align-items: unset; + -webkit-box-align: unset; + -ms-flex-align: unset; + align-items: unset; + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/OrganizationBrand.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/OrganizationBrand.test.jsx.snap new file mode 100644 index 00000000..a5b9cb23 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/OrganizationBrand.test.jsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 2em; +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/Sitemap.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/Sitemap.test.jsx.snap new file mode 100644 index 00000000..69f01aac --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/Sitemap.test.jsx.snap @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-top: 1em; + margin-bottom: 1em; +} + +@media (min-width:37.5em) { + .c0 { + -webkit-align-items: unset; + -webkit-box-align: unset; + -ms-flex-align: unset; + align-items: unset; + margin-top: 0; + margin-bottom: 0; + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/SitemapCategory.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapCategory.test.jsx.snap new file mode 100644 index 00000000..fe17344c --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapCategory.test.jsx.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + border-bottom: 1px solid #d8dee9; + -webkit-transition: border-bottom 400ms ease-in-out; + transition: border-bottom 400ms ease-in-out; + margin-bottom: 1em; + width: 70%; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +@media (min-width:37.5em) { + .c0 { + width: unset; + } +} + +@media (min-width:56.25em) { + .c0 { + -webkit-box-pack: unset; + -webkit-justify-content: unset; + -ms-flex-pack: unset; + justify-content: unset; + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/SitemapLink.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapLink.test.jsx.snap new file mode 100644 index 00000000..08a99304 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapLink.test.jsx.snap @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c1 { + color: inherit; + cursor: pointer; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:active, +.c1:focus, +.c1:hover, +.c1:visited { + outline: none; +} + +.c0 { + display: block; + padding: 0.4em 0; + font-size: 0.9em; + color: #7b88a1; + -webkit-transition: color 200ms ease-in-out; + transition: color 200ms ease-in-out; +} + +.c0:active, +.c0:focus, +.c0:hover { + color: #4c566a; +} + +.c0:first-child { + padding-top: 0; +} + +.c0:last-child { + padding-bottom: 0; +} + + + Nord + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/SitemapList.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapList.test.jsx.snap new file mode 100644 index 00000000..23d8bc41 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/SitemapList.test.jsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + text-align: center; +} + +@media (min-width:56.25em) { + .c0 { + text-align: start; + } +} + + +`; diff --git a/test/components/organisms/core/Footer/styled/__snapshots__/SocialNetworking.test.jsx.snap b/test/components/organisms/core/Footer/styled/__snapshots__/SocialNetworking.test.jsx.snap new file mode 100644 index 00000000..5b74a9e5 --- /dev/null +++ b/test/components/organisms/core/Footer/styled/__snapshots__/SocialNetworking.test.jsx.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +@media (min-width:56.25em) { + .c0 { + -webkit-box-pack: unset; + -webkit-justify-content: unset; + -ms-flex-pack: unset; + justify-content: unset; + } + + .c0 * { + margin: 0 0.625em; + } + + .c0 *:last-child { + margin-right: 0; + } + + .c0 *:first-child { + margin-left: 0; + } +} + + +`; diff --git a/test/pages/__snapshots__/index.test.jsx.snap b/test/pages/__snapshots__/index.test.jsx.snap deleted file mode 100644 index 3a2e181c..00000000 --- a/test/pages/__snapshots__/index.test.jsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`snapshot 1`] = ` - - - -`; diff --git a/test/pages/index.test.jsx b/test/pages/index.test.jsx deleted file mode 100644 index 4ffc144a..00000000 --- a/test/pages/index.test.jsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2018-present Arctic Ice Studio - * Copyright (C) 2018-present Sven Greb - * - * Project: Nord Docs - * Repository: https://github.com/arcticicestudio/nord-docs - * License: MIT - */ - -import React from "react"; -import { render } from "react-testing-library"; - -import Landing from "pages"; - -/* - * This test is disabled because it will be covered by E2E tests with Cypress later on. - * It is also skipped due to problems with mocking transitive modules and components. - */ -test.skip("snapshot", () => { - const { container } = render(); - expect(container).toMatchSnapshot(); -}); diff --git a/test/utils/getSemVerFromGitDescribe.test.js b/test/utils/getSemVerFromGitDescribe.test.js new file mode 100644 index 00000000..4e944c4f --- /dev/null +++ b/test/utils/getSemVerFromGitDescribe.test.js @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018-present Arctic Ice Studio + * Copyright (C) 2018-present Sven Greb + * + * Project: Nord Docs + * Repository: https://github.com/arcticicestudio/nord-docs + * License: MIT + */ + +import { getSemVerFromGitDescribe } from "utils"; + +const CHANNEL_PRERELEASE = "pre-release"; +const CHANNEL_RELEASE = "release"; +const CHANNEL_SNAPSHOT = "snapshot"; +const CHANNEL_PRERELEASE_SNAPSHOT = `${CHANNEL_PRERELEASE}-${CHANNEL_SNAPSHOT}`; +const STABILITY_STATUS_STABLE = "stable"; +const STABILITY_STATUS_UNSTABLE = "unstable"; +const SCM_PREFIX = "g"; + +const PREFIX = "v"; +const MAJOR_VERSION = "0"; +const MINOR_VERSION = "1"; +const PATCH_VERSION = "2"; +const COMMITS_AHEAD = "8"; +const COMMIT_HASH = "abcd1234"; +const PRE_RELEASE_NAME = "frost"; +const PRE_RELEASE_NUMBER = "2"; +const PRE_RELEASE = `${PRE_RELEASE_NAME}.${PRE_RELEASE_NUMBER}`; +const VERSION = `${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}`; +const VERSION_WITH_PREFIX = `${PREFIX}${VERSION}`; +const VERSION_SNAPSHOT = `${VERSION}-${COMMITS_AHEAD}-${SCM_PREFIX}${COMMIT_HASH}`; +const VERSION_PRE_RELEASE = `${VERSION}-${PRE_RELEASE}`; +const VERSION_PRE_RELEASE_SNAPTSHOT = `${VERSION_PRE_RELEASE}-${COMMITS_AHEAD}-${SCM_PREFIX}${COMMIT_HASH}`; + +describe("rejects incompatible SemVer versions", () => { + test("single commit SHA hash", () => { + expect(getSemVerFromGitDescribe(COMMIT_HASH)).toBeNull(); + }); + + test("empty string and single whitespace", () => { + expect(getSemVerFromGitDescribe("")).toBeNull(); + expect(getSemVerFromGitDescribe(" ")).toBeNull(); + }); + + test("invalid tag/version prefixes", () => { + [ + `V${VERSION}`, + `vv${VERSION}`, + `version${VERSION}`, + `invalid${VERSION}`, + `_${VERSION}`, + `_v${VERSION}`, + `v_${VERSION}`, + ` ${VERSION}`, + ` v${VERSION}` + ].forEach(invalidVersionPrefix => expect(getSemVerFromGitDescribe(invalidVersionPrefix)).toBeNull()); + }); +}); + +describe("processes valid SemVer versions including additional metadata", () => { + test("stable release version without any additional metadata", () => { + const parsedSemVer = getSemVerFromGitDescribe(VERSION_WITH_PREFIX); + + expect(parsedSemVer.version).toBe(VERSION); + expect(parsedSemVer.prerelease).toHaveLength(0); + expect(parsedSemVer.build).toHaveLength(0); + expect(parsedSemVer.commitsAhead).toBe(0); + expect(parsedSemVer.channel).toBe(CHANNEL_RELEASE); + expect(parsedSemVer.stabilityStatus).toBe(STABILITY_STATUS_STABLE); + }); + + test("snapshot version with number of commits ahead", () => { + const parsedSemVer = getSemVerFromGitDescribe(`${PREFIX}${VERSION_SNAPSHOT}`); + + expect(parsedSemVer.version).toBe(VERSION); + expect(parsedSemVer.prerelease).toHaveLength(0); + expect(parsedSemVer.build).toHaveLength(1); + expect(parsedSemVer.build).toContainEqual(COMMIT_HASH); + expect(parsedSemVer.commitsAhead).toBe(8); + expect(parsedSemVer.channel).toBe(CHANNEL_SNAPSHOT); + expect(parsedSemVer.stabilityStatus).toBe(STABILITY_STATUS_UNSTABLE); + expect(parsedSemVer.raw).toBe(`${VERSION_WITH_PREFIX}+${COMMIT_HASH}`); + }); + + test("pre-release snapshot version with number of commits ahead", () => { + const parsedSemVer = getSemVerFromGitDescribe(`${PREFIX}${VERSION_PRE_RELEASE_SNAPTSHOT}`); + + expect(parsedSemVer.version).toBe(VERSION_PRE_RELEASE); + expect(parsedSemVer.prerelease).toHaveLength(2); + expect(parsedSemVer.prerelease).toContainEqual(PRE_RELEASE_NAME); + expect(parsedSemVer.prerelease).toContainEqual(Number.parseInt(PRE_RELEASE_NUMBER, 10)); + expect(parsedSemVer.build).toHaveLength(1); + expect(parsedSemVer.build).toContainEqual(COMMIT_HASH); + expect(parsedSemVer.commitsAhead).toBe(8); + expect(parsedSemVer.channel).toBe(CHANNEL_PRERELEASE_SNAPSHOT); + expect(parsedSemVer.stabilityStatus).toBe(STABILITY_STATUS_UNSTABLE); + expect(parsedSemVer.raw).toBe(`${PREFIX}${VERSION_PRE_RELEASE}+${COMMIT_HASH}`); + }); +});