From ad114ee9d9fdbe2ef8360baaffd237ff19724af8 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Mon, 24 Dec 2018 09:51:45 +0100 Subject: [PATCH 01/15] Implement core atom `Link` component CSS styles GH-105 --- src/components/atoms/core/Link/styles.js | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/components/atoms/core/Link/styles.js diff --git a/src/components/atoms/core/Link/styles.js b/src/components/atoms/core/Link/styles.js new file mode 100644 index 00000000..9a3aaf97 --- /dev/null +++ b/src/components/atoms/core/Link/styles.js @@ -0,0 +1,82 @@ +/* + * 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 multiple styles for the `Link` component. + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ + +import { css } from "styled-components"; +import { lighten, rgba } from "polished"; + +import { colors, themedMode, MODE_BRIGHT_SNOW_FLURRY, MODE_DARK_NIGHT_FROST } from "styles/theme"; + +const backgroundColorHover = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: rgba(colors.nord6, 0.45), + [MODE_DARK_NIGHT_FROST]: rgba(colors.nord3, 0.8) +}); + +const fontColor = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.nord10, + [MODE_DARK_NIGHT_FROST]: colors.nord8 +}); + +const fontColorDecent = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.nord0, + [MODE_DARK_NIGHT_FROST]: lighten(0.2, colors.font.base[MODE_DARK_NIGHT_FROST]) +}); + +const fontColorHover = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.nord10 +}); + +const fontColorHoverMinimal = themedMode({ + [MODE_BRIGHT_SNOW_FLURRY]: colors.nord0, + [MODE_DARK_NIGHT_FROST]: lighten(0.2, colors.font.base[MODE_DARK_NIGHT_FROST]) +}); + +const calmly = css` + border-radius: 0.25em; + color: ${fontColor}; + transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out; + + &:hover, + &:active, + &:focus { + background-color: ${backgroundColorHover}; + color: ${fontColorHover}; + } +`; + +const decent = css` + border-bottom: 1px solid ${fontColor}; + color: ${fontColorDecent}; + transition: color 0.2s ease-in-out; + + &:hover, + &:active, + &:focus { + color: ${fontColor}; + } +`; + +const minimal = css` + border-bottom: 1px solid ${fontColor}; + transition: border-bottom-color 0.2s ease-in-out; + + &:hover, + &:active, + &:focus { + border-bottom-color: ${fontColorHoverMinimal}; + } +`; + +export { calmly, decent, minimal }; From 7cf4e0434edf6c1c26e9f252730ea8b54ae00e3c Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Mon, 24 Dec 2018 09:52:36 +0100 Subject: [PATCH 02/15] Implement core atom component `Link` Implemented the core atom `Link` that wraps the base HTML element atom component the `A` (1) and adds matching brand styles to it. References: (1) https://github.com/arcticicestudio/nord-docs/issues/70 Associated epic: GH-63 GH-105 --- src/components/atoms/core/Link/Link.jsx | 42 +++++ src/components/atoms/core/Link/index.js | 10 ++ .../inlineTextSemantics/A.test.jsx | 4 + test/components/atoms/core/Link/Link.test.jsx | 35 +++++ .../Link/__snapshots__/Link.test.jsx.snap | 146 ++++++++++++++++++ 5 files changed, 237 insertions(+) create mode 100644 src/components/atoms/core/Link/Link.jsx create mode 100644 src/components/atoms/core/Link/index.js create mode 100644 test/components/atoms/core/Link/Link.test.jsx create mode 100644 test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap diff --git a/src/components/atoms/core/Link/Link.jsx b/src/components/atoms/core/Link/Link.jsx new file mode 100644 index 00000000..93e96d21 --- /dev/null +++ b/src/components/atoms/core/Link/Link.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 PropTypes from "prop-types"; +import styled from "styled-components"; + +import { A } from "atoms/core/HTMLElements"; + +import { calmly, decent, minimal } from "./styles"; + +const variants = { + calmly, + decent, + minimal +}; + +/** + * A wrapper for the base HTML component `A` with multiple styles that can be selected through the `variant` prop. + * + * @author Arctic Ice Studio + * @author Sven Greb + * @since 0.5.0 + */ +const Link = styled(A)` + ${({ variant }) => variants[variant]}; +`; + +Link.propTypes = { + variant: PropTypes.oneOf(Object.keys(variants)) +}; + +Link.defaultProps = { + variant: "calmly" +}; + +export default Link; diff --git a/src/components/atoms/core/Link/index.js b/src/components/atoms/core/Link/index.js new file mode 100644 index 00000000..19903a1b --- /dev/null +++ b/src/components/atoms/core/Link/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 "./Link"; diff --git a/test/components/atoms/core/HTMLElements/inlineTextSemantics/A.test.jsx b/test/components/atoms/core/HTMLElements/inlineTextSemantics/A.test.jsx index 3a62cd4e..ed474c6e 100644 --- a/test/components/atoms/core/HTMLElements/inlineTextSemantics/A.test.jsx +++ b/test/components/atoms/core/HTMLElements/inlineTextSemantics/A.test.jsx @@ -17,21 +17,25 @@ import { metadataNordDocs } from "data/project"; describe("logical behavior", () => { test("renders inernal URLs with `to` prop", () => { const { container } = render(Docs); + expect(container.firstChild).toHaveAttribute("href", ROUTE_DOCS); expect(container.firstChild).toMatchSnapshot(); }); test("renders inernal URLs with `href` prop", () => { const { container } = render(Docs); + expect(container.firstChild).toHaveAttribute("href", ROUTE_DOCS); expect(container.firstChild).toMatchSnapshot(); }); test("renders external URLs with `href` prop", () => { const { container } = render(Docs); + expect(container.firstChild).toHaveAttribute("href", metadataNordDocs.homepage); expect(container.firstChild).toMatchSnapshot(); }); test("renders external URLs with `to` prop", () => { const { container } = render(Docs); + expect(container.firstChild).toHaveAttribute("href", metadataNordDocs.homepage); expect(container.firstChild).toMatchSnapshot(); }); }); diff --git a/test/components/atoms/core/Link/Link.test.jsx b/test/components/atoms/core/Link/Link.test.jsx new file mode 100644 index 00000000..5627f02b --- /dev/null +++ b/test/components/atoms/core/Link/Link.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 { renderWithTheme } from "nord-docs-test-utils"; +import Link from "atoms/core/Link"; + +describe("theme styles", () => { + test("matches the snapshot with default variant", () => { + const { container } = renderWithTheme(Nord); + expect(container.firstChild).toMatchSnapshot(); + }); + + test("matches the snapshot with `calmly` variant", () => { + const { container } = renderWithTheme(Nord); + expect(container.firstChild).toMatchSnapshot(); + }); + + test("matches the snapshot with `decent` variant", () => { + const { container } = renderWithTheme(Nord); + expect(container.firstChild).toMatchSnapshot(); + }); + + test("matches the snapshot with `minimal` variant", () => { + const { container } = renderWithTheme(Nord); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap b/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap new file mode 100644 index 00000000..1bce632a --- /dev/null +++ b/test/components/atoms/core/Link/__snapshots__/Link.test.jsx.snap @@ -0,0 +1,146 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme styles matches the snapshot with \`calmly\` variant 1`] = ` +.c1 { + color: inherit; + cursor: pointer; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:active, +.c1:focus, +.c1:hover, +.c1:visited { + outline: none; +} + +.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; +} + +.c0:hover, +.c0:active, +.c0:focus { + background-color: rgba(236,239,244,0.45); + color: #5e81ac; +} + + + Nord + +`; + +exports[`theme styles matches the snapshot with \`decent\` variant 1`] = ` +.c1 { + color: inherit; + cursor: pointer; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:active, +.c1:focus, +.c1:hover, +.c1:visited { + outline: none; +} + +.c0 { + border-bottom: 1px solid #5e81ac; + color: #2e3440; + -webkit-transition: color 0.2s ease-in-out; + transition: color 0.2s ease-in-out; +} + +.c0:hover, +.c0:active, +.c0:focus { + color: #5e81ac; +} + + + Nord + +`; + +exports[`theme styles matches the snapshot with \`minimal\` variant 1`] = ` +.c1 { + color: inherit; + cursor: pointer; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:active, +.c1:focus, +.c1:hover, +.c1:visited { + outline: none; +} + +.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; +} + +.c0:hover, +.c0:active, +.c0:focus { + border-bottom-color: #2e3440; +} + + + Nord + +`; + +exports[`theme styles matches the snapshot with default variant 1`] = ` +.c1 { + color: inherit; + cursor: pointer; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:active, +.c1:focus, +.c1:hover, +.c1:visited { + outline: none; +} + +.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; +} + +.c0:hover, +.c0:active, +.c0:focus { + background-color: rgba(236,239,244,0.45); + color: #5e81ac; +} + + + Nord + +`; From a9610c5ee26b06b4ac1c0c659be17f12f8c1a7e8 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Tue, 25 Dec 2018 10:51:20 +0100 Subject: [PATCH 03/15] Install "semver" package It is required to implement the utility function to get Git version information during build time. References: https://semver.org https://www.npmjs.com/package/semver GH-106 --- package.json | 1 + 1 file changed, 1 insertion(+) 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", From f3dc035fe27c275e4ff251176d97910ba0e0b7a7 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Tue, 25 Dec 2018 10:59:01 +0100 Subject: [PATCH 04/15] Implement util function to get Git version (SemVer) information The function converts the output from the Git "describe --always" command (1) to a SemVer (2) compatible version. If the passed string ) not a valid SemVer version `null` will be returned instead of the object that contains detailed information about the passed string. References: (1) https://git-scm.com/docs/git-describe (2) https://semver.org GH-106 --- src/config/project/constants.js | 88 ++++++++++++ src/utils/getSemVerFromGitDescribe.js | 142 ++++++++++++++++++++ src/utils/index.js | 3 +- test/babel-config.js | 3 +- test/utils/getSemVerFromGitDescribe.test.js | 101 ++++++++++++++ 5 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 src/config/project/constants.js create mode 100644 src/utils/getSemVerFromGitDescribe.js create mode 100644 test/utils/getSemVerFromGitDescribe.test.js 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/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..9ed268e8 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"] }; module.exports = require("babel-jest").createTransformer(jestBabelConfig); diff --git a/test/utils/getSemVerFromGitDescribe.test.js b/test/utils/getSemVerFromGitDescribe.test.js new file mode 100644 index 00000000..339cb847 --- /dev/null +++ b/test/utils/getSemVerFromGitDescribe.test.js @@ -0,0 +1,101 @@ +/* + * 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"; + +/* , "v0.1.0", "v0.1.0-123", "v0.1.0-123-abcd1234", "v0.1.0-abcd1234" */ + +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}`); + }); +}); From 0f731204dd922f6a39b3c6ba0b1fbdb5fe562be1 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Tue, 25 Dec 2018 11:05:40 +0100 Subject: [PATCH 05/15] Remove skipped/disabled layout & page component unit tests These tests have been disabled because they'll be covered by E2E tests with Cypress later on. They were also skipped due to problems with mocking transitive modules and components. GH-106 --- .../core/BaseLayout/BaseLayout.test.jsx | 26 ------------------- .../__snapshots__/BaseLayout.test.jsx.snap | 9 ------- test/pages/__snapshots__/index.test.jsx.snap | 9 ------- test/pages/index.test.jsx | 22 ---------------- 4 files changed, 66 deletions(-) delete mode 100644 test/components/layouts/core/BaseLayout/BaseLayout.test.jsx delete mode 100644 test/components/layouts/core/BaseLayout/__snapshots__/BaseLayout.test.jsx.snap delete mode 100644 test/pages/__snapshots__/index.test.jsx.snap delete mode 100644 test/pages/index.test.jsx 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/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(); -}); From b9e326f0889674df9613564db2c8883060b02830 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Tue, 25 Dec 2018 11:08:46 +0100 Subject: [PATCH 06/15] Wrap project data social media links into `organization` object Wrapped the social media URLs of the project `links` data object into a `organization` object for a better logical distinction with the `community` object. GH-106 --- src/components/atoms/core/Link/styles.js | 9 +-- .../atoms/core/SiteMetadata/SiteMetadata.jsx | 12 ++-- src/data/project.js | 55 +++++++++++-------- .../Link/__snapshots__/Link.test.jsx.snap | 16 +++--- .../core/SiteMetadata/SiteMetadata.test.jsx | 8 ++- 5 files changed, 57 insertions(+), 43 deletions(-) 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..014e4296 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 }, @@ -110,9 +112,11 @@ const SiteMetadata = ({ pathName, ...passProp }) => ( description keywords links { - social { - twitter { - id + organization { + social { + twitter { + id + } } } } 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/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..6a97b444 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", From abf431802b0589a8b829215f1b53604cad830a7b Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Tue, 25 Dec 2018 11:12:55 +0100 Subject: [PATCH 07/15] Implement more brand & social media icon components This includes the official logo of Arctic Ice Studio, more UI icons as well as several social media & community sites and services: - Discord (1) - GitHub (2) - Keybase (3) - Reddit (4) - Slack (5) - Spectrum (6) - Twitter (7) References: (1) https://discordapp.com (2) https://github.com (3) https://keybase.io (4) https://reddit.com (5) https://slack.com (6) https://spectrum.chat (7) https://twitter.com https://akveo.github.io/eva-icons https://simpleicons.org Associated epic: GH-74 GH-106 --- .../images/icons/eva-icons/heart-fill.svg | 3 ++ .../images/icons/eva-icons/heart-outline.svg | 3 ++ .../images/icons/simple-icons/discord.svg | 3 ++ .../images/icons/simple-icons/github.svg | 3 ++ .../images/icons/simple-icons/keybase.svg | 5 ++ .../images/icons/simple-icons/reddit.svg | 3 ++ .../images/icons/simple-icons/slack.svg | 4 ++ .../icons/simple-icons/stackoverflow.svg | 3 ++ .../images/icons/simple-icons/twitter.svg | 3 ++ src/assets/images/icons/spectrum.svg | 3 ++ src/assets/images/logos/arcticicestudio.svg | 3 ++ .../atoms/core/vectors/icons/Discord.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/GitHub.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/Heart.jsx | 47 +++++++++++++++++++ .../atoms/core/vectors/icons/Keybase.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/Menu.jsx | 4 +- .../atoms/core/vectors/icons/Moon.jsx | 10 ++-- .../atoms/core/vectors/icons/Reddit.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/Slack.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/Spectrum.jsx | 36 ++++++++++++++ .../core/vectors/icons/StackOverflow.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/Sun.jsx | 9 +++- .../atoms/core/vectors/icons/Twitter.jsx | 36 ++++++++++++++ .../atoms/core/vectors/icons/index.js | 11 ++++- .../core/vectors/logos/ArcticIceStudio.jsx | 29 ++++++++++++ .../atoms/core/vectors/logos/index.js | 4 +- 26 files changed, 428 insertions(+), 10 deletions(-) create mode 100755 src/assets/images/icons/eva-icons/heart-fill.svg create mode 100755 src/assets/images/icons/eva-icons/heart-outline.svg create mode 100755 src/assets/images/icons/simple-icons/discord.svg create mode 100755 src/assets/images/icons/simple-icons/github.svg create mode 100755 src/assets/images/icons/simple-icons/keybase.svg create mode 100755 src/assets/images/icons/simple-icons/reddit.svg create mode 100755 src/assets/images/icons/simple-icons/slack.svg create mode 100755 src/assets/images/icons/simple-icons/stackoverflow.svg create mode 100755 src/assets/images/icons/simple-icons/twitter.svg create mode 100644 src/assets/images/icons/spectrum.svg create mode 100644 src/assets/images/logos/arcticicestudio.svg create mode 100644 src/components/atoms/core/vectors/icons/Discord.jsx create mode 100644 src/components/atoms/core/vectors/icons/GitHub.jsx create mode 100644 src/components/atoms/core/vectors/icons/Heart.jsx create mode 100644 src/components/atoms/core/vectors/icons/Keybase.jsx create mode 100644 src/components/atoms/core/vectors/icons/Reddit.jsx create mode 100644 src/components/atoms/core/vectors/icons/Slack.jsx create mode 100644 src/components/atoms/core/vectors/icons/Spectrum.jsx create mode 100644 src/components/atoms/core/vectors/icons/StackOverflow.jsx create mode 100644 src/components/atoms/core/vectors/icons/Twitter.jsx create mode 100644 src/components/atoms/core/vectors/logos/ArcticIceStudio.jsx 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/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 }; From aa1ab355ea516414e4fa92896eda377156adc0b2 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Wed, 26 Dec 2018 08:46:58 +0100 Subject: [PATCH 08/15] Remove `prefix` attribute from `` tag This is not necessary to support the Open Graph Protocol metadata and can lead to problems with other specifications. GH-106` --- .../atoms/core/SiteMetadata/SiteMetadata.jsx | 2 +- .../atoms/core/SiteMetadata/SiteMetadata.test.jsx | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx b/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx index 014e4296..f2eacd87 100644 --- a/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx +++ b/src/components/atoms/core/SiteMetadata/SiteMetadata.jsx @@ -40,7 +40,7 @@ const PureSiteMetadata = ({ }) => ( - + diff --git a/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx b/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx index 6a97b444..957e6afd 100644 --- a/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx +++ b/test/components/atoms/core/SiteMetadata/SiteMetadata.test.jsx @@ -132,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(); From 0b5516def118c2e15ee995cee3456177a913e1ce Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Wed, 26 Dec 2018 09:20:34 +0100 Subject: [PATCH 09/15] Implement `WaveFooter` SVG divider component A SVG vector graphic divider component consisting of three overlapping waves that is placed as last child within the last section/component of a page to render the wave as divider for the footer (rendered through the `Baselayout` component). GH-106 --- .../atoms/core/vectors/divider/DividerSvg.jsx | 43 ++++++++++++ .../atoms/core/vectors/divider/WaveFooter.jsx | 68 +++++++++++++++++++ .../atoms/core/vectors/divider/index.js | 21 ++++++ .../404/SectionLanding/SectionLanding.jsx | 2 + .../SectionBlogPosts/SectionBlogPosts.jsx | 2 + .../SectionLanding/SectionLanding.jsx | 2 + .../docs/SectionLanding/SectionLanding.jsx | 2 + .../page/landing/SectionHero/SectionHero.jsx | 2 + .../ports/SectionLanding/SectionLanding.jsx | 2 + 9 files changed, 144 insertions(+) create mode 100644 src/components/atoms/core/vectors/divider/DividerSvg.jsx create mode 100644 src/components/atoms/core/vectors/divider/WaveFooter.jsx create mode 100644 src/components/atoms/core/vectors/divider/index.js 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/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!" /> + ); From 33ad87684cb44bd5f64c331e0f0613345c62df12 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Thu, 27 Dec 2018 20:23:42 +0100 Subject: [PATCH 10/15] Implement mapping of categories for the sitemap It includes all links and category headings that'll be rendered as sitemap in the footer. GH-106 --- .../core/Footer/sitemapCategories.js | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/data/components/organisms/core/Footer/sitemapCategories.js 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; From 7012415b7b912eab1a6cd65c462c01385a03c2fc Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Fri, 28 Dec 2018 20:23:56 +0100 Subject: [PATCH 11/15] Implement styled footer components GH-106 --- .../containers/core/Section/Content.jsx | 4 +- .../organisms/core/Footer/styled/Category.jsx | 58 +++++++++++++++ .../core/Footer/styled/Copyright.jsx | 41 +++++++++++ .../organisms/core/Footer/styled/Grid.jsx | 35 +++++++++ .../organisms/core/Footer/styled/Metadata.jsx | 32 ++++++++ .../core/Footer/styled/OrganizationBrand.jsx | 25 +++++++ .../styled/OrganizationBrandCaption.jsx | 27 +++++++ .../organisms/core/Footer/styled/Sitemap.jsx | 33 +++++++++ .../core/Footer/styled/SitemapCategory.jsx | 44 +++++++++++ .../core/Footer/styled/SitemapLink.jsx | 54 ++++++++++++++ .../core/Footer/styled/SitemapList.jsx | 27 +++++++ .../core/Footer/styled/SocialNetworking.jsx | 40 ++++++++++ .../organisms/core/Footer/styled/index.js | 34 +++++++++ .../organisms/core/Footer/styles.js | 60 +++++++++++++++ src/styles/theme/colors/font.js | 9 ++- test/babel-config.js | 2 +- .../containers/core/Section/Content.test.jsx | 20 ++--- .../__snapshots__/Content.test.jsx.snap | 8 +- .../core/Footer/styled/Category.test.jsx | 29 ++++++++ .../core/Footer/styled/Copyright.test.jsx | 42 +++++++++++ .../core/Footer/styled/Grid.test.jsx | 51 +++++++++++++ .../core/Footer/styled/Metadata.test.jsx | 47 ++++++++++++ .../Footer/styled/OrganizationBrand.test.jsx | 35 +++++++++ .../core/Footer/styled/Sitemap.test.jsx | 38 ++++++++++ .../Footer/styled/SitemapCategory.test.jsx | 73 +++++++++++++++++++ .../core/Footer/styled/SitemapLink.test.jsx | 49 +++++++++++++ .../core/Footer/styled/SitemapList.test.jsx | 38 ++++++++++ .../Footer/styled/SocialNetworking.test.jsx | 49 +++++++++++++ .../__snapshots__/Category.test.jsx.snap | 39 ++++++++++ .../__snapshots__/Copyright.test.jsx.snap | 30 ++++++++ .../styled/__snapshots__/Grid.test.jsx.snap | 32 ++++++++ .../__snapshots__/Metadata.test.jsx.snap | 36 +++++++++ .../OrganizationBrand.test.jsx.snap | 19 +++++ .../__snapshots__/Sitemap.test.jsx.snap | 34 +++++++++ .../SitemapCategory.test.jsx.snap | 42 +++++++++++ .../__snapshots__/SitemapLink.test.jsx.snap | 47 ++++++++++++ .../__snapshots__/SitemapList.test.jsx.snap | 17 +++++ .../SocialNetworking.test.jsx.snap | 39 ++++++++++ test/utils/getSemVerFromGitDescribe.test.js | 2 - 39 files changed, 1321 insertions(+), 20 deletions(-) create mode 100644 src/components/organisms/core/Footer/styled/Category.jsx create mode 100644 src/components/organisms/core/Footer/styled/Copyright.jsx create mode 100644 src/components/organisms/core/Footer/styled/Grid.jsx create mode 100644 src/components/organisms/core/Footer/styled/Metadata.jsx create mode 100644 src/components/organisms/core/Footer/styled/OrganizationBrand.jsx create mode 100644 src/components/organisms/core/Footer/styled/OrganizationBrandCaption.jsx create mode 100644 src/components/organisms/core/Footer/styled/Sitemap.jsx create mode 100644 src/components/organisms/core/Footer/styled/SitemapCategory.jsx create mode 100644 src/components/organisms/core/Footer/styled/SitemapLink.jsx create mode 100644 src/components/organisms/core/Footer/styled/SitemapList.jsx create mode 100644 src/components/organisms/core/Footer/styled/SocialNetworking.jsx create mode 100644 src/components/organisms/core/Footer/styled/index.js create mode 100644 src/components/organisms/core/Footer/styles.js create mode 100644 test/components/organisms/core/Footer/styled/Category.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/Copyright.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/Grid.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/Metadata.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/OrganizationBrand.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/Sitemap.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/SitemapCategory.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/SitemapLink.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/SitemapList.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/SocialNetworking.test.jsx create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/Category.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/Copyright.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/Grid.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/Metadata.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/OrganizationBrand.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/Sitemap.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/SitemapCategory.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/SitemapLink.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/SitemapList.test.jsx.snap create mode 100644 test/components/organisms/core/Footer/styled/__snapshots__/SocialNetworking.test.jsx.snap 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/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/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/test/babel-config.js b/test/babel-config.js index 9ed268e8..e91bb2b6 100644 --- a/test/babel-config.js +++ b/test/babel-config.js @@ -18,7 +18,7 @@ const jestBabelConfig = { presets: ["babel-preset-gatsby"], - plugins: ["@babel/plugin-proposal-optional-chaining"] + plugins: ["@babel/plugin-proposal-optional-chaining", "@babel/plugin-proposal-export-default-from"] }; module.exports = require("babel-jest").createTransformer(jestBabelConfig); 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/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/utils/getSemVerFromGitDescribe.test.js b/test/utils/getSemVerFromGitDescribe.test.js index 339cb847..4e944c4f 100644 --- a/test/utils/getSemVerFromGitDescribe.test.js +++ b/test/utils/getSemVerFromGitDescribe.test.js @@ -9,8 +9,6 @@ import { getSemVerFromGitDescribe } from "utils"; -/* , "v0.1.0", "v0.1.0-123", "v0.1.0-123-abcd1234", "v0.1.0-abcd1234" */ - const CHANNEL_PRERELEASE = "pre-release"; const CHANNEL_RELEASE = "release"; const CHANNEL_SNAPSHOT = "snapshot"; From 7a4c3568c019f51804833c6c025b0b86ded7f496 Mon Sep 17 00:00:00 2001 From: Arctic Ice Studio Date: Fri, 28 Dec 2018 20:34:00 +0100 Subject: [PATCH 12/15] Implement `Footer` core organism component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It represents the HTML `