Skip to content

Commit

Permalink
Merge pull request bulwark-crypto#45 from dustinengle/modal
Browse files Browse the repository at this point in the history
fixes bulwark-crypto#27 added modal
  • Loading branch information
dustinengle committed Aug 27, 2018
2 parents 299f3f1 + 6771706 commit 818e558
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 1 deletion.
58 changes: 58 additions & 0 deletions react/Modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import PropTypes from 'prop-types'
import React from 'react'
import {pickRest} from '../lib/utils'

// Modal
export const Modal = (props) => {
if (!props.open) return null
const [mods, {children, onCancel, ...rest}] = pickRest(props, ['open', 'overlay'])
return (
<div block='modal' mods={mods} onClick={onCancel}>
<div block='modal' elem='container' {...rest}>
{children}
</div>
</div>
)
}

Modal.propTypes = {
children: PropTypes.any.isRequired,
onCancel: PropTypes.func,
open: PropTypes.bool,
overlay: PropTypes.bool
}

// Actions
export const ModalActions = ({children, ...rest}) => (
<div block='modal' elem='actions' {...rest}>
{children}
</div>
)

ModalActions.propTypes = {
children: PropTypes.any.isRequired
}

// Content
export const ModalContent = ({children, ...rest}) => (
<div block='modal' elem='content' {...rest}>
{children}
</div>
)

ModalContent.propTypes = {
children: PropTypes.any.isRequired
}

// Title
export const ModalTitle = ({children, ...rest}) => (
<div block='modal' elem='title' {...rest}>
{children}
</div>
)

ModalTitle.propTypes = {
children: PropTypes.any.isRequired
}

export default {Modal, ModalActions, ModalContent, ModalTitle}
1 change: 1 addition & 0 deletions sass/_library.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@import 'inc/card';
@import 'inc/drawer';
@import 'inc/grid';
@import 'inc/modal';
@import 'inc/navbar';
@import 'inc/reset';
@import 'inc/text';
Expand Down
3 changes: 3 additions & 0 deletions sass/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ $grid-sm: 768px;
$grid-md: 1024px;
$grid-lg: 1200px;
$grid-breaks: ("xs": $grid-xs, "sm": $grid-sm, "md": $grid-md, "lg": $grid-lg);

/* Modal */
$modal-padding: 32px;
69 changes: 69 additions & 0 deletions sass/inc/_modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

.modal {
background: transparent;
bottom: 0;
left: 0;
margin: 0;
padding: 0;
position: fixed;
right: 0;
top: 0;
z-index: 10;

&--open {
opacity: 1;
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
will-change: opacity;
}

&--overlay {
background-color: rgba(0, 0, 0, 0.5);
}

&__actions {
margin: 0;
padding-top: 42px;
text-align: right;

.button, button { margin: 0; }

.button:first-child, button:first-child { margin-right: 20px; }
}

&__container {
background-color: $white;
border-radius: 5px;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.25);
left: 50%;
margin: 0;
padding: $modal-padding;
position: fixed;
top: 50%;
transform: translate(-50%, -50%);
}

&__content {
margin: 0;
padding: 0;

* {
margin: 0;
padding: 0;
}
}

&__title {
font-family: $font-secondary;
font-size: 20px;
font-weight: bold;
height: 28px;
letter-spacing: -1px;
line-height: 30px;
margin-bottom: 17px;

* {
margin: 0;
padding: 0;
}
}
}
71 changes: 71 additions & 0 deletions test/Modal.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* global describe, it */
import React from 'react'
import expect from 'must'
import {shallow} from 'enzyme'
import Button from '../react/Button'
import {Modal, ModalActions, ModalContent, ModalTitle} from '../react/Modal'

