From ffa3eca932f91b830f748f160aeb59c2e6e74c87 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 1 Feb 2017 22:01:52 +0100 Subject: [PATCH 01/15] Allow Portal to take title & buttons props --- .../DappPermissions/dappPermissions.css | 5 -- .../modals/DappPermissions/dappPermissions.js | 17 +++--- js/src/ui/Container/Title/title.css | 28 ++++++---- js/src/ui/Container/Title/title.js | 54 +++++++++++-------- js/src/ui/Portal/portal.css | 42 ++++++++++----- js/src/ui/Portal/portal.js | 53 ++++++++++++++---- js/src/ui/Portal/portal.spec.js | 23 ++++++++ 7 files changed, 152 insertions(+), 70 deletions(-) diff --git a/js/src/modals/DappPermissions/dappPermissions.css b/js/src/modals/DappPermissions/dappPermissions.css index 8b7c03a6a21..4e7700dd83d 100644 --- a/js/src/modals/DappPermissions/dappPermissions.css +++ b/js/src/modals/DappPermissions/dappPermissions.css @@ -15,12 +15,7 @@ /* along with Parity. If not, see . */ -.modal { - flex-direction: column; -} - .container { - margin-top: 1.5em; overflow-y: auto; } diff --git a/js/src/modals/DappPermissions/dappPermissions.js b/js/src/modals/DappPermissions/dappPermissions.js index dd63183682c..0252ba39853 100644 --- a/js/src/modals/DappPermissions/dappPermissions.js +++ b/js/src/modals/DappPermissions/dappPermissions.js @@ -18,7 +18,7 @@ import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { AccountCard, ContainerTitle, Portal, SectionList } from '~/ui'; +import { AccountCard, Portal, SectionList } from '~/ui'; import { CheckIcon, StarIcon, StarOutlineIcon } from '~/ui/Icons'; import styles from './dappPermissions.css'; @@ -38,18 +38,15 @@ export default class DappPermissions extends Component { return ( + } > - - } - />
. */ -.byline, .description { - overflow: hidden; - position: relative; - line-height: 1.2em; - max-height: 2.4em; +$bylineColor: #aaa; +$bylineLineHeight: 1.2rem; +$bylineMaxHeight: 2.4rem; +$titleLineHeight: 2rem; +$smallFontSize: 0.75rem; + +.byline, +.description { + color: $bylineColor; display: -webkit-box; + line-height: $bylineLineHeight; + max-height: $bylineMaxHeight; + overflow: hidden; + position: relative; -webkit-line-clamp: 2; -webkit-box-orient: vertical; - color: #aaa; - * { - color: #aaa !important; + color: $bylineColor !important; } } .description { - font-size: 0.75em; + font-size: $smallFontSize; margin: 0.5em 0 0; } .title { - text-transform: uppercase; + line-height: $titleLineHeight; margin: 0; - line-height: 34px; + text-transform: uppercase; } diff --git a/js/src/ui/Container/Title/title.js b/js/src/ui/Container/Title/title.js index 1eb264201cf..217ad13bfda 100644 --- a/js/src/ui/Container/Title/title.js +++ b/js/src/ui/Container/Title/title.js @@ -29,29 +29,41 @@ export default class Title extends Component { } render () { - const { byline, className, title } = this.props; - - const byLine = typeof byline === 'string' - ? ( - - { byline } - - ) - : byline; + const { className, title } = this.props; return (

{ title }

-
- { byLine } -
+ { this.renderByline() } { this.renderDescription() }
); } + renderByline () { + const { byline } = this.props; + + if (!byline) { + return null; + } + + return ( +
+ { + typeof byline === 'string' + ? ( + + { byline } + + ) + : byline + } +
+ ); + } + renderDescription () { const { description } = this.props; @@ -59,17 +71,17 @@ export default class Title extends Component { return null; } - const desc = typeof description === 'string' - ? ( - - { description } - - ) - : description; - return (
- { desc } + { + typeof description === 'string' + ? ( + + { description } + + ) + : description + }
); } diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index daa646ba925..ea9883ec679 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -16,6 +16,7 @@ */ $modalMargin: 1.5em; +$modalPadding: 1.5em; $modalBackZ: 2500; /* This should be the default case, the Portal used as a stand-alone modal */ @@ -55,7 +56,8 @@ $popoverZ: 3600; background-color: rgba(0, 0, 0, 1); box-sizing: border-box; display: flex; - padding: 1.5em; + flex-direction: column; + padding: $modalPadding; position: fixed; * { @@ -77,22 +79,34 @@ $popoverZ: 3600; width: calc(100vw - $popoverLeft - $popoverRight); z-index: $popoverZ; } -} -.closeIcon { - font-size: 4em; - position: absolute; - right: 1rem; - top: 0.5rem; - z-index: 100; + .buttonRow { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-end; + margin: $modalPadding -$modalPadding -$modalPadding -$modalPadding; + } + + .closeIcon { + font-size: 4em; + position: absolute; + right: 1rem; + top: 0.5rem; + z-index: 100; + + &, * { + height: 48px !important; + width: 48px !important; + } - &, * { - height: 48px !important; - width: 48px !important; + &:hover { + cursor: pointer; + opacity: 0.5; + } } - &:hover { - cursor: pointer; - opacity: 0.5; + .titleRow { + margin-bottom: $modalPadding; } } diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index f334405adb7..b712d6d2fff 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -20,6 +20,8 @@ import ReactDOM from 'react-dom'; import ReactPortal from 'react-portal'; import keycode from 'keycode'; +import { nodeOrStringProptype } from '~/util/proptypes'; +import { Title as ContainerTitle } from '~/ui/Container'; import { CloseIcon } from '~/ui/Icons'; import ParityBackground from '~/ui/ParityBackground'; @@ -29,10 +31,12 @@ export default class Portal extends Component { static propTypes = { onClose: PropTypes.func.isRequired, open: PropTypes.bool.isRequired, + buttons: PropTypes.array, children: PropTypes.node, className: PropTypes.string, isChildModal: PropTypes.bool, - onKeyDown: PropTypes.func + onKeyDown: PropTypes.func, + title: nodeOrStringProptype() }; render () { @@ -69,19 +73,48 @@ export default class Portal extends Component { onKeyUp={ this.handleKeyUp } /> -
- -
+ /> + { this.renderTitle() } { children } + { this.renderButtons() }
); } + renderButtons () { + const { buttons } = this.props; + + if (!buttons) { + return null; + } + + return ( +
+ { buttons } +
+ ); + } + + renderTitle () { + const { title } = this.props; + + if (!title) { + return null; + } + + return ( + + ); + } + stopEvent = (event) => { event.preventDefault(); event.stopPropagation(); @@ -95,6 +128,7 @@ export default class Portal extends Component { const { onKeyDown } = this.props; event.persist(); + return onKeyDown ? onKeyDown(event) : false; @@ -111,10 +145,11 @@ export default class Portal extends Component { } handleDOMAction = (ref, method) => { - const refItem = typeof ref === 'string' - ? this.refs[ref] - : ref; - const element = ReactDOM.findDOMNode(refItem); + const element = ReactDOM.findDOMNode( + typeof ref === 'string' + ? this.refs[ref] + : ref + ); if (!element || typeof element[method] !== 'function') { console.warn('could not find', ref, 'or method', method); diff --git a/js/src/ui/Portal/portal.spec.js b/js/src/ui/Portal/portal.spec.js index 6d2f5d5f384..9714f027ca0 100644 --- a/js/src/ui/Portal/portal.spec.js +++ b/js/src/ui/Portal/portal.spec.js @@ -44,4 +44,27 @@ describe('ui/Portal', () => { it('renders defaults', () => { expect(component).to.be.ok; }); + + describe('title rendering', () => { + const TITLE = 'some test title'; + let preTitle; + let title; + + beforeEach(() => { + preTitle = component.find('ContainerTitle'); + title = render({ title: TITLE }).find('ContainerTitle'); + }); + + it('renders no title with none specified', () => { + expect(preTitle).to.have.length(0); + }); + + it('renders the specified title', () => { + expect(title).to.have.length(1); + }); + + it('renders the passed title', () => { + expect(title.props().title).to.equal(TITLE); + }); + }); }); From df487ead67332f4d075cd71449f8b813cfcc0fc3 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 1 Feb 2017 22:10:53 +0100 Subject: [PATCH 02/15] Fix tests --- js/src/ui/Portal/portal.spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/src/ui/Portal/portal.spec.js b/js/src/ui/Portal/portal.spec.js index 9714f027ca0..efa5c1466ca 100644 --- a/js/src/ui/Portal/portal.spec.js +++ b/js/src/ui/Portal/portal.spec.js @@ -47,12 +47,13 @@ describe('ui/Portal', () => { describe('title rendering', () => { const TITLE = 'some test title'; + let preTitle; let title; beforeEach(() => { - preTitle = component.find('ContainerTitle'); - title = render({ title: TITLE }).find('ContainerTitle'); + preTitle = component.find('Title'); + title = render({ title: TITLE }).find('Title'); }); it('renders no title with none specified', () => { From 7d0ceec1794a038e8179c3eac3498476611cf03a Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 1 Feb 2017 22:18:40 +0100 Subject: [PATCH 03/15] Portal consistent in screen center --- js/src/ui/Portal/portal.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index ea9883ec679..22694ab1d4d 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -20,10 +20,10 @@ $modalPadding: 1.5em; $modalBackZ: 2500; /* This should be the default case, the Portal used as a stand-alone modal */ -$modalBottom: 15vh; +$modalBottom: $modalMargin; $modalLeft: $modalMargin; $modalRight: $modalMargin; -$modalTop: 0; +$modalTop: $modalMargin; $modalZ: 3500; /* This is the case where popped-up over another modal, Portal or otherwise */ From f39894cd3c1a1c24050765e0b78b74e6e422627e Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 2 Feb 2017 10:06:37 +0100 Subject: [PATCH 04/15] Allow hiding of Close (e.g. FirstRun usage) --- js/src/ui/Portal/portal.css | 3 ++- js/src/ui/Portal/portal.js | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index 22694ab1d4d..71e22e5029d 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -57,6 +57,7 @@ $popoverZ: 3600; box-sizing: border-box; display: flex; flex-direction: column; + justify-content: space-between; padding: $modalPadding; position: fixed; @@ -85,7 +86,7 @@ $popoverZ: 3600; flex-direction: row; flex-wrap: nowrap; justify-content: flex-end; - margin: $modalPadding -$modalPadding -$modalPadding -$modalPadding; + margin: $modalPadding 0 0 0; } .closeIcon { diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index b712d6d2fff..0d54e6647a3 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -34,6 +34,7 @@ export default class Portal extends Component { buttons: PropTypes.array, children: PropTypes.node, className: PropTypes.string, + hideClose: PropTypes.bool, isChildModal: PropTypes.bool, onKeyDown: PropTypes.func, title: nodeOrStringProptype() @@ -73,10 +74,7 @@ export default class Portal extends Component { onKeyUp={ this.handleKeyUp } /> - + { this.renderClose() } { this.renderTitle() } { children } { this.renderButtons() } @@ -100,6 +98,21 @@ export default class Portal extends Component { ); } + renderClose () { + const { hideClose } = this.props; + + if (hideClose) { + return null; + } + + return ( + + ); + } + renderTitle () { const { title } = this.props; @@ -121,7 +134,11 @@ export default class Portal extends Component { } handleClose = () => { - this.props.onClose(); + const { hideClose, onClose } = this.props; + + if (!hideClose) { + onClose(); + } } handleKeyDown = (event) => { From 76af56eef8fdf14e7fbc45da3ab10db393ef71ef Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 2 Feb 2017 10:33:37 +0100 Subject: [PATCH 05/15] Set overflow style on body based on open --- js/src/ui/Portal/portal.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index 0d54e6647a3..eda646c7846 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -40,6 +40,20 @@ export default class Portal extends Component { title: nodeOrStringProptype() }; + componentDidMount () { + this.setBodyOverflow(this.props.open); + } + + componentWillReceiveProps (nextProps) { + if (nextProps.open !== this.props.open) { + this.setBodyOverflow(nextProps.open); + } + } + + componentWillUnmount () { + this.setBodyOverflow(false); + } + render () { const { children, className, isChildModal, open } = this.props; @@ -175,4 +189,10 @@ export default class Portal extends Component { return element[method](); } + + setBodyOverflow (open) { + document.body.style.overflow = open + ? 'hidden' + : null; + } } From 38d5052965aeac321c84917e0fd9ad8a5289964d Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 2 Feb 2017 11:14:57 +0100 Subject: [PATCH 06/15] Don't lock scroll for child popups (overlaps) --- js/src/ui/Portal/portal.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index eda646c7846..6e1d0553546 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -191,8 +191,10 @@ export default class Portal extends Component { } setBodyOverflow (open) { - document.body.style.overflow = open - ? 'hidden' - : null; + if (!this.props.isChildModal) { + document.body.style.overflow = open + ? 'hidden' + : null; + } } } From 5457603e3759292b97ccc431ce1a1fa07df6ab6a Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 2 Feb 2017 14:58:59 +0100 Subject: [PATCH 07/15] Override buttons to be white --- js/src/ui/Portal/portal.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index 71e22e5029d..60a77df06cc 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -87,6 +87,14 @@ $popoverZ: 3600; flex-wrap: nowrap; justify-content: flex-end; margin: $modalPadding 0 0 0; + + button:not([disabled]) { + color: white !important; + + svg { + fill: white !important; + } + } } .closeIcon { From 4425498bd4c4743cd6be0eaf7c0774bf8e80c213 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 2 Feb 2017 15:30:44 +0100 Subject: [PATCH 08/15] Expose ~/ui/Modal/Title as re-usable component --- js/src/ui/Modal/modal.css | 14 ---------- js/src/ui/Modal/modal.js | 7 ++--- js/src/ui/{Modal => }/Title/index.js | 0 js/src/ui/Title/title.css | 26 +++++++++++++++++++ js/src/ui/{Modal => }/Title/title.js | 38 ++++++++++++++++++---------- js/src/ui/index.js | 2 ++ 6 files changed, 56 insertions(+), 31 deletions(-) rename js/src/ui/{Modal => }/Title/index.js (100%) create mode 100644 js/src/ui/Title/title.css rename js/src/ui/{Modal => }/Title/title.js (67%) diff --git a/js/src/ui/Modal/modal.css b/js/src/ui/Modal/modal.css index 2b8172f2f33..5eb419a76bb 100644 --- a/js/src/ui/Modal/modal.css +++ b/js/src/ui/Modal/modal.css @@ -47,20 +47,6 @@ .title { background: rgba(0, 0, 0, 0.25) !important; padding: 1em; - margin-bottom: 0; - - h3 { - margin: 0; - text-transform: uppercase; - } - - .steps { - margin-bottom: -1em; - } -} - -.waiting { - margin: 1em -1em -1em -1em; } .overlay { diff --git a/js/src/ui/Modal/modal.js b/js/src/ui/Modal/modal.js index 7dde32f4580..7c7e19883f5 100644 --- a/js/src/ui/Modal/modal.js +++ b/js/src/ui/Modal/modal.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import { nodeOrStringProptype } from '~/util/proptypes'; import Container from '../Container'; -import Title from './Title'; +import Title from '../Title'; const ACTIONS_STYLE = { borderStyle: 'none' }; const TITLE_STYLE = { borderStyle: 'none' }; @@ -63,11 +63,12 @@ class Modal extends Component { const contentStyle = muiTheme.parity.getBackgroundStyle(null, settings.backgroundSeed); const header = ( ); const classes = `${styles.dialog} ${className}`; diff --git a/js/src/ui/Modal/Title/index.js b/js/src/ui/Title/index.js similarity index 100% rename from js/src/ui/Modal/Title/index.js rename to js/src/ui/Title/index.js diff --git a/js/src/ui/Title/title.css b/js/src/ui/Title/title.css new file mode 100644 index 00000000000..202a2f6d959 --- /dev/null +++ b/js/src/ui/Title/title.css @@ -0,0 +1,26 @@ +/* Copyright 2015-2017 Parity Technologies (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation, either version 3 of the License, or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful, +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not, see <http://www.gnu.org/licenses/>. +*/ + +.title { + .steps { + margin-bottom: -1em; + } + + .waiting { + margin: 1em -1em -1em -1em; + } +} diff --git a/js/src/ui/Modal/Title/title.js b/js/src/ui/Title/title.js similarity index 67% rename from js/src/ui/Modal/Title/title.js rename to js/src/ui/Title/title.js index d39bbb772ca..4045bd9393f 100644 --- a/js/src/ui/Modal/Title/title.js +++ b/js/src/ui/Title/title.js @@ -14,35 +14,45 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see <http://www.gnu.org/licenses/>. -import React, { Component, PropTypes } from 'react'; import { LinearProgress } from 'material-ui'; import { Step, Stepper, StepLabel } from 'material-ui/Stepper'; +import React, { Component, PropTypes } from 'react'; +// TODO: It would make sense (going forward) to replace all uses of +// ContainerTitle with this component. In that case the styles for the +// h3 (title) can be pulled from there. (As it stands the duplication +// between the 2 has been removed, but as a short-term DRY only) +import { Title as ContainerTitle } from '~/ui/Container'; import { nodeOrStringProptype } from '~/util/proptypes'; -import styles from '../modal.css'; +import styles from './title.css'; export default class Title extends Component { static propTypes = { + activeStep: PropTypes.number, busy: PropTypes.bool, - current: PropTypes.number, + busySteps: PropTypes.array, + className: PropTypes.string, steps: PropTypes.array, - waiting: PropTypes.array, title: nodeOrStringProptype() } render () { - const { current, steps, title } = this.props; + const { activeStep, className, steps, title } = this.props; return ( - <div className={ styles.title }> - <h3> - { + <div + className={ + [styles.title, className].join(' ') + } + > + <ContainerTitle + title={ steps - ? steps[current] + ? steps[activeStep] : title } - </h3> + /> { this.renderSteps() } { this.renderWaiting() } </div> @@ -50,7 +60,7 @@ export default class Title extends Component { } renderSteps () { - const { current, steps } = this.props; + const { activeStep, steps } = this.props; if (!steps) { return; @@ -58,7 +68,7 @@ export default class Title extends Component { return ( <div className={ styles.steps }> - <Stepper activeStep={ current }> + <Stepper activeStep={ activeStep }> { this.renderTimeline() } </Stepper> </div> @@ -80,8 +90,8 @@ export default class Title extends Component { } renderWaiting () { - const { current, busy, waiting } = this.props; - const isWaiting = busy || (waiting || []).includes(current); + const { activeStep, busy, busySteps } = this.props; + const isWaiting = busy || (busySteps || []).includes(activeStep); if (!isWaiting) { return null; diff --git a/js/src/ui/index.js b/js/src/ui/index.js index ce71bae0250..02889d3acbe 100644 --- a/js/src/ui/index.js +++ b/js/src/ui/index.js @@ -54,6 +54,7 @@ import SectionList from './SectionList'; import ShortenedHash from './ShortenedHash'; import SignerIcon from './SignerIcon'; import Tags from './Tags'; +import Title from './Title'; import Tooltips, { Tooltip } from './Tooltips'; import TxHash from './TxHash'; import TxList from './TxList'; @@ -114,6 +115,7 @@ export { SectionList, SignerIcon, Tags, + Title, Tooltip, Tooltips, TxHash, From 3a8fadce61e79ae088ca0cbfbc9158215faff63a Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Thu, 2 Feb 2017 16:01:21 +0100 Subject: [PATCH 09/15] Use ~/ui/Title to render the Title --- js/src/ui/Portal/portal.js | 32 ++++++++++++++------------------ js/src/ui/Title/title.css | 2 +- js/src/ui/Title/title.js | 4 ++++ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index 6e1d0553546..d3d51b6a81c 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -21,9 +21,9 @@ import ReactPortal from 'react-portal'; import keycode from 'keycode'; import { nodeOrStringProptype } from '~/util/proptypes'; -import { Title as ContainerTitle } from '~/ui/Container'; import { CloseIcon } from '~/ui/Icons'; import ParityBackground from '~/ui/ParityBackground'; +import Title from '~/ui/Title'; import styles from './portal.css'; @@ -31,12 +31,16 @@ export default class Portal extends Component { static propTypes = { onClose: PropTypes.func.isRequired, open: PropTypes.bool.isRequired, + activeStep: PropTypes.number, + busy: PropTypes.bool, + busySteps: PropTypes.array, buttons: PropTypes.array, children: PropTypes.node, className: PropTypes.string, hideClose: PropTypes.bool, isChildModal: PropTypes.bool, onKeyDown: PropTypes.func, + steps: PropTypes.array, title: nodeOrStringProptype() }; @@ -55,7 +59,7 @@ export default class Portal extends Component { } render () { - const { children, className, isChildModal, open } = this.props; + const { activeStep, busy, busySteps, children, className, isChildModal, open, steps, title } = this.props; if (!open) { return null; @@ -89,7 +93,14 @@ export default class Portal extends Component { /> <ParityBackground className={ styles.parityBackground } /> { this.renderClose() } - { this.renderTitle() } + <Title + activeStep={ activeStep } + busy={ busy } + busySteps={ busySteps } + className={ styles.titleRow } + steps={ steps } + title={ title } + /> { children } { this.renderButtons() } </div> @@ -127,21 +138,6 @@ export default class Portal extends Component { ); } - renderTitle () { - const { title } = this.props; - - if (!title) { - return null; - } - - return ( - <ContainerTitle - className={ styles.titleRow } - title={ title } - /> - ); - } - stopEvent = (event) => { event.preventDefault(); event.stopPropagation(); diff --git a/js/src/ui/Title/title.css b/js/src/ui/Title/title.css index 202a2f6d959..c211b0586db 100644 --- a/js/src/ui/Title/title.css +++ b/js/src/ui/Title/title.css @@ -17,7 +17,7 @@ .title { .steps { - margin-bottom: -1em; + margin: -0.5em 0 -1em 0; } .waiting { diff --git a/js/src/ui/Title/title.js b/js/src/ui/Title/title.js index 4045bd9393f..c28c9029da4 100644 --- a/js/src/ui/Title/title.js +++ b/js/src/ui/Title/title.js @@ -40,6 +40,10 @@ export default class Title extends Component { render () { const { activeStep, className, steps, title } = this.props; + if (!title && !steps) { + return null; + } + return ( <div className={ From 7171d443b622838295e6a23ec2a8748eab473cb9 Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Thu, 2 Feb 2017 20:44:14 +0100 Subject: [PATCH 10/15] Update tests --- js/src/ui/Portal/portal.css | 6 +++++- js/src/ui/Portal/portal.js | 2 +- js/src/ui/Portal/portal.spec.js | 7 ------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index 60a77df06cc..a7d650c29e7 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -82,11 +82,15 @@ $popoverZ: 3600; } .buttonRow { + bottom: 0; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-end; - margin: $modalPadding 0 0 0; + left: 0; + padding: $modalPadding $modalPadding 0 $modalPadding; + position: absolute; + right: 0; button:not([disabled]) { color: white !important; diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index d3d51b6a81c..fea64fd0d35 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -93,6 +93,7 @@ export default class Portal extends Component { /> <ParityBackground className={ styles.parityBackground } /> { this.renderClose() } + { this.renderButtons() } <Title activeStep={ activeStep } busy={ busy } @@ -102,7 +103,6 @@ export default class Portal extends Component { title={ title } /> { children } - { this.renderButtons() } </div> </div> </ReactPortal> diff --git a/js/src/ui/Portal/portal.spec.js b/js/src/ui/Portal/portal.spec.js index efa5c1466ca..fdc1ab4a71c 100644 --- a/js/src/ui/Portal/portal.spec.js +++ b/js/src/ui/Portal/portal.spec.js @@ -47,19 +47,12 @@ describe('ui/Portal', () => { describe('title rendering', () => { const TITLE = 'some test title'; - - let preTitle; let title; beforeEach(() => { - preTitle = component.find('Title'); title = render({ title: TITLE }).find('Title'); }); - it('renders no title with none specified', () => { - expect(preTitle).to.have.length(0); - }); - it('renders the specified title', () => { expect(title).to.have.length(1); }); From 6b47241fd793729c4683de35b2ff4d27a465f94c Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac <ngotchac@gmail.com> Date: Fri, 3 Feb 2017 13:53:10 +0100 Subject: [PATCH 11/15] Added a portal example with buttons and steps --- js/src/ui/Portal/portal.example.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/js/src/ui/Portal/portal.example.js b/js/src/ui/Portal/portal.example.js index e8c51008ef3..7305a27b0b1 100644 --- a/js/src/ui/Portal/portal.example.js +++ b/js/src/ui/Portal/portal.example.js @@ -16,6 +16,7 @@ import React, { Component } from 'react'; +import { Button } from '~/ui'; import PlaygroundExample from '~/playground/playgroundExample'; import Modal from '../Modal'; @@ -77,6 +78,29 @@ export default class PortalExample extends Component { </Portal> </div> </PlaygroundExample> + + <PlaygroundExample name='Portal with Buttons'> + <div> + <button onClick={ this.handleOpen(4) }>Open</button> + <Portal + activeStep={ 0 } + buttons={ [ + <Button + key='close' + label='close' + onClick={ this.handleClose } + /> + ] } + isChildModal + open={ open[4] || false } + onClose={ this.handleClose } + steps={ [ 'step 1', 'step 2' ] } + title='Portal with button' + > + <p>This is the fourth portal</p> + </Portal> + </div> + </PlaygroundExample> </div> ); } From 350f05a3e5218c9aca094e08de94c0cc6509317b Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Fri, 3 Feb 2017 16:13:46 +0100 Subject: [PATCH 12/15] Address PR comments --- js/src/modals/AddDapps/addDapps.js | 16 +++++++--------- js/src/ui/Portal/portal.css | 10 +++++----- js/src/ui/Portal/portal.js | 6 ++++-- js/src/ui/Title/title.js | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/js/src/modals/AddDapps/addDapps.js b/js/src/modals/AddDapps/addDapps.js index 0a4d19af93f..9b1fcc76008 100644 --- a/js/src/modals/AddDapps/addDapps.js +++ b/js/src/modals/AddDapps/addDapps.js @@ -18,7 +18,7 @@ import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { ContainerTitle, DappCard, Portal, SectionList } from '~/ui'; +import { DappCard, Portal, SectionList } from '~/ui'; import { CheckIcon } from '~/ui/Icons'; import styles from './addDapps.css'; @@ -41,15 +41,13 @@ export default class AddDapps extends Component { className={ styles.modal } onClose={ store.closeModal } open + title={ + <FormattedMessage + id='dapps.add.label' + defaultMessage='visible applications' + /> + } > - <ContainerTitle - title={ - <FormattedMessage - id='dapps.add.label' - defaultMessage='visible applications' - /> - } - /> <div className={ styles.container }> <div className={ styles.warning } /> { diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index a7d650c29e7..05a87b71fd6 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -82,15 +82,11 @@ $popoverZ: 3600; } .buttonRow { - bottom: 0; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-end; - left: 0; - padding: $modalPadding $modalPadding 0 $modalPadding; - position: absolute; - right: 0; + padding: $modalPadding 0 0 0; button:not([disabled]) { color: white !important; @@ -101,6 +97,10 @@ $popoverZ: 3600; } } + .childContainer { + flex: 1; + } + .closeIcon { font-size: 4em; position: absolute; diff --git a/js/src/ui/Portal/portal.js b/js/src/ui/Portal/portal.js index fea64fd0d35..03b8b1f18b3 100644 --- a/js/src/ui/Portal/portal.js +++ b/js/src/ui/Portal/portal.js @@ -93,7 +93,6 @@ export default class Portal extends Component { /> <ParityBackground className={ styles.parityBackground } /> { this.renderClose() } - { this.renderButtons() } <Title activeStep={ activeStep } busy={ busy } @@ -102,7 +101,10 @@ export default class Portal extends Component { steps={ steps } title={ title } /> - { children } + <div className={ styles.childContainer }> + { children } + </div> + { this.renderButtons() } </div> </div> </ReactPortal> diff --git a/js/src/ui/Title/title.js b/js/src/ui/Title/title.js index c28c9029da4..6f1319bd096 100644 --- a/js/src/ui/Title/title.js +++ b/js/src/ui/Title/title.js @@ -53,7 +53,7 @@ export default class Title extends Component { <ContainerTitle title={ steps - ? steps[activeStep] + ? steps[activeStep || 0] : title } /> From 8ea78f5647038c0ed8d1d3b29de07818f6795dd5 Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Fri, 3 Feb 2017 22:23:20 +0100 Subject: [PATCH 13/15] Fix AddressSelect with new container withing container --- js/src/modals/AddDapps/addDapps.css | 1 - .../ui/Form/AddressSelect/addressSelect.css | 6 ++ js/src/ui/Form/AddressSelect/addressSelect.js | 58 ++++++++++--------- js/src/ui/Portal/portal.css | 2 + 4 files changed, 39 insertions(+), 28 deletions(-) diff --git a/js/src/modals/AddDapps/addDapps.css b/js/src/modals/AddDapps/addDapps.css index 8de8f7f8067..b26ffa623de 100644 --- a/js/src/modals/AddDapps/addDapps.css +++ b/js/src/modals/AddDapps/addDapps.css @@ -20,7 +20,6 @@ } .container { - margin-top: 1.5em; overflow-y: auto; } diff --git a/js/src/ui/Form/AddressSelect/addressSelect.css b/js/src/ui/Form/AddressSelect/addressSelect.css index 0502a271fce..94549c26f34 100644 --- a/js/src/ui/Form/AddressSelect/addressSelect.css +++ b/js/src/ui/Form/AddressSelect/addressSelect.css @@ -73,6 +73,12 @@ } } +.title { + display: flex; + flex-direction: column; + position: relative; +} + .label { margin: 1rem 0.5rem 0.25em; color: rgba(255, 255, 255, 0.498039); diff --git a/js/src/ui/Form/AddressSelect/addressSelect.js b/js/src/ui/Form/AddressSelect/addressSelect.js index ce3aad2d353..d3c7462c3c0 100644 --- a/js/src/ui/Form/AddressSelect/addressSelect.js +++ b/js/src/ui/Form/AddressSelect/addressSelect.js @@ -180,34 +180,38 @@ class AddressSelect extends Component { onClose={ this.handleClose } onKeyDown={ this.handleKeyDown } open={ expanded } + title={ + <div className={ styles.title }> + <label className={ styles.label } htmlFor={ id }> + { label } + </label> + <div className={ styles.outerInput }> + <input + id={ id } + className={ styles.input } + placeholder={ ilHint } + onBlur={ this.handleInputBlur } + onFocus={ this.handleInputFocus } + onChange={ this.handleChange } + ref={ this.setInputRef } + /> + { this.renderLoader() } + </div> + + <div className={ styles.underline }> + <TextFieldUnderline + focus={ inputFocused } + focusStyle={ BOTTOM_BORDER_STYLE } + muiTheme={ muiTheme } + style={ BOTTOM_BORDER_STYLE } + /> + </div> + + { this.renderCurrentInput() } + { this.renderRegistryValues() } + </div> + } > - <label className={ styles.label } htmlFor={ id }> - { label } - </label> - <div className={ styles.outerInput }> - <input - id={ id } - className={ styles.input } - placeholder={ ilHint } - onBlur={ this.handleInputBlur } - onFocus={ this.handleInputFocus } - onChange={ this.handleChange } - ref={ this.setInputRef } - /> - { this.renderLoader() } - </div> - - <div className={ styles.underline }> - <TextFieldUnderline - focus={ inputFocused } - focusStyle={ BOTTOM_BORDER_STYLE } - muiTheme={ muiTheme } - style={ BOTTOM_BORDER_STYLE } - /> - </div> - - { this.renderCurrentInput() } - { this.renderRegistryValues() } { this.renderAccounts() } </Portal> ); diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index 05a87b71fd6..d88150bfedf 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -99,6 +99,8 @@ $popoverZ: 3600; .childContainer { flex: 1; + overflow-x: hidden; + overflow-y: auto; } .closeIcon { From f4b42080d586dedc9a9985721e9e020099b36f1e Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Fri, 3 Feb 2017 22:27:10 +0100 Subject: [PATCH 14/15] Move legend to "buttons" --- .../DappPermissions/dappPermissions.css | 1 - .../modals/DappPermissions/dappPermissions.js | 22 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/js/src/modals/DappPermissions/dappPermissions.css b/js/src/modals/DappPermissions/dappPermissions.css index 4e7700dd83d..22df5d24b50 100644 --- a/js/src/modals/DappPermissions/dappPermissions.css +++ b/js/src/modals/DappPermissions/dappPermissions.css @@ -60,7 +60,6 @@ .legend { opacity: 0.75; - margin-top: 1em; span { line-height: 24px; diff --git a/js/src/modals/DappPermissions/dappPermissions.js b/js/src/modals/DappPermissions/dappPermissions.js index 0252ba39853..4cd7cc8370c 100644 --- a/js/src/modals/DappPermissions/dappPermissions.js +++ b/js/src/modals/DappPermissions/dappPermissions.js @@ -38,6 +38,18 @@ export default class DappPermissions extends Component { return ( <Portal + buttons={ + <div className={ styles.legend }> + <FormattedMessage + id='dapps.permissions.description' + defaultMessage='{activeIcon} account is available to application, {defaultIcon} account is the default account' + values={ { + activeIcon: <CheckIcon />, + defaultIcon: <StarIcon /> + } } + /> + </div> + } onClose={ store.closeModal } open title={ @@ -54,16 +66,6 @@ export default class DappPermissions extends Component { renderItem={ this.renderAccount } /> </div> - <div className={ styles.legend }> - <FormattedMessage - id='dapps.permissions.description' - defaultMessage='{activeIcon} account is available to application, {defaultIcon} account is the default account' - values={ { - activeIcon: <CheckIcon />, - defaultIcon: <StarIcon /> - } } - /> - </div> </Portal> ); } From 7edf95321acfc90b826c5c04894ebdbb47fa43bb Mon Sep 17 00:00:00 2001 From: Jaco Greeff <jaco@ethcore.io> Date: Fri, 3 Feb 2017 22:29:32 +0100 Subject: [PATCH 15/15] AddressSelect extra padding --- js/src/ui/Form/AddressSelect/addressSelect.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/js/src/ui/Form/AddressSelect/addressSelect.css b/js/src/ui/Form/AddressSelect/addressSelect.css index 94549c26f34..43d6a7075fb 100644 --- a/js/src/ui/Form/AddressSelect/addressSelect.css +++ b/js/src/ui/Form/AddressSelect/addressSelect.css @@ -108,14 +108,11 @@ } .categories { - flex: 1; - display: flex; + flex: 1; flex-direction: row; justify-content: flex-start; - margin: 2rem 0 0; - > * { flex: 1; }