-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Drawer): Drawer for mobile menu
- Loading branch information
Oscar Martinez
committed
Sep 14, 2018
1 parent
71c3a65
commit 9d050f1
Showing
24 changed files
with
3,136 additions
and
414 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,53 @@ | ||
### Default | ||
|
||
```react | ||
responsive: true | ||
responsive: false | ||
span: 6 | ||
state: { invert: false } | ||
--- | ||
<DeviceSizeProvider cssOnly> | ||
<Header> | ||
<NavBar message="Hi there this is an optional message. There can be really really really long content here but we are going to try not to overflow this area" position="fixed" invert={state.invert}> | ||
<DisplayFor small medium> | ||
<NavBar.MenuButton isFirst /> | ||
</DisplayFor> | ||
<NavBar.LogoContainer> | ||
Aurora | ||
</NavBar.LogoContainer> | ||
<DisplayFor large xLarge> | ||
<NavBar.LinkRow> | ||
<NavBar.Link href="/">Link 1</NavBar.Link> | ||
<NavBar.Link>Link 2</NavBar.Link> | ||
<NavBar.Link>Link 3</NavBar.Link> | ||
<NavBar.Link> | ||
More | ||
<NavBar.LinkList style={{ width: "265px", top: '40px', left: 0}}> | ||
<NavBar.LinkListItem href="/">Link 4</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 5</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 6</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 7 With Really Long Content </NavBar.LinkListItem> | ||
</NavBar.LinkList> | ||
</NavBar.Link> | ||
</NavBar.LinkRow> | ||
</DisplayFor> | ||
<NavBar.Right> | ||
<NavBar.SearchButton /> | ||
<NavBar.UserButton isLast /> | ||
</NavBar.Right> | ||
</NavBar> | ||
</Header> | ||
<Spacing top={{small: "cozy"}}> | ||
<Container> | ||
<Row> | ||
<Column> | ||
<Button variant="outline" onClick={() => setState({ invert: !state.invert })}>invert</Button> | ||
</Column> | ||
</Row> | ||
</Container> | ||
</Spacing> | ||
</DeviceSizeProvider> | ||
<DrawerProvider> | ||
<DeviceSizeProvider cssOnly> | ||
<Header> | ||
<NavBar message="Hi there this is an optional message. There can be really really really long content here but we are going to try not to overflow this area" position="absolute" invert={state.invert}> | ||
<NavBar.LogoContainer> | ||
Aurora | ||
</NavBar.LogoContainer> | ||
<DisplayFor large xLarge> | ||
<NavBar.LinkRow> | ||
<NavBar.Link href="/">Link 1</NavBar.Link> | ||
<NavBar.Link>Link 2</NavBar.Link> | ||
<NavBar.Link>Link 3</NavBar.Link> | ||
<NavBar.Link> | ||
More | ||
<NavBar.LinkList style={{ width: "275px", top: '40px', left: 0}}> | ||
<NavBar.LinkListItem href="/">Link 4</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 5</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 6</NavBar.LinkListItem> | ||
<NavBar.LinkListItem>Link 7 With Really Long Content </NavBar.LinkListItem> | ||
</NavBar.LinkList> | ||
</NavBar.Link> | ||
</NavBar.LinkRow> | ||
</DisplayFor> | ||
<NavBar.Right> | ||
<NavBar.SearchButton /> | ||
<NavBar.UserButton /> | ||
<DisplayFor small medium> | ||
<NavBar.DrawerMenu header="Content!"> | ||
<Spacing top={{xSmall: "moderate"}}>Some Menu Content</Spacing> | ||
</NavBar.DrawerMenu> | ||
</DisplayFor> | ||
</NavBar.Right> | ||
</NavBar> | ||
</Header> | ||
<Spacing top={{small: "cozy"}}> | ||
<Container> | ||
<Row> | ||
<Column> | ||
<Button variant="outline" onClick={() => setState({ invert: !state.invert })}>invert</Button> | ||
</Column> | ||
</Row> | ||
</Container> | ||
</Spacing> | ||
</DeviceSizeProvider> | ||
</DrawerProvider> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import React from "react"; | ||
|
||
export const { Provider, Consumer } = React.createContext({ isOpen: false }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<Provider value={this.state}> | ||
<ContentWrapper | ||
className={classNames({ "drawer--open": isOpen }, className)} | ||
innerRef={this.contentContainer} | ||
> | ||
{Children.only(children)} | ||
{content && <Portal>{content}</Portal>} | ||
</ContentWrapper> | ||
</Provider> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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( | ||
<DrawerProvider> | ||
<div>Content</div> | ||
</DrawerProvider> | ||
); | ||
expect(container.innerHTML).toMatchSnapshot(); | ||
}); | ||
|
||
it("sets content", () => { | ||
const { getByTestId, container } = render( | ||
<DrawerProvider> | ||
<div> | ||
<Consumer> | ||
{({ setContent }) => ( | ||
<button | ||
data-testid="button" | ||
onClick={() => { | ||
setContent( | ||
<div data-testid="drawer-content">Drawer Content</div> | ||
); | ||
}} | ||
> | ||
ClickMe! | ||
</button> | ||
)} | ||
</Consumer> | ||
Content | ||
</div> | ||
</DrawerProvider> | ||
); | ||
|
||
Simulate.click(getByTestId("button")); | ||
|
||
expect(container).toMatchSnapshot(); | ||
}); | ||
|
||
it("toggles drawer", () => { | ||
const { getByTestId, container } = render( | ||
<DrawerProvider> | ||
<div> | ||
<Consumer> | ||
{({ setContent, toggleDrawer }) => ( | ||
<button | ||
data-testid="button" | ||
onClick={() => { | ||
setContent( | ||
<div data-testid="drawer-content">Drawer Content</div> | ||
); | ||
toggleDrawer(); | ||
}} | ||
> | ||
ClickMe! | ||
</button> | ||
)} | ||
</Consumer> | ||
Content | ||
</div> | ||
</DrawerProvider> | ||
); | ||
|
||
Simulate.click(getByTestId("button")); | ||
|
||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
37 changes: 37 additions & 0 deletions
37
src/components/Drawer/__tests__/__snapshots__/Provider.spec.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`DrawerProvider renders child elements 1`] = `"<div class=\\"sc-ifAKCX eaZCGx\\"><div>Content</div></div>"`; | ||
exports[`DrawerProvider sets content 1`] = ` | ||
<div> | ||
<div | ||
class="sc-ifAKCX eaZCGx" | ||
> | ||
<div> | ||
<button | ||
data-testid="button" | ||
> | ||
ClickMe! | ||
</button> | ||
Content | ||
</div> | ||
</div> | ||
</div> | ||
`; | ||
|
||
exports[`DrawerProvider toggles drawer 1`] = ` | ||
<div> | ||
<div | ||
class="drawer--open sc-ifAKCX eaZCGx" | ||
> | ||
<div> | ||
<button | ||
data-testid="button" | ||
> | ||
ClickMe! | ||
</button> | ||
Content | ||
</div> | ||
</div> | ||
</div> | ||
`; |
Oops, something went wrong.