describe('<Modal />', () => {
it('render as modal', () => {
const wrapper = shallow(<Modal open>Test</Modal>)
expect(wrapper.is('div')).to.be.true()
expect(wrapper.hasClass('modal')).to.be.true()
expect(wrapper.find('.modal__container')).to.have.length(1)
})

it('render nothing if not open', () => {
const wrapper = shallow(<Modal>Test</Modal>)
expect(wrapper.html()).to.equal(null)
})

it('render as modal open', () => {
const wrapper = shallow(<Modal open>Test</Modal>)
expect(wrapper.hasClass('modal--open')).to.be.true()
})

it('render as modal overlay', () => {
const wrapper = shallow(<Modal open overlay>Test</Modal>)
expect(wrapper.hasClass('modal--overlay')).to.be.true()
})

it('passes onCancel prop', () => {
const fakeFunc = () => {}
const wrapper = shallow(<Modal open onCancel={fakeFunc}>Test</Modal>)
expect(wrapper.prop('onClick')).to.equal(fakeFunc)
})
})

describe('<ModalActions />', () => {
it('render as modal actions', () => {
const wrapper = shallow(<ModalActions><Button>OK</Button></ModalActions>)
expect(wrapper.is('div')).to.be.true()
expect(wrapper.hasClass('modal__actions')).to.be.true()
})
})

describe('<ModalContent />', () => {
it('render as modal content', () => {
const wrapper = shallow(<ModalContent>OK?</ModalContent>)
expect(wrapper.is('div')).to.be.true()
expect(wrapper.hasClass('modal__content')).to.be.true()
})

it('render as modal content text', () => {
const wrapper = shallow(<ModalContent>OK?</ModalContent>)
expect(wrapper.is('div')).to.be.true()
expect(wrapper.text()).to.equal('OK?')
})
})

describe('<ModalTitle />', () => {
it('render as modal title', () => {
const wrapper = shallow(<ModalTitle>Test</ModalTitle>)
expect(wrapper.is('div')).to.be.true()
expect(wrapper.hasClass('modal__title')).to.be.true()
})

it('render modal title text', () => {
const wrapper = shallow(<ModalTitle>Test</ModalTitle>)
expect(wrapper.text()).to.equal('Test')
})
})
4 changes: 3 additions & 1 deletion todo/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { render } from 'react-dom'

import BadgeDemo from './Section/BadgeDemo'
import ButtonDemo from './Section/ButtonDemo'
import CardDemo from './Section/CardDemo'
import {Drawer, DrawerDivider, DrawerHeader, DrawerLink} from '../react/Drawer'
import FontDemo from './Section/FontDemo'
import GridDemo from './Section/GridDemo'
import CardDemo from './Section/CardDemo'
import ModalDemo from './Section/ModalDemo'
import {Navbar, NavbarLink} from '../react/Navbar'
import TooltipDemo from './Section/TooltipDemo'

Expand Down Expand Up @@ -45,6 +46,7 @@ class App extends React.Component {
<CardDemo />
<TooltipDemo />
<BadgeDemo />
<ModalDemo />
</div>
</div>
)
Expand Down
42 changes: 42 additions & 0 deletions todo/Section/ModalDemo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react'

import Button from '../../react/Button'
import {Modal, ModalActions, ModalContent, ModalTitle} from '../../react/Modal'

class ModalDemo extends React.Component {
state = {
open: false,
overlay: false
}

handleClick = () => {
const state = {open: !this.state.open}
if (this.state.overlay && !state.open) state.overlay = false
this.setState(state)
}

handleOverlay = () => this.setState({overlay: !this.state.overlay}, this.handleClick)

render () {
return (
<div>
<Modal onCancel={this.handleClick} open={this.state.open} overlay={this.state.overlay}>
<ModalTitle>Terms of Service</ModalTitle>
<ModalContent style={{width: 320}}>
By clicking Sign Up, you agree to our Terms and that you
have read our Data Use Policy, including our Cookie Use.
</ModalContent>
<ModalActions>
<Button primary outline onClick={this.handleClick}>I Accept</Button>
<Button outline onClick={this.handleClick}>No Thanks</Button>
</ModalActions>
</Modal>
<h3>Modal</h3>
<Button onClick={this.handleClick}>Open Modal</Button>
<Button onClick={this.handleOverlay}>Open Modal with Overlay</Button>
</div>
)
}
}

export default ModalDemo

0 comments on commit 818e558

Please sign in to comment.