diff --git a/.jest/jest.setup.js b/.jest/jest.setup.js index 4ecf19ad..98748bfe 100644 --- a/.jest/jest.setup.js +++ b/.jest/jest.setup.js @@ -1,10 +1,9 @@ -import Enzyme, { shallow, render, mount } from "enzyme" +import Enzyme, { shallow, mount } from "enzyme" import Adapter from "enzyme-adapter-react-16" Enzyme.configure({ adapter: new Adapter() }) global.shallow = shallow -global.render = render global.mount = mount // Create a simple component instance with jest.mock() @@ -13,37 +12,3 @@ global.simpleMock = mockName => { // eslint-disable-next-line return eval(`const ${mockName} = props => props.children || null; ${mockName}`) } - -/** - * Create and fire a keyboard event. - * @param {Number} which - The key code to simulate. - * @param {Boolean} shiftKey - Whether shift key should be used. - * @param {Element} node - The element to fire the event on. - */ -global.simulateKeyPress = (which, shiftKey = false, node = null) => { - const event = new KeyboardEvent("keydown", { - which, - shiftKey, - keyCode: which, - bubbles: true, - }) - - return node ? node.dispatchEvent(event) : document.dispatchEvent(event) -} - -/** - * Create and fire a keyboard event. - * @param {String} name - Event name. - * @param {Object} node - The node to dispatch the event against. - * @param {Boolean} bubbles - Flag for allowing bubbling of the event. - * @param {Boolean} cancelale - Flag for allowing cancelling of the event. - */ -global.simulateMouseEvent = (name, node = null, bubbles = false, cancelable = false) => { - const event = new MouseEvent(name, { - bubbles: bubbles || true, - cancelable: cancelable || true, - relatedTarget: window, - }) - - return node ? node.dispatchEvent(event) : document.dispatchEvent(event) -} diff --git a/.prettierignore b/.prettierignore index 2ad22ac4..d0f77c28 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,5 @@ -**/*.html -**/*.md +/node_modules/ +/build/ +/dist/ +/lib/ +/app/docs/ diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 00000000..352354e4 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,4 @@ +dist/ +app/docs/* +src/scss/utilities/_reset.scss +src/__tests__/ diff --git a/stylelint.config.js b/.stylelintrc.js similarity index 92% rename from stylelint.config.js rename to .stylelintrc.js index dcb001c4..bcb9e086 100644 --- a/stylelint.config.js +++ b/.stylelintrc.js @@ -55,8 +55,6 @@ module.exports = { "length-zero-no-unit": true, - linebreaks: "unix", - "max-nesting-depth": [3, { ignore: ["pseudo-classes", "blockless-at-rules"] }], "media-feature-colon-space-after": ALWAYS, @@ -71,16 +69,11 @@ module.exports = { "no-duplicate-at-import-rules": true, "no-duplicate-selectors": true, "no-empty-source": true, - "no-empty-first-line": true, "no-invalid-double-slash-comments": true, "no-unknown-animations": true, "property-no-unknown": true, - // This will be flagged by the script `scss:lint:check` - // Please ignore the error :) - "rule-empty-line-before": [ALWAYS, { except: ["first-nested"], ignore: ["after-comment"] }], - "selector-attribute-brackets-space-inside": NEVER, "selector-attribute-operator-blacklist": [], "selector-attribute-operator-space-after": NEVER, @@ -119,7 +112,6 @@ module.exports = { "scss/at-mixin-argumentless-call-parentheses": NEVER, "scss/at-mixin-parentheses-space-before": NEVER, "scss/at-each-key-value-single-line": true, - "scss/at-rule-conditional-no-parentheses": true, "scss/at-rule-no-unknown": true, "scss/declaration-nested-properties": NEVER, @@ -137,8 +129,6 @@ module.exports = { "scss/map-keys-quotes": ALWAYS, - "scss/operator-no-newline-after": true, - "scss/operator-no-newline-before": true, "scss/operator-no-unspaced": true, "scss/selector-no-redundant-nesting-selector": true, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eda693b0..43cd9842 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,11 +2,11 @@ All input is good input! Contributing to this project should be as easy and transparent as possible, whether it's: -* Reporting a bug -* Discussing the current state of the code -* Submitting a fix -* Proposing new features -* Becoming a maintainer +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing new features +- Becoming a maintainer ## We Develop with Github @@ -18,11 +18,11 @@ All code changes happen through pull requests Pull requests are the best way to propose changes to the codebase. Any kind of idea or change is welcome. -1. Fork the repo and create your branch from `develop`. -2. If you've added code that should be tested, add tests. -3. If you've changed APIs, update the documentation. -4. If you've added dependencies, note what they are and why they are needed. -5. Make sure your code and tests run without errors. It's also helpful if you've done a regression check against other areas of the framework, but not strictly required. +1. Fork the repo and create your branch from `develop`. +2. If you've added code that should be tested, add tests. +3. If you've changed APIs, update the documentation. +4. If you've added dependencies, note what they are and why they are needed. +5. Make sure your code and tests run without errors. It's also helpful if you've done a regression check against other areas of the framework, but not strictly required. ## Any contributions you make will be under the MIT Software License @@ -40,11 +40,9 @@ The more detail, the less confusion! ## Use a Consistent Coding Style -Reference `.prettierrc` for code styling. Run `npm run lint` to apply styling to both css and javascript, or manually apply updates to files using `prettier`: +If you're using a code editor, make sure it has plugins for prettier, eslint, and stylelint. -```sh -$ prettier --write path/to/folder/**/* -``` +If you don't have plugins for your editor, run `npm run prettify && npm run lint` to apply styling to both css and javascript before you commit changes. ## References diff --git a/README.md b/README.md index 2127fe01..64508938 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Undernet](app/assets/images/github-logo.png?raw=true) -[![CircleCI](https://circleci.com/gh/geotrev/undernet/tree/master.svg?style=svg)](https://circleci.com/gh/geotrev/undernet/tree/master) [![devDependencies Status](https://david-dm.org/geotrev/undernet/dev-status.svg)](https://david-dm.org/geotrev/undernet?type=dev) [![dependencies Status](https://david-dm.org/geotrev/undernet.svg)](https://david-dm.org/geotrev/undernet) [![npm version](https://badge.fury.io/js/undernet.svg)](https://badge.fury.io/js/undernet) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) +[![CircleCI](https://circleci.com/gh/geotrev/undernet/tree/master.svg?style=svg)](https://circleci.com/gh/geotrev/undernet/tree/master) [![devDependencies Status](https://david-dm.org/geotrev/undernet/dev-status.svg)](https://david-dm.org/geotrev/undernet?type=dev) [![dependencies Status](https://david-dm.org/geotrev/undernet.svg)](https://david-dm.org/geotrev/undernet) [![npm version](https://badge.fury.io/js/undernet.svg)](https://badge.fury.io/js/undernet) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) [![Netlify Status](https://api.netlify.com/api/v1/badges/b895bcd0-9455-4818-a94b-8d33e5907517/deploy-status)](https://app.netlify.com/sites/undernet-prod/deploys) # Undernet @@ -27,7 +27,7 @@ $ yarn add -D undernet ### Styles -See [branding documentation](https://www.undernet.io/docs/overview/branding) to setup a custom pipeline with Undernet's SCSS. +See [CSS documentation](https://www.undernet.io/docs/overview/css) to setup a custom pipeline with Undernet's SCSS. ### Components / JS diff --git a/app/components/Article/Article.js b/app/components/Article/Article.js index d5f1273c..ec8dd667 100644 --- a/app/components/Article/Article.js +++ b/app/components/Article/Article.js @@ -1,33 +1,30 @@ -import React, { useState, useEffect } from "react" +import React, { useState } from "react" import Markdown from "react-markdown" import Prism from "prismjs" import classNames from "classnames" import PropTypes from "prop-types" +import Undernet from "undernet" -import { COMPONENTS } from "./constants" import ScrollUpOnMount from "app/components/ScrollUpOnMount" +import { useDidMount, useWillUnmount } from "app/helpers" + +const SCOPE = "#article" export default function Article(props) { const [domIsLoaded, setDomIsLoaded] = useState(false) - const componentUnmountFunction = () => { - COMPONENTS.forEach(Component => Component.stop()) - } + useWillUnmount(() => Undernet.stop(SCOPE)) - const observedStateOnMount = [] - useEffect(() => { + useDidMount(() => { Prism.highlightAll() - COMPONENTS.forEach(Component => Component.start()) + Undernet.start(SCOPE) setDomIsLoaded(true) - - return componentUnmountFunction - }, observedStateOnMount) + }) return (
diff --git a/app/components/Article/__tests__/Article.spec.js b/app/components/Article/__tests__/Article.spec.js index 50ed17f6..2870f14e 100644 --- a/app/components/Article/__tests__/Article.spec.js +++ b/app/components/Article/__tests__/Article.spec.js @@ -1,16 +1,14 @@ import React from "react" -import Article from "../Article" import Prism from "prismjs" -import { COMPONENTS } from "../constants" +import Undernet from "undernet" +import Article from "../Article" jest.mock("app/components/ScrollUpOnMount", () => global.simpleMock("ScrollUpOnMount")) global.scrollTo = jest.fn() -COMPONENTS.forEach(Component => { - Component.start = jest.fn() - Component.stop = jest.fn() -}) +Undernet.start = jest.fn() +Undernet.stop = jest.fn() jest.mock("prismjs", () => ({ highlightAll: jest.fn(), @@ -47,29 +45,25 @@ describe("
", () => { // Given mountComponent() // Then - expect(Prism.highlightAll).toHaveBeenCalled() + expect(Prism.highlightAll).toBeCalled() }) - COMPONENTS.forEach(Component => { - it(`calls ${Component}.start`, () => { - // Given - mountComponent() - // Then - expect(Component.start).toHaveBeenCalled() - }) + it("calls Undernet.start", () => { + // Given + mountComponent() + // Then + expect(Undernet.start).toBeCalled() }) }) describe("#componentWillUnmount", () => { - COMPONENTS.forEach(Component => { - it(`calls ${Component}.stop`, () => { - // Given - const wrapper = mountComponent() - // When - wrapper.unmount() - // Then - expect(Component.stop).toHaveBeenCalled() - }) + it("calls Undernet.stop", () => { + // Given + const wrapper = mountComponent() + // When + wrapper.unmount() + // Then + expect(Undernet.stop).toBeCalled() }) }) }) diff --git a/app/components/Article/__tests__/__snapshots__/Article.spec.js.snap b/app/components/Article/__tests__/__snapshots__/Article.spec.js.snap index 471eadfc..a1a962db 100644 --- a/app/components/Article/__tests__/__snapshots__/Article.spec.js.snap +++ b/app/components/Article/__tests__/__snapshots__/Article.spec.js.snap @@ -3,7 +3,8 @@ exports[`
#render renders 1`] = `
#render renders 1`] = ` transformLinkUri={[Function]} >

Test header @@ -37,11 +38,11 @@ exports[`
#render renders 1`] = `

So neat diff --git a/app/components/Article/constants.js b/app/components/Article/constants.js deleted file mode 100644 index 305c1959..00000000 --- a/app/components/Article/constants.js +++ /dev/null @@ -1,3 +0,0 @@ -import { Tooltips, Accordions, Modals, Dropdowns } from "undernet" - -export const COMPONENTS = [Tooltips, Accordions, Modals, Dropdowns] diff --git a/app/components/DocsRoutes/DocsRoutes.js b/app/components/DocsRoutes/DocsRoutes.js index 89f92a67..af8b5a6d 100644 --- a/app/components/DocsRoutes/DocsRoutes.js +++ b/app/components/DocsRoutes/DocsRoutes.js @@ -2,7 +2,7 @@ import React from "react" import { Switch, Route } from "react-router-dom" import Loadable from "react-loadable" -import * as routes from "app/routes" +import { docPages } from "app/routes" import PageNotFound from "app/components/PageNotFound" import LoadingSpinner from "app/components/LoadingSpinner" @@ -18,24 +18,11 @@ const getComponent = component => export default function DocsRoutes() { return ( - - - - - - - - - - - - - - - - - - + {Object.entries(docPages).map(([name, path]) => { + const componentName = name[0].toUpperCase() + name.slice(1) + + return + })} ) diff --git a/app/components/DocsRoutes/articles/Accordions.js b/app/components/DocsRoutes/articles/Accordions.js index 908d6bfa..4bbeb7f8 100644 --- a/app/components/DocsRoutes/articles/Accordions.js +++ b/app/components/DocsRoutes/articles/Accordions.js @@ -6,14 +6,14 @@ import AccordionsMd from "app/docs/accordions.md" const Accordions = () => { return ( - + <> Accordions

{AccordionsMd}
- + ) } diff --git a/app/components/DocsRoutes/articles/Alignment.js b/app/components/DocsRoutes/articles/Alignment.js index 05c59bc3..8e5de8a0 100644 --- a/app/components/DocsRoutes/articles/Alignment.js +++ b/app/components/DocsRoutes/articles/Alignment.js @@ -6,14 +6,14 @@ import AlignmentMd from "app/docs/alignment.md" const Alignment = () => { return ( - + <> Alignment
{AlignmentMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Buttons.js b/app/components/DocsRoutes/articles/Buttons.js index 66793135..656c895b 100644 --- a/app/components/DocsRoutes/articles/Buttons.js +++ b/app/components/DocsRoutes/articles/Buttons.js @@ -6,14 +6,14 @@ import ButtonsMd from "app/docs/buttons.md" const Buttons = () => { return ( - + <> Buttons
{ButtonsMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Collapsibles.js b/app/components/DocsRoutes/articles/Collapsibles.js new file mode 100644 index 00000000..587e64dd --- /dev/null +++ b/app/components/DocsRoutes/articles/Collapsibles.js @@ -0,0 +1,20 @@ +import React from "react" +import Article from "app/components/Article" +import PageHeader from "app/components/PageHeader" +import SetMeta from "app/components/SetMeta" +import CollapsiblesMd from "app/docs/collapsibles.md" + +const Collapsibles = () => { + return ( + <> + + Collapsibles +
{CollapsiblesMd}
+ + ) +} + +export default Collapsibles diff --git a/app/components/DocsRoutes/articles/Color.js b/app/components/DocsRoutes/articles/Color.js index 697d3325..076f5ac8 100644 --- a/app/components/DocsRoutes/articles/Color.js +++ b/app/components/DocsRoutes/articles/Color.js @@ -6,14 +6,14 @@ import ColorMd from "app/docs/color.md" const Color = () => { return ( - + <> Color
{ColorMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Branding.js b/app/components/DocsRoutes/articles/Css.js similarity index 69% rename from app/components/DocsRoutes/articles/Branding.js rename to app/components/DocsRoutes/articles/Css.js index b124d3c6..8a90fb20 100644 --- a/app/components/DocsRoutes/articles/Branding.js +++ b/app/components/DocsRoutes/articles/Css.js @@ -2,18 +2,18 @@ import React from "react" import Article from "app/components/Article" import PageHeader from "app/components/PageHeader" import SetMeta from "app/components/SetMeta" -import BrandingMd from "app/docs/branding.md" +import CssMd from "app/docs/css.md" const Branding = () => { return ( - + <> - Branding -
{BrandingMd}
-
+ CSS +
{CssMd}
+ ) } diff --git a/app/components/DocsRoutes/articles/Display.js b/app/components/DocsRoutes/articles/Display.js index 042e8bce..a834eb64 100644 --- a/app/components/DocsRoutes/articles/Display.js +++ b/app/components/DocsRoutes/articles/Display.js @@ -6,14 +6,14 @@ import DisplayMd from "app/docs/display.md" const Display = () => { return ( - + <> Display
{DisplayMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Download.js b/app/components/DocsRoutes/articles/Download.js index b35ad22c..3abd0a49 100644 --- a/app/components/DocsRoutes/articles/Download.js +++ b/app/components/DocsRoutes/articles/Download.js @@ -6,14 +6,14 @@ import DownloadMd from "app/docs/download.md" const Download = () => { return ( - + <> Download
{DownloadMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Dropdowns.js b/app/components/DocsRoutes/articles/Dropdowns.js index c191ac55..36f740d9 100644 --- a/app/components/DocsRoutes/articles/Dropdowns.js +++ b/app/components/DocsRoutes/articles/Dropdowns.js @@ -6,14 +6,14 @@ import DropdownsMd from "app/docs/dropdowns.md" const Dropdowns = () => { return ( - + <> Dropdowns
{DropdownsMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Forms.js b/app/components/DocsRoutes/articles/Forms.js index ec44d4e5..47287ef2 100644 --- a/app/components/DocsRoutes/articles/Forms.js +++ b/app/components/DocsRoutes/articles/Forms.js @@ -6,14 +6,14 @@ import FormsMd from "app/docs/forms.md" const Forms = () => { return ( - + <> Forms
{FormsMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Grid.js b/app/components/DocsRoutes/articles/Grid.js index 55f5013f..267180a1 100644 --- a/app/components/DocsRoutes/articles/Grid.js +++ b/app/components/DocsRoutes/articles/Grid.js @@ -6,14 +6,14 @@ import GridMd from "app/docs/grid.md" const Grid = () => { return ( - + <> Grid
{GridMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Introduction.js b/app/components/DocsRoutes/articles/Introduction.js index 08af1fdd..e677b0fc 100644 --- a/app/components/DocsRoutes/articles/Introduction.js +++ b/app/components/DocsRoutes/articles/Introduction.js @@ -6,14 +6,14 @@ import IntroductionMd from "app/docs/introduction.md" const Introduction = () => { return ( - + <> Introduction
{IntroductionMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Javascript.js b/app/components/DocsRoutes/articles/Javascript.js index 9a2b5d45..86ba758d 100644 --- a/app/components/DocsRoutes/articles/Javascript.js +++ b/app/components/DocsRoutes/articles/Javascript.js @@ -6,14 +6,14 @@ import JavaScriptMd from "app/docs/javascript.md" const JavaScript = () => { return ( - + <> JavaScript
{JavaScriptMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Modals.js b/app/components/DocsRoutes/articles/Modals.js index bfd32cc2..a0a537f7 100644 --- a/app/components/DocsRoutes/articles/Modals.js +++ b/app/components/DocsRoutes/articles/Modals.js @@ -6,14 +6,14 @@ import ModalsMd from "app/docs/modals.md" const Modals = () => { return ( - + <> Modals
{ModalsMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/OffsetOrder.js b/app/components/DocsRoutes/articles/OffsetOrder.js index c4bfdc11..434f3679 100644 --- a/app/components/DocsRoutes/articles/OffsetOrder.js +++ b/app/components/DocsRoutes/articles/OffsetOrder.js @@ -6,14 +6,14 @@ import OffsetOrderMd from "app/docs/offset-order.md" const OffsetOrder = () => { return ( - + <> Offset & Order
{OffsetOrderMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Spacing.js b/app/components/DocsRoutes/articles/Spacing.js index 4c3ccf2e..cef39681 100644 --- a/app/components/DocsRoutes/articles/Spacing.js +++ b/app/components/DocsRoutes/articles/Spacing.js @@ -6,14 +6,14 @@ import SpacingMd from "app/docs/spacing.md" const Spacing = () => { return ( - + <> Spacing
{SpacingMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Text.js b/app/components/DocsRoutes/articles/Text.js index 305c5847..bd3cc7ad 100644 --- a/app/components/DocsRoutes/articles/Text.js +++ b/app/components/DocsRoutes/articles/Text.js @@ -6,14 +6,14 @@ import TextMd from "app/docs/text.md" const Text = () => { return ( - + <> Text
{TextMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Tooltips.js b/app/components/DocsRoutes/articles/Tooltips.js index d8f34746..8b0533eb 100644 --- a/app/components/DocsRoutes/articles/Tooltips.js +++ b/app/components/DocsRoutes/articles/Tooltips.js @@ -6,14 +6,14 @@ import TooltipsMd from "app/docs/tooltips.md" const Tooltips = () => { return ( - + <> Tooltips
{TooltipsMd}
-
+ ) } diff --git a/app/components/DocsRoutes/articles/Typography.js b/app/components/DocsRoutes/articles/Typography.js index bae2ee95..edd0cb77 100644 --- a/app/components/DocsRoutes/articles/Typography.js +++ b/app/components/DocsRoutes/articles/Typography.js @@ -6,14 +6,14 @@ import TypographyMd from "app/docs/typography.md" const Typography = () => { return ( - + <> Typography
{TypographyMd}
-
+ ) } diff --git a/app/components/Footer/Footer.js b/app/components/Footer/Footer.js index f3e6ffaa..c1125ff1 100644 --- a/app/components/Footer/Footer.js +++ b/app/components/Footer/Footer.js @@ -1,6 +1,5 @@ import React from "react" -import Github from "react-feather/dist/icons/github" -import Twitter from "react-feather/dist/icons/twitter" +import { GitHub, Twitter } from "react-feather" import PropTypes from "prop-types" import "./styles.scss" @@ -12,54 +11,54 @@ export default function Footer(props) { } return ( -
+
-
-

- Undernet is a front-end framework created and maintained by{" "} - - George Treviranus +

+

+ {"Undernet is a front-end framework created and maintained by "} + + {"George Treviranus"} - . + {"."}

-

- Animations provided by{" "} - - Gavin Folgert +

+ {"Animations provided by "} + + {"Gavin Folgert"} - . ❤️ + {". ❤️"}

-
    -
  • + diff --git a/app/components/Footer/__tests__/Footer.spec.js b/app/components/Footer/__tests__/Footer.spec.js index 808088c6..34c9af7f 100644 --- a/app/components/Footer/__tests__/Footer.spec.js +++ b/app/components/Footer/__tests__/Footer.spec.js @@ -1,8 +1,10 @@ import React from "react" import Footer from "../Footer" -jest.mock("react-feather/dist/icons/twitter", () => global.simpleMock("Twitter")) -jest.mock("react-feather/dist/icons/github", () => global.simpleMock("Github")) +jest.mock("react-feather", () => ({ + GitHub: global.simpleMock("Github"), + Twitter: global.simpleMock("Twitter"), +})) describe("