diff --git a/catalog/pages/nav_bar/index.js b/catalog/pages/nav_bar/index.js
index 203bd2b7b..e392cb3b9 100644
--- a/catalog/pages/nav_bar/index.js
+++ b/catalog/pages/nav_bar/index.js
@@ -9,6 +9,7 @@ import Column from "../../../src/components/Grid/Column";
import Row from "../../../src/components/Grid/Row";
import DeviceSizeProvider from "../../../src/components/DeviceSize/Provider";
import DisplayFor from "../../../src/components/DeviceSize";
+import DrawerProvider from "../../../src/components/Drawer/Provider";
export default {
path: "/nav_bar",
@@ -22,7 +23,8 @@ export default {
Column,
Row,
DeviceSizeProvider,
- DisplayFor
+ DisplayFor,
+ DrawerProvider
},
content: pageLoader(() => import("./index.md"))
};
diff --git a/catalog/pages/nav_bar/index.md b/catalog/pages/nav_bar/index.md
index 2a4bc7b2f..c2adfb776 100644
--- a/catalog/pages/nav_bar/index.md
+++ b/catalog/pages/nav_bar/index.md
@@ -1,49 +1,53 @@
### Default
```react
-responsive: true
+responsive: false
span: 6
state: { invert: false }
---
-
-
-
-
-
-
-
- Aurora
-
-
-
- Link 1
- Link 2
- Link 3
-
- More
-
- Link 4
- Link 5
- Link 6
- Link 7 With Really Long Content
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ Aurora
+
+
+
+ Link 1
+ Link 2
+ Link 3
+
+ More
+
+ Link 4
+ Link 5
+ Link 6
+ Link 7 With Really Long Content
+
+
+
+
+
+
+
+
+
+ Some Menu Content
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
```
diff --git a/src/components/Drawer/Context.js b/src/components/Drawer/Context.js
new file mode 100644
index 000000000..a64419c27
--- /dev/null
+++ b/src/components/Drawer/Context.js
@@ -0,0 +1,3 @@
+import React from "react";
+
+export const { Provider, Consumer } = React.createContext({ isOpen: false });
diff --git a/src/components/Drawer/Drawer.styles.js b/src/components/Drawer/Drawer.styles.js
new file mode 100644
index 000000000..bfd31c007
--- /dev/null
+++ b/src/components/Drawer/Drawer.styles.js
@@ -0,0 +1,67 @@
+import styled from "styled-components";
+
+import constants from "../../theme/constants";
+import spacing from "../../theme/spacing";
+import getThemeValue from "../../utils/getThemeValue";
+
+export const DrawerContainer = styled.div`
+ background-color: ${getThemeValue("onyx", "base")};
+ color: ${getThemeValue("white", "base")};
+ height: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ visibility: hidden;
+ transform: translateY(-100%);
+ opacity: 0;
+ transition: opacity 0.3ms ${constants.easing.easeInOutQuad};
+ overflow: hidden;
+ z-index: -1;
+
+ &.drawer__content--open {
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+ }
+`;
+
+export const DrawerContent = styled.div`
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ overflow-x: hidden;
+`;
+
+export const HeaderContent = styled.div`
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ align-items: center;
+ height: 60px;
+ padding-left: ${spacing.moderate};
+`;
+
+export const CloseButton = styled.button`
+ appearance: none;
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ display: flex;
+ align-items: center;
+ height: 60px;
+ padding: 0 ${spacing.moderate};
+`;
+
+export const ContentWrapper = styled.div`
+ &.drawer--open {
+ overflow: hidden;
+ }
+`;
diff --git a/src/components/Drawer/Provider.js b/src/components/Drawer/Provider.js
new file mode 100644
index 000000000..daac826be
--- /dev/null
+++ b/src/components/Drawer/Provider.js
@@ -0,0 +1,77 @@
+/* global window: true */
+/* eslint react/sort-comp: off, react/no-unused-state: off */
+import React, { Children } from "react";
+import PropTypes from "prop-types";
+import classNames from "classnames";
+
+import { Provider } from "./Context";
+import { ContentWrapper } from "./Drawer.styles";
+import Portal from "../Portal";
+
+export default class DrawerProvider extends React.Component {
+ static propTypes = {
+ children: PropTypes.element.isRequired,
+ className: PropTypes.string
+ };
+
+ static defaultProps = { className: "" };
+
+ contentContainer = React.createRef();
+
+ scrollPosition = 0;
+
+ shouldComponentUpdate(prevProps, prevState) {
+ return (
+ prevState.isOpen !== this.state.isOpen ||
+ prevState.content !== this.state.content ||
+ prevProps.children !== this.props.children
+ );
+ }
+
+ componentDidUpdate() {
+ const { isOpen } = this.state;
+ /* istanbul ignore next */
+ if (
+ !isOpen &&
+ typeof window !== "undefined" &&
+ typeof window.scrollTo === "function"
+ ) {
+ window.scrollTo(0, this.scrollPosition);
+ }
+ }
+
+ setContent = content => this.setState(() => ({ content }));
+
+ toggleDrawer = () => {
+ this.setState(({ isOpen }) => {
+ /* istanbul ignore else */
+ if (typeof window !== "undefined" && !isOpen) {
+ this.scrollPosition = window.pageYOffset;
+ }
+ return { isOpen: !isOpen };
+ });
+ };
+
+ state = {
+ isOpen: false,
+ toggleDrawer: this.toggleDrawer,
+ setContent: this.setContent,
+ content: null
+ };
+
+ render() {
+ const { className, children } = this.props;
+ const { isOpen, content } = this.state;
+ return (
+
+
+ {Children.only(children)}
+ {content && {content}}
+
+
+ );
+ }
+}
diff --git a/src/components/Drawer/__tests__/Provider.spec.js b/src/components/Drawer/__tests__/Provider.spec.js
new file mode 100644
index 000000000..23f169c25
--- /dev/null
+++ b/src/components/Drawer/__tests__/Provider.spec.js
@@ -0,0 +1,87 @@
+/* global window: true */
+import React from "react";
+import { render, Simulate } from "react-testing-library";
+
+import DrawerProvider from "../Provider";
+import { Consumer } from "../Context";
+
+describe("DrawerProvider", () => {
+ beforeEach(() => {
+ window.scrollTo = jest.fn();
+ const modalRoot = global.document.createElement("div");
+ modalRoot.setAttribute("id", "modal-root");
+ const body = global.document.querySelector("body");
+ body.appendChild(modalRoot);
+ });
+
+ afterEach(() => {
+ const body = global.document.querySelector("body");
+ const modalRoot = global.document.getElementById("modal-root");
+ body.removeChild(modalRoot);
+ });
+ it("renders child elements", () => {
+ const { container } = render(
+
+ Content
+
+ );
+ expect(container.innerHTML).toMatchSnapshot();
+ });
+
+ it("sets content", () => {
+ const { getByTestId, container } = render(
+
+
+
+ {({ setContent }) => (
+
+ )}
+
+ Content
+
+
+ );
+
+ Simulate.click(getByTestId("button"));
+
+ expect(container).toMatchSnapshot();
+ });
+
+ it("toggles drawer", () => {
+ const { getByTestId, container } = render(
+
+
+
+ {({ setContent, toggleDrawer }) => (
+
+ )}
+
+ Content
+
+
+ );
+
+ Simulate.click(getByTestId("button"));
+
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/src/components/Drawer/__tests__/__snapshots__/Provider.spec.js.snap b/src/components/Drawer/__tests__/__snapshots__/Provider.spec.js.snap
new file mode 100644
index 000000000..3f3328c73
--- /dev/null
+++ b/src/components/Drawer/__tests__/__snapshots__/Provider.spec.js.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DrawerProvider renders child elements 1`] = `"
"`;
+
+exports[`DrawerProvider sets content 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`DrawerProvider toggles drawer 1`] = `
+
+
+
+
+ Content
+
+
+
+`;
diff --git a/src/components/Drawer/__tests__/__snapshots__/index.spec.js.snap b/src/components/Drawer/__tests__/__snapshots__/index.spec.js.snap
new file mode 100644
index 000000000..c3b54d770
--- /dev/null
+++ b/src/components/Drawer/__tests__/__snapshots__/index.spec.js.snap
@@ -0,0 +1,1836 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Drawer renders default drawer 1`] = `
+.c0 {
+ background-color: rgba(38,38,38,1);
+ color: rgba(255,255,255,1);
+ height: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ opacity: 0;
+ -webkit-transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ overflow: hidden;
+ z-index: -1;
+}
+
+.c0.drawer__content--open {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+}
+
+.c1 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ overflow-x: hidden;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 60px;
+ padding-left: 16px;
+}
+
+.c7 {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ 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;
+ height: 60px;
+ padding: 0 16px;
+}
+
+.c4 {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: auto;
+ height: 100%;
+}
+
+.c5 {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ height: 100%;
+ width: auto;
+}
+
+.c2 {
+ z-index: 1;
+ width: 100%;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2.gradient--overlay:after,
+.c2.gradient--underlay:after {
+ height: 100%;
+ content: "";
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+}
+
+.c2.gradient--underlay.gradient--spotlight:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2:not(.gradient--spotlight).gradient--overlay:after {
+ z-index: 2;
+ opacity: 0.4;
+ background-image: linear-gradient(77deg,rgba(0,0,0,0),#000000);
+}
+
+.c2:not(.gradient--spotlight).gradient--underlay:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c3 {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+
+.c9 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before,
+.c9:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before {
+ top: 0;
+ left: 0;
+}
+
+.c9:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c9 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c9:before,
+.nav--inverted .c9:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c9 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c9:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c9:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c8 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:768px) {
+ .c2 {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2 {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--spotlight {
+ box-shadow: inset 0 1px 40px 10px rgba(0,0,0,0.15);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(82deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(86deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`Drawer renders header elements 1`] = `
+.c0 {
+ background-color: rgba(38,38,38,1);
+ color: rgba(255,255,255,1);
+ height: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ opacity: 0;
+ -webkit-transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ overflow: hidden;
+ z-index: -1;
+}
+
+.c0.drawer__content--open {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+}
+
+.c1 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ overflow-x: hidden;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 60px;
+ padding-left: 16px;
+}
+
+.c7 {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ 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;
+ height: 60px;
+ padding: 0 16px;
+}
+
+.c4 {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: auto;
+ height: 100%;
+}
+
+.c5 {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ height: 100%;
+ width: auto;
+}
+
+.c2 {
+ z-index: 1;
+ width: 100%;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2.gradient--overlay:after,
+.c2.gradient--underlay:after {
+ height: 100%;
+ content: "";
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+}
+
+.c2.gradient--underlay.gradient--spotlight:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2:not(.gradient--spotlight).gradient--overlay:after {
+ z-index: 2;
+ opacity: 0.4;
+ background-image: linear-gradient(77deg,rgba(0,0,0,0),#000000);
+}
+
+.c2:not(.gradient--spotlight).gradient--underlay:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c3 {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+
+.c9 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before,
+.c9:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before {
+ top: 0;
+ left: 0;
+}
+
+.c9:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c9 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c9:before,
+.nav--inverted .c9:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c9 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c9:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c9:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c8 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:768px) {
+ .c2 {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2 {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--spotlight {
+ box-shadow: inset 0 1px 40px 10px rgba(0,0,0,0.15);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(82deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(86deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+ Some Title Element
+
+
+
+
+
+
+ Content
+
+
+
+`;
+
+exports[`Drawer renders multiple child elements 1`] = `
+.c0 {
+ background-color: rgba(38,38,38,1);
+ color: rgba(255,255,255,1);
+ height: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ opacity: 0;
+ -webkit-transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ overflow: hidden;
+ z-index: -1;
+}
+
+.c0.drawer__content--open {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+}
+
+.c1 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ overflow-x: hidden;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 60px;
+ padding-left: 16px;
+}
+
+.c7 {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ 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;
+ height: 60px;
+ padding: 0 16px;
+}
+
+.c4 {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: auto;
+ height: 100%;
+}
+
+.c5 {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ height: 100%;
+ width: auto;
+}
+
+.c2 {
+ z-index: 1;
+ width: 100%;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2.gradient--overlay:after,
+.c2.gradient--underlay:after {
+ height: 100%;
+ content: "";
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+}
+
+.c2.gradient--underlay.gradient--spotlight:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2:not(.gradient--spotlight).gradient--overlay:after {
+ z-index: 2;
+ opacity: 0.4;
+ background-image: linear-gradient(77deg,rgba(0,0,0,0),#000000);
+}
+
+.c2:not(.gradient--spotlight).gradient--underlay:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c3 {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+
+.c9 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before,
+.c9:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before {
+ top: 0;
+ left: 0;
+}
+
+.c9:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c9 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c9:before,
+.nav--inverted .c9:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c9 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c9:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c9:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c8 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:768px) {
+ .c2 {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2 {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--spotlight {
+ box-shadow: inset 0 1px 40px 10px rgba(0,0,0,0.15);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(82deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(86deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+ Content
+
+
+ Content
+
+
+ Content
+
+
+
+`;
+
+exports[`Drawer renders string header header 1`] = `
+.c0 {
+ background-color: rgba(38,38,38,1);
+ color: rgba(255,255,255,1);
+ height: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ visibility: hidden;
+ -webkit-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+ opacity: 0;
+ -webkit-transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: opacity 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ overflow: hidden;
+ z-index: -1;
+}
+
+.c0.drawer__content--open {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+}
+
+.c1 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ overflow-x: hidden;
+}
+
+.c6 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ -webkit-flex-wrap: nowrap;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ height: 60px;
+ padding-left: 16px;
+}
+
+.c7 {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ 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;
+ height: 60px;
+ padding: 0 16px;
+}
+
+.c4 {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: auto;
+ height: 100%;
+}
+
+.c5 {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ height: 100%;
+ width: auto;
+}
+
+.c2 {
+ z-index: 1;
+ width: 100%;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2.gradient--overlay:after,
+.c2.gradient--underlay:after {
+ height: 100%;
+ content: "";
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+}
+
+.c2.gradient--underlay.gradient--spotlight:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c2:not(.gradient--spotlight).gradient--overlay:after {
+ z-index: 2;
+ opacity: 0.4;
+ background-image: linear-gradient(77deg,rgba(0,0,0,0),#000000);
+}
+
+.c2:not(.gradient--spotlight).gradient--underlay:after {
+ z-index: -1;
+ opacity: 0.8;
+ background-image: linear-gradient(256deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+}
+
+.c3 {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+
+.c9 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before,
+.c9:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c9:before {
+ top: 0;
+ left: 0;
+}
+
+.c9:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c9 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c9:before,
+.nav--inverted .c9:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c9 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c9:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c9:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c8 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:768px) {
+ .c2 {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2 {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--spotlight {
+ box-shadow: inset 0 1px 40px 10px rgba(0,0,0,0.15);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2.gradient--underlay.gradient--spotlight:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(82deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--overlay:after {
+ background-image: linear-gradient(86deg,rgba(0,0,0,0),#000000);
+ }
+}
+
+@media screen and (min-width:768px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(260deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+@media screen and (min-width:1024px) {
+ .c2:not(.gradient--spotlight).gradient--underlay:after {
+ background-image: linear-gradient(262deg,rgb(0,45,161),rgba(2,108,223,1) 55%,rgb(0,45,161));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+ Some Title
+
+
+
+
+ Content
+
+
+`;
diff --git a/src/components/Drawer/__tests__/index.spec.js b/src/components/Drawer/__tests__/index.spec.js
new file mode 100644
index 000000000..9fae9860f
--- /dev/null
+++ b/src/components/Drawer/__tests__/index.spec.js
@@ -0,0 +1,56 @@
+import React from "react";
+import renderer from "react-test-renderer";
+
+import Drawer from "../index";
+
+describe("Drawer", () => {
+ it("renders default drawer", () => {
+ expect(renderer.create().toJSON()).toMatchSnapshot();
+ });
+
+ it("renders multiple child elements", () => {
+ expect(
+ renderer
+ .create(
+
+ Content
+ Content
+ Content
+
+ )
+ .toJSON()
+ ).toMatchSnapshot();
+ });
+
+ it("calls a function as child", () => {
+ const children = jest.fn(() => "Content");
+ renderer.create({children});
+
+ expect(children).toHaveBeenCalled();
+ });
+
+ it("renders string header header", () => {
+ expect(
+ renderer.create(Content).toJSON()
+ ).toMatchSnapshot();
+ });
+
+ it("renders header elements", () => {
+ expect(
+ renderer
+ .create(
+ Some Title Element}>
+ Content
+
+ )
+ .toJSON()
+ ).toMatchSnapshot();
+ });
+
+ it("calls header as function", () => {
+ const header = jest.fn(() => "Header Content");
+ renderer.create(Content);
+
+ expect(header).toHaveBeenCalled();
+ });
+});
diff --git a/src/components/Drawer/index.js b/src/components/Drawer/index.js
new file mode 100644
index 000000000..df6161c94
--- /dev/null
+++ b/src/components/Drawer/index.js
@@ -0,0 +1,101 @@
+import React from "react";
+import PropTypes from "prop-types";
+import classNames from "classnames";
+
+import { Consumer } from "./Context";
+import {
+ DrawerContainer,
+ DrawerContent,
+ HeaderContent,
+ CloseButton
+} from "./Drawer.styles";
+import Gradient from "../Gradient";
+import Text from "../Text/Base";
+import HamburgerIcon from "../Icons/HamburgerIcon";
+import omitKeys from "../../utils/omitKeys";
+
+export default class Drawer extends React.Component {
+ static propTypes = {
+ children: PropTypes.oneOfType([
+ PropTypes.node,
+ PropTypes.element,
+ PropTypes.func
+ ]),
+ header: PropTypes.oneOfType([
+ PropTypes.node,
+ PropTypes.func,
+ PropTypes.string
+ ])
+ };
+
+ static defaultProps = { children: null, header: null };
+
+ renderChildren = props => {
+ const { children } = this.props;
+ if (typeof children === "function") return children(props);
+
+ return children;
+ };
+
+ renderHeader = ({ toggleDrawer, isOpen }) => {
+ const { header } = this.props;
+
+ if (typeof header === "function") return header({ toggleDrawer, isOpen });
+
+ return (
+
+
+
+ {typeof content === "string" ? (
+
+ {header}
+
+ ) : (
+ header
+ )}
+
+
+
+
+
+
+ );
+ };
+
+ render() {
+ const { className, ...rest } = this.props;
+ return (
+
+ {({ isOpen, toggleDrawer }) => (
+
+
+ {this.renderHeader({
+ toggleDrawer,
+ isOpen
+ })}
+ {this.renderChildren({
+ toggleDrawer,
+ isOpen
+ })}
+
+
+ )}
+
+ );
+ }
+}
diff --git a/src/components/Icons/HamburgerIcon.js b/src/components/Icons/HamburgerIcon.js
new file mode 100644
index 000000000..156e53e66
--- /dev/null
+++ b/src/components/Icons/HamburgerIcon.js
@@ -0,0 +1,76 @@
+import React from "react";
+import styled from "styled-components";
+
+import constants from "../../theme/constants";
+import getThemeValue from "../../utils/getThemeValue";
+
+const HamburgerContent = styled.span`
+ border-radius: ${constants.borderRadius.small};
+ overflow: hidden;
+ height: 3px;
+ background-color: ${getThemeValue("white", "base")};
+ width: 100%;
+ display: block;
+ transition: all 300ms ${constants.easing.easeInOutQuad};
+
+ &:before,
+ &:after {
+ content: "";
+ border-radius: ${constants.borderRadius.small};
+ height: 3px;
+ background-color: ${getThemeValue("white", "base")};
+ width: 100%;
+ display: block;
+ position: absolute;
+ transform: rotate(0deg);
+ transform-origin: right center;
+ transition: transform 300ms ${constants.easing.easeInOutQuad},
+ background-color 300ms ${constants.easing.easeInOutQuad};
+ }
+
+ &:before {
+ top: 0;
+ left: 0;
+ }
+
+ &:after {
+ bottom: 0;
+ left: 0;
+ }
+
+ .nav--inverted & {
+ background-color: ${getThemeValue("onyx", "base")};
+
+ &:before,
+ &:after {
+ background-color: ${getThemeValue("onyx", "base")};
+ }
+ }
+
+ .hamburger--opened & {
+ background-color: transparent;
+ &:before {
+ transform: rotate(-45deg);
+ }
+
+ &:after {
+ transform: rotate(45deg);
+ }
+ }
+`;
+
+const HamburgerIconWrapper = styled.span`
+ height: 17px;
+ width: 20px;
+ position: relative;
+ display: flex;
+ align-items: center;
+`;
+
+const HamburgerIcon = props => (
+
+
+
+);
+
+export default HamburgerIcon;
diff --git a/src/components/NavBar/ButtonBase.js b/src/components/NavBar/ButtonBase.js
new file mode 100644
index 000000000..13ef93d65
--- /dev/null
+++ b/src/components/NavBar/ButtonBase.js
@@ -0,0 +1,111 @@
+import React from "react";
+import PropTypes from "prop-types";
+import styled from "styled-components";
+import classNames from "classnames";
+
+import colors from "../../theme/colors";
+import spacing from "../../theme/spacing";
+import typography from "../../theme/typography";
+import constants from "../../theme/constants";
+import { smallAndUp } from "../../theme/mediaQueries";
+import getRelByTarget from "../../utils/link";
+
+const BaseButton = styled.button`
+ backface-visibility: hidden;
+ display: flex;
+ align-items: center;
+ flex: 0 1 auto;
+ background-color: transparent;
+ text-decoration: none;
+ border: 0;
+ height: 60px;
+ outline: 0;
+ appearance: none;
+ padding-right: ${spacing.gutters.small / 2}px;
+ padding-left: ${spacing.gutters.small / 2}px;
+ color: ${colors.white.base};
+ font-size: ${typography.size.kilo};
+ font-weight: ${typography.weight.semiBold};
+ transition: all 0.3ms ${constants.easing.easeInOutQuad};
+ .nav--inverted & {
+ color: ${colors.onyx.base};
+ font-weight: ${typography.weight.regular};
+ }
+
+ &.nav-button--last {
+ padding-right: ${spacing.gutters.small}px;
+ }
+
+ &.nav-button--first {
+ padding-left: ${spacing.gutters.small}px;
+ }
+
+ ${smallAndUp`
+ padding-right: ${parseInt(spacing.normal, 10) / 2}px;
+ padding-left: ${parseInt(spacing.normal, 10) / 2}px;
+
+ &.nav-button--last {
+ padding-right: ${spacing.gutters.mediumAndUp}px;
+ }
+
+ &.nav-button--first {
+ padding-left: ${spacing.gutters.mediumAndUp}px;
+ }
+ `};
+`;
+
+const Anchor = BaseButton.withComponent("a");
+
+const Button = ({
+ children,
+ href,
+ target,
+ rel,
+ className,
+ isFirst,
+ isLast,
+ ...props
+}) => {
+ if (href) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
+Button.propTypes = {
+ children: PropTypes.node,
+ href: PropTypes.string,
+ target: PropTypes.string,
+ rel: PropTypes.string,
+ isFirst: PropTypes.bool,
+ isLast: PropTypes.bool
+};
+
+Button.defaultProps = {
+ children: null,
+ href: null,
+ isFirst: false,
+ isLast: false,
+ target: "_self",
+ rel: null
+};
+
+export default Button;
diff --git a/src/components/NavBar/Buttons.js b/src/components/NavBar/Buttons.js
index 27a5561dd..3860c8880 100644
--- a/src/components/NavBar/Buttons.js
+++ b/src/components/NavBar/Buttons.js
@@ -2,89 +2,12 @@ import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
+import Button from "./ButtonBase";
import Menu from "../Icons/Menu";
import Search from "../Icons/Search";
import User from "../Icons/User";
-import colors from "../../theme/colors";
import spacing from "../../theme/spacing";
-import typography from "../../theme/typography";
import { mediumAndUp, smallAndUp } from "../../theme/mediaQueries";
-import getRelByTarget from "../../utils/link";
-
-const BaseButton = styled.button`
- display: flex;
- align-items: center;
- flex: 0 1 auto;
- background-color: transparent;
- text-decoration: none;
- border: 0;
- height: 60px;
- outline: 0;
- appearance: none;
- padding-right: ${({ isLast }) =>
- isLast ? spacing.gutters.small : spacing.gutters.small / 2}px;
- padding-left: ${({ isFirst }) =>
- isFirst ? spacing.gutters.small : spacing.gutters.small / 2}px;
- color: ${colors.white.base};
- font-size: ${typography.size.kilo};
- font-weight: ${typography.weight.semiBold};
- .nav--inverted & {
- color: ${colors.onyx.base};
- font-weight: ${typography.weight.regular};
- }
-
- ${smallAndUp`
- padding-right: ${({ isLast }) =>
- isLast
- ? spacing.gutters.mediumAndUp
- : parseInt(spacing.normal, 10) / 2}px;
- padding-left: ${({ isFirst }) =>
- isFirst
- ? spacing.gutters.mediumAndUp
- : parseInt(spacing.normal, 10) / 2}px;
- `};
-`;
-
-const Anchor = BaseButton.withComponent("a");
-
-const Button = ({ children, href, target, rel, ...props }) => {
- if (href) {
- return (
-
- {children}
-
- );
- }
-
- return (
-
- {children}
-
- );
-};
-
-Button.propTypes = {
- children: PropTypes.node,
- href: PropTypes.string,
- target: PropTypes.string,
- rel: PropTypes.string,
- isFirst: PropTypes.bool,
- isLast: PropTypes.bool
-};
-
-Button.defaultProps = {
- children: null,
- href: null,
- isFirst: false,
- isLast: false,
- target: "_self",
- rel: null
-};
const LogoBtn = styled(Button)`
padding-left: ${spacing.gutters.small / 2}px;
diff --git a/src/components/NavBar/DrawerMenu.js b/src/components/NavBar/DrawerMenu.js
new file mode 100644
index 000000000..bec35bc42
--- /dev/null
+++ b/src/components/NavBar/DrawerMenu.js
@@ -0,0 +1,59 @@
+import React from "react";
+import PropTypes from "prop-types";
+import classNames from "classnames";
+
+import MenuButton from "./MenuButton";
+import Drawer from "../Drawer";
+import { Consumer } from "../Drawer/Context";
+import composeEventHandlers from "../../utils/composeEventHandlers";
+import omitKeys from "../../utils/omitKeys";
+
+const noop = () => {};
+
+class DrawerMenu extends React.Component {
+ static propTypes = {
+ onClick: PropTypes.func,
+ children: PropTypes.node,
+ setContent: PropTypes.func.isRequired,
+ toggleDrawer: PropTypes.func.isRequired,
+ isOpen: PropTypes.bool.isRequired
+ };
+
+ static defaultProps = { onClick: noop, children: null };
+
+ componentDidMount() {
+ const { children, ...rest } = this.props;
+ this.props.setContent(
+
+ {children}
+
+ );
+ }
+
+ render() {
+ const { onClick, toggleDrawer, isOpen } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const DrawerMenuWrapper = props => (
+
+ {({ isOpen = false, setContent = noop, toggleDrawer = noop } = {}) => (
+
+ )}
+
+);
+
+export default DrawerMenuWrapper;
diff --git a/src/components/NavBar/Links.js b/src/components/NavBar/Links.js
index 615ff3516..af439a60d 100644
--- a/src/components/NavBar/Links.js
+++ b/src/components/NavBar/Links.js
@@ -9,6 +9,7 @@ import {
import colors from "../../theme/colors";
import typography from "../../theme/typography";
import spacing from "../../theme/spacing";
+import constants from "../../theme/constants";
const LinkRow = LinkRowBase.extend`
height: 60px;
@@ -27,6 +28,8 @@ const Link = styled(LinkItem)`
color: ${colors.white.base};
font-size: ${typography.size.kilo};
font-weight: ${typography.weight.semiBold};
+ text-shadow: 1px 0px 0px transparent;
+ transition: all 300ms ${constants.easing.easeInOutQuad};
.nav--inverted &,
.links__list & {
diff --git a/src/components/NavBar/MenuButton.js b/src/components/NavBar/MenuButton.js
new file mode 100644
index 000000000..89d8f57cc
--- /dev/null
+++ b/src/components/NavBar/MenuButton.js
@@ -0,0 +1,24 @@
+import React from "react";
+import PropTypes from "prop-types";
+import classNames from "classnames";
+
+import Button from "./ButtonBase";
+import HamburgerIcon from "../Icons/HamburgerIcon";
+
+const MenuButton = ({ iconClassName, className, ...props }) => (
+
+);
+
+MenuButton.propTypes = {
+ isLast: PropTypes.bool,
+ className: PropTypes.string
+};
+
+MenuButton.defaultProps = {
+ isLast: true,
+ className: ""
+};
+
+export default MenuButton;
diff --git a/src/components/NavBar/__tests__/DrawerMenu.spec.js b/src/components/NavBar/__tests__/DrawerMenu.spec.js
new file mode 100644
index 000000000..7d467bf9e
--- /dev/null
+++ b/src/components/NavBar/__tests__/DrawerMenu.spec.js
@@ -0,0 +1,20 @@
+import React from "react";
+import renderer from "react-test-renderer";
+
+import MobileMenu from "../DrawerMenu";
+
+describe("MobileMenu", () => {
+ it("renders default", () => {
+ expect(renderComponent().toJSON()).toMatchSnapshot();
+ });
+
+ it("accepts children as menu content", () => {
+ expect(
+ renderComponent({ children: Some Content
}).toJSON()
+ ).toMatchSnapshot();
+ });
+
+ function renderComponent(props = {}, render = renderer.create) {
+ return render();
+ }
+});
diff --git a/src/components/NavBar/__tests__/__snapshots__/DrawerMenu.spec.js.snap b/src/components/NavBar/__tests__/__snapshots__/DrawerMenu.spec.js.snap
new file mode 100644
index 000000000..18c6fc20c
--- /dev/null
+++ b/src/components/NavBar/__tests__/__snapshots__/DrawerMenu.spec.js.snap
@@ -0,0 +1,313 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MobileMenu accepts children as menu content 1`] = `
+.c0 {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ 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;
+ -webkit-flex: 0 1 auto;
+ -ms-flex: 0 1 auto;
+ flex: 0 1 auto;
+ background-color: transparent;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ border: 0;
+ height: 60px;
+ outline: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding-right: 8px;
+ padding-left: 8px;
+ color: rgba(255,255,255,1);
+ font-size: 16px;
+ font-weight: 600;
+ -webkit-transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.nav--inverted .c0 {
+ color: rgba(38,38,38,1);
+ font-weight: 400;
+}
+
+.c0.nav-button--last {
+ padding-right: 16px;
+}
+
+.c0.nav-button--first {
+ padding-left: 16px;
+}
+
+.c2 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c2:before,
+.c2:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c2:before {
+ top: 0;
+ left: 0;
+}
+
+.c2:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c2 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c2:before,
+.nav--inverted .c2:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c2 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c2:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c2:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c1 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:480px) {
+ .c0 {
+ padding-right: 12px;
+ padding-left: 12px;
+ }
+
+ .c0.nav-button--last {
+ padding-right: 24px;
+ }
+
+ .c0.nav-button--first {
+ padding-left: 24px;
+ }
+}
+
+
+`;
+
+exports[`MobileMenu renders default 1`] = `
+.c0 {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ 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;
+ -webkit-flex: 0 1 auto;
+ -ms-flex: 0 1 auto;
+ flex: 0 1 auto;
+ background-color: transparent;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ border: 0;
+ height: 60px;
+ outline: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding-right: 8px;
+ padding-left: 8px;
+ color: rgba(255,255,255,1);
+ font-size: 16px;
+ font-weight: 600;
+ -webkit-transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.nav--inverted .c0 {
+ color: rgba(38,38,38,1);
+ font-weight: 400;
+}
+
+.c0.nav-button--last {
+ padding-right: 16px;
+}
+
+.c0.nav-button--first {
+ padding-left: 16px;
+}
+
+.c2 {
+ border-radius: 2px;
+ overflow: hidden;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c2:before,
+.c2:after {
+ content: "";
+ border-radius: 2px;
+ height: 3px;
+ background-color: rgba(255,255,255,1);
+ width: 100%;
+ display: block;
+ position: absolute;
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ -webkit-transform-origin: right center;
+ -ms-transform-origin: right center;
+ transform-origin: right center;
+ -webkit-transition: -webkit-transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ -webkit-transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: transform 300ms cubic-bezier(0.455,0.03,0.515,0.955), background-color 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+}
+
+.c2:before {
+ top: 0;
+ left: 0;
+}
+
+.c2:after {
+ bottom: 0;
+ left: 0;
+}
+
+.nav--inverted .c2 {
+ background-color: rgba(38,38,38,1);
+}
+
+.nav--inverted .c2:before,
+.nav--inverted .c2:after {
+ background-color: rgba(38,38,38,1);
+}
+
+.hamburger--opened .c2 {
+ background-color: transparent;
+}
+
+.hamburger--opened .c2:before {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+
+.hamburger--opened .c2:after {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+
+.c1 {
+ height: 17px;
+ width: 20px;
+ position: relative;
+ 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;
+}
+
+@media screen and (min-width:480px) {
+ .c0 {
+ padding-right: 12px;
+ padding-left: 12px;
+ }
+
+ .c0.nav-button--last {
+ padding-right: 24px;
+ }
+
+ .c0.nav-button--first {
+ padding-left: 24px;
+ }
+}
+
+
+`;
diff --git a/src/components/NavBar/__tests__/__snapshots__/index.spec.js.snap b/src/components/NavBar/__tests__/__snapshots__/index.spec.js.snap
index 844e0a3b2..924d8996b 100644
--- a/src/components/NavBar/__tests__/__snapshots__/index.spec.js.snap
+++ b/src/components/NavBar/__tests__/__snapshots__/index.spec.js.snap
@@ -77,6 +77,9 @@ exports[`NavBar renders fixed 1`] = `
color: rgba(255,255,255,1);
font-size: 16px;
font-weight: 600;
+ text-shadow: 1px 0px 0px transparent;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
}
.nav--inverted .c6,
@@ -111,6 +114,8 @@ exports[`NavBar renders fixed 1`] = `
}
.c2 {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -132,10 +137,12 @@ exports[`NavBar renders fixed 1`] = `
-moz-appearance: none;
appearance: none;
padding-right: 8px;
- padding-left: 16px;
+ padding-left: 8px;
color: rgba(255,255,255,1);
font-size: 16px;
font-weight: 600;
+ -webkit-transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
}
.nav--inverted .c2 {
@@ -143,7 +150,17 @@ exports[`NavBar renders fixed 1`] = `
font-weight: 400;
}
+.c2.nav-button--last {
+ padding-right: 16px;
+}
+
+.c2.nav-button--first {
+ padding-left: 16px;
+}
+
.c4 {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -169,6 +186,8 @@ exports[`NavBar renders fixed 1`] = `
color: rgba(255,255,255,1);
font-size: 16px;
font-weight: 600;
+ -webkit-transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 0.3ms cubic-bezier(0.455,0.03,0.515,0.955);
}
.nav--inverted .c4 {
@@ -176,6 +195,14 @@ exports[`NavBar renders fixed 1`] = `
font-weight: 400;
}
+.c4.nav-button--last {
+ padding-right: 16px;
+}
+
+.c4.nav-button--first {
+ padding-left: 16px;
+}
+
.c3 {
padding-left: 8px;
padding-right: 8px;
@@ -191,6 +218,9 @@ exports[`NavBar renders fixed 1`] = `
background-color: transparent;
color: rgba(255,255,255,1);
font-weight: 600;
+ border-bottom: 1px solid transparent;
+ -webkit-transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
+ transition: all 300ms cubic-bezier(0.455,0.03,0.515,0.955);
}
.c0.nav--relative {
@@ -205,19 +235,9 @@ exports[`NavBar renders fixed 1`] = `
position: fixed;
}
-.c0 .linkItem:visited {
- color: rgba(255,255,255,1);
-}
-
.c0.nav--inverted {
background-color: rgba(255,255,255,1);
border-bottom: 1px solid #D1D1D1;
- color: rgba(38,38,38,1);
- font-weight: 400;
-}
-
-.c0.nav--inverted .linkItem:visited {
- color: rgba(38,38,38,1);
}
.c0.nav--overlay:after {
@@ -232,16 +252,6 @@ exports[`NavBar renders fixed 1`] = `
background-image: linear-gradient(77deg,rgba(0,0,0,0),#000000);
}
-.c0.nav--fade-in {
- -webkit-animation: fadeIn 0.3s ease-in-out;
- animation: fadeIn 0.3s ease-in-out;
-}
-
-.c0.nav--fade-out {
- -webkit-animation: fadeOut 0.3s ease-in-out;
- animation: fadeOut 0.3s ease-in-out;
-}
-
.c1 {
width: 100%;
height: 60px;
@@ -266,6 +276,14 @@ exports[`NavBar renders fixed 1`] = `
@media screen and (min-width:480px) {
.c2 {
padding-right: 12px;
+ padding-left: 12px;
+ }
+
+ .c2.nav-button--last {
+ padding-right: 24px;
+ }
+
+ .c2.nav-button--first {
padding-left: 24px;
}
}
@@ -275,6 +293,14 @@ exports[`NavBar renders fixed 1`] = `
padding-right: 12px;
padding-left: 12px;
}
+
+ .c4.nav-button--last {
+ padding-right: 24px;
+ }
+
+ .c4.nav-button--first {
+ padding-left: 24px;
+ }
}
@media screen and (min-width:480px) {
@@ -308,14 +334,14 @@ exports[`NavBar renders fixed 1`] = `
}
}
-@media (min-width:1440px) {
+@media screen and (min-width:1440px) {
.c1 {
padding: 0 44px;
}
}