Ivan - Frontend - Create static method for open modal, improve animation, add accessibility [skip ci]

This commit is contained in:
ivan 2016-09-09 18:22:17 -03:00
parent 8f5852a0d0
commit a0b4457676
10 changed files with 83 additions and 47 deletions

View File

@ -13,23 +13,27 @@ class AreYouSure extends React.Component {
closeModal: React.PropTypes.func closeModal: React.PropTypes.func
}; };
componentDidMount() {
this.refs.yesButton && this.refs.yesButton.focus();
}
render() { render() {
return ( return (
<div className="are-you-sure"> <div className="are-you-sure" role="dialog" aria-labelledby="are-you-sure__header" aria-describedby="are-you-sure__description">
<div className="are-you-sure__header"> <div className="are-you-sure__header" id="are-you-sure__header">
{i18n('ARE_YOU_SURE')} {i18n('ARE_YOU_SURE')}
</div> </div>
<div className="are-you-sure__description"> <div className="are-you-sure__description" id="are-you-sure__description">
{this.props.description} {this.props.description}
</div> </div>
<div className="are-you-sure__buttons"> <div className="are-you-sure__buttons">
<div className="are-you-sure__yes-button"> <div className="are-you-sure__yes-button">
<Button type="secondary" size="small" onClick={this.onYes.bind(this)}> <Button type="secondary" size="small" onClick={this.onYes.bind(this)} ref="yesButton" tabIndex="2">
{i18n('YES')} {i18n('YES')}
</Button> </Button>
</div> </div>
<div className="are-you-sure__no-button"> <div className="are-you-sure__no-button">
<Button type="link" size="auto" onClick={this.onNo.bind(this)}> <Button type="link" size="auto" onClick={this.onNo.bind(this)} tabIndex="2">
{i18n('CANCEL')} {i18n('CANCEL')}
</Button> </Button>
</div> </div>

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import _ from 'lodash'; import _ from 'lodash';
import classNames from 'classnames';
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { browserHistory } from 'react-router'; import { browserHistory } from 'react-router';
@ -21,13 +22,24 @@ class App extends React.Component {
render() { render() {
return ( return (
<div> <div className={this.getClass()}>
{React.cloneElement(this.props.children, {})} <div className="application__content">
{React.cloneElement(this.props.children, {})}
</div>
<ModalContainer /> <ModalContainer />
</div> </div>
); );
} }
getClass() {
let classes = {
'application': true,
'application_modal-opened': (this.props.modal.opened)
};
return classNames(classes);
}
redirectIfPathIsNotValid(props) { redirectIfPathIsNotValid(props) {
const validations = { const validations = {
languageChanged: props.config.language !== this.props.config.language, languageChanged: props.config.language !== this.props.config.language,

12
client/src/app/app.scss Normal file
View File

@ -0,0 +1,12 @@
@import "../scss/vars";
.application {
padding: $half-space;
&_modal-opened {
.application__content {
position: fixed;
overflow: hidden;
}
}
}

View File

@ -3,9 +3,7 @@
const React = require('react'); const React = require('react');
const DocumentTitle = require('react-document-title'); const DocumentTitle = require('react-document-title');
const ModalActions = require('actions/modal-actions'); const ModalContainer = require('app/modal-container');
const store = require('app/store');
const AreYouSure = require('app-components/are-you-sure'); const AreYouSure = require('app-components/are-you-sure');
const Button = require('core-components/button'); const Button = require('core-components/button');
@ -96,10 +94,8 @@ let DemoPage = React.createClass({
title: 'ModalTrigger', title: 'ModalTrigger',
render: ( render: (
<Button onClick={function () { <Button onClick={function () {
store.dispatch( ModalContainer.openModal(
ModalActions.openModal( <AreYouSure description="I confirm I want to perform this action." onYes={()=> {alert('yes');}} />
<AreYouSure description="I confirm I want to perform this action." onYes={()=> {alert('yes');}} />
)
); );
}}> }}>
Open Modal Open Modal

View File

@ -2,11 +2,20 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import keyCode from 'keycode'; import keyCode from 'keycode';
import store from 'app/store';
import ModalActions from 'actions/modal-actions'; import ModalActions from 'actions/modal-actions';
import Modal from 'core-components/modal'; import Modal from 'core-components/modal';
class ModalContainer extends React.Component { class ModalContainer extends React.Component {
static openModal(content) {
store.dispatch(
ModalActions.openModal(
content
)
);
}
static childContextTypes = { static childContextTypes = {
closeModal: React.PropTypes.func closeModal: React.PropTypes.func
}; };
@ -21,7 +30,7 @@ class ModalContainer extends React.Component {
window.addEventListener('keydown', this.onKeyDown.bind(this)); window.addEventListener('keydown', this.onKeyDown.bind(this));
} }
componentWillUnMount() { componentWillUnmount() {
window.removeEventListener('keydown', this.onKeyDown.bind(this)); window.removeEventListener('keydown', this.onKeyDown.bind(this));
} }

View File

@ -56,6 +56,7 @@ class Button extends React.Component {
props.onClick = callback(this.handleClick.bind(this), this.props.onClick); props.onClick = callback(this.handleClick.bind(this), this.props.onClick);
props.className = this.getClass(); props.className = this.getClass();
props.ref = 'button';
delete props.route; delete props.route;
delete props.iconName; delete props.iconName;
@ -91,6 +92,10 @@ class Button extends React.Component {
this.context.router.push(this.props.route.to); this.context.router.push(this.props.route.to);
} }
} }
focus() {
this.refs.button.focus();
}
} }
export default Button; export default Button;

View File

@ -21,22 +21,6 @@
background-color: $secondary-blue; background-color: $secondary-blue;
} }
&_clean {
background: none;
border: none;
}
&_link {
background: none;
border: none;
color: $dark-grey;
text-decoration: underline;
&:focus {
outline: none;
}
}
&_disabled { &_disabled {
background-color: #ec9696; background-color: #ec9696;
} }
@ -58,4 +42,24 @@
width: initial; width: initial;
height: initial; height: initial;
} }
&_clean {
background: none;
border: none;
width: initial;
height: initial;
}
&_link {
background: none;
border: none;
color: $dark-grey;
width: initial;
height: initial;
&:focus, &:hover {
outline: none;
text-decoration: underline;
}
}
} }

View File

@ -9,11 +9,9 @@ class Modal extends React.Component {
render() { render() {
return ( return (
<div className="modal"> <Motion {...this.getAnimations()}>
<Motion {...this.getAnimations()}> {this.renderModal.bind(this)}
{this.renderContent.bind(this)} </Motion>
</Motion>
</div>
); );
} }
@ -21,7 +19,7 @@ class Modal extends React.Component {
return { return {
defaultStyle: { defaultStyle: {
scale: spring(0.7), scale: spring(0.7),
fade: spring(0) fade: spring(0.5)
}, },
style: { style: {
scale: spring(1), scale: spring(1),
@ -30,15 +28,12 @@ class Modal extends React.Component {
} }
} }
renderContent(animation) { renderModal(animation) {
const style = {
transform: 'scale(' + animation.scale + ')',
opacity: animation.fade
};
return ( return (
<div className="modal__content" style={style}> <div className="modal" style={{opacity: animation.fade}}>
{this.props.content} <div className="modal__content" style={{transform: 'scale(' + animation.scale + ')'}}>
{this.props.content}
</div>
</div> </div>
) )
} }

View File

@ -13,6 +13,6 @@
background-color: white; background-color: white;
border-radius: 4px; border-radius: 4px;
padding: 50px; padding: 50px;
box-shadow: 0 0 11px white; box-shadow: 0 0 10px white;
} }
} }

View File

@ -5,5 +5,4 @@
body { body {
font-family: Helvetica, sans-serif; font-family: Helvetica, sans-serif;
background-color: $light-grey; background-color: $light-grey;
padding: $half-space;
} }