Merge pull request #5559 from paritytech/menu

dropdowns
This commit is contained in:
Craig O'Connor 2017-05-10 23:48:40 -04:00 committed by GitHub
commit 85cf93e65d
21 changed files with 212 additions and 75 deletions

View File

@ -15,13 +15,13 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Button as SemButton } from 'semantic-ui-react'; import { Button as SemanticButton } from 'semantic-ui-react';
import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
export default function Button ({ active, animated, basic, className, color, disabled, fullWidth, icon, label, onClick, primary, size, toggle }) { export default function Button ({ active, animated, basic, className, color, disabled, fullWidth, icon, label, onClick, primary, size, toggle }) {
return ( return (
<SemButton <SemanticButton
active={ active } active={ active }
animated={ animated } animated={ animated }
basic={ basic } basic={ basic }

View File

@ -16,7 +16,6 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import { Card } from 'material-ui/Card';
import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
@ -50,7 +49,7 @@ export default class Container extends Component {
} }
const card = ( const card = (
<Card <div
className={ className={
compact compact
? styles.compact ? styles.compact
@ -61,7 +60,7 @@ export default class Container extends Component {
> >
{ this.renderTitle() } { this.renderTitle() }
{ children } { children }
</Card> </div>
); );
return ( return (
@ -126,9 +125,9 @@ export default class Container extends Component {
} }
return ( return (
<Card className={ styles.hoverOverlay }> <div className={ styles.hoverOverlay }>
{ hover } { hover }
</Card> </div>
); );
} }

View File

@ -35,24 +35,4 @@ describe('ui/Container', () => {
expect(render({ className: 'testClass' })).to.have.className('testClass'); expect(render({ className: 'testClass' })).to.have.className('testClass');
}); });
}); });
describe('sections', () => {
it('renders the default Card', () => {
expect(render().find('Card')).to.have.length(1);
});
it('renders Hover Card when available', () => {
const cards = render({ hover: <div>testingHover</div> }).find('Card');
expect(cards).to.have.length(2);
expect(cards.get(1).props.children.props.children).to.equal('testingHover');
});
it('renders the Title', () => {
const title = render({ title: 'title' }).find('Title');
expect(title).to.have.length(1);
expect(title.props().title).to.equal('title');
});
});
}); });

View File

@ -0,0 +1,21 @@
/* 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/>.
*/
.dropdown {
position: relative;
display: block;
}

View File

@ -0,0 +1,54 @@
// 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/>.
import React, { PropTypes } from 'react';
import { Dropdown as SemanticDropdown } from 'semantic-ui-react';
import LabelComponent from '../labelComponent';
import styles from './dropdown.css';
// FIXME: Currently does not display the selected icon alongside
export default function Dropdown ({ className, disabled = false, fullWidth = true, hint, label, onChange, options, value }) {
return (
<LabelComponent label={ label }>
<SemanticDropdown
className={ `${styles.dropdown} ${className}` }
disabled={ disabled }
fluid={ fullWidth }
onChange={ onChange }
options={ options }
placeholder={ hint }
scrolling
search
selection
value={ value }
/>
</LabelComponent>
);
}
Dropdown.propTypes = {
className: PropTypes.string,
disabled: PropTypes.bool, // A disabled dropdown menu or item does not allow user interaction.
fullWidth: PropTypes.bool, // A dropdown can take the full width of its parent.
hint: PropTypes.string, // Placeholder text.
label: PropTypes.node,
name: PropTypes.func, // Name of the hidden input which holds the value.
onChange: PropTypes.func, // Called when the user attempts to change the value.
options: PropTypes.any, // Array of Dropdown.Item props e.g. `{ text: '', value: '' }`
value: PropTypes.any // Current value. Creates a controlled component.
};

View File

@ -0,0 +1,18 @@
/* 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/>.
*/
export default from './dropdown';

View File

@ -0,0 +1,17 @@
// 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/>.
export default from './labelComponent';

View File

@ -0,0 +1,24 @@
/* 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/>.
*/
.container {
.label {
color: rgba(0, 0, 0, 0.3);
pointer-events: none;
user-select: none;
}
}

View File

@ -0,0 +1,44 @@
// 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/>.
import React, { PropTypes } from 'react';
import styles from './labelComponent.css';
export default function LabelComponent ({ children, label }) {
return (
<div className={ styles.container }>
{
label
? (
<label
className={ styles.label }
htmlFor=''
>
{ label }
</label>
)
: null
}
{ children }
</div>
);
}
LabelComponent.propTypes = {
label: PropTypes.node,
children: PropTypes.node.isRequired
};

View File

@ -15,7 +15,6 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>. /* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/ */
.form { .form {
margin-top: -1em;
width: 100%; width: 100%;
} }

View File

@ -17,6 +17,7 @@
export AddressSelect from './AddressSelect'; export AddressSelect from './AddressSelect';
export Checkbox from './Checkbox'; export Checkbox from './Checkbox';
export DappUrlInput from './DappUrlInput'; export DappUrlInput from './DappUrlInput';
export Dropdown from './Dropdown';
export FileSelect from './FileSelect'; export FileSelect from './FileSelect';
export FormWrap from './FormWrap'; export FormWrap from './FormWrap';
export Input from './Input'; export Input from './Input';

View File

@ -33,7 +33,7 @@ export DappIcon from './DappIcon';
export DappLink from './DappLink'; export DappLink from './DappLink';
export Errors from './Errors'; export Errors from './Errors';
export Features, { FEATURES, FeaturesStore } from './Features'; export Features, { FEATURES, FeaturesStore } from './Features';
export Form, { AddressSelect, Checkbox, DappUrlInput, FileSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputDate, InputInline, InputTime, Label, RadioButtons, Select, TypedInput, VaultSelect } from './Form'; export Form, { AddressSelect, Checkbox, DappUrlInput, Dropdown, FileSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputDate, InputInline, InputTime, Label, RadioButtons, Select, TypedInput, VaultSelect } from './Form';
export GasPriceEditor from './GasPriceEditor'; export GasPriceEditor from './GasPriceEditor';
export GasPriceSelector from './GasPriceSelector'; export GasPriceSelector from './GasPriceSelector';
export IconCache from './IconCache'; export IconCache from './IconCache';

View File

@ -38,7 +38,7 @@ function render () {
return component; return component;
} }
describe('modals/Shapeshift/AwaitingDepositStep', () => { describe('views/Account/Shapeshift/AwaitingDepositStep', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -33,7 +33,7 @@ function render () {
return component; return component;
} }
describe('modals/Shapeshift/AwaitingExchangeStep', () => { describe('views/Account/Shapeshift/AwaitingExchangeStep', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -34,7 +34,7 @@ function render () {
return component; return component;
} }
describe('modals/Shapeshift/CompletedStep', () => { describe('views/Account/Shapeshift/CompletedStep', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -33,7 +33,7 @@ function render () {
return component; return component;
} }
describe('modals/Shapeshift/ErrorStep', () => { describe('views/Account/Shapeshift/ErrorStep', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -14,12 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { MenuItem } from 'material-ui';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Checkbox, Form, Input, Select, Warning } from '~/ui'; import { Checkbox, Dropdown, Form, Input, Warning } from '~/ui';
import Price from '../Price'; import Price from '../Price';
import { WARNING_NO_PRICE } from '../store'; import { WARNING_NO_PRICE } from '../store';
@ -41,7 +40,8 @@ export default class OptionsStep extends Component {
}; };
render () { render () {
const { coinSymbol, coins, hasAcceptedTerms, price, refundAddress, warning } = this.props.store; const { coinSymbol, hasAcceptedTerms, price, refundAddress, warning } = this.props.store;
let { coins } = this.props.store;
if (!coins.length) { if (!coins.length) {
return ( return (
@ -54,10 +54,12 @@ export default class OptionsStep extends Component {
); );
} }
coins = coins.map(this.renderCoinSelectItem);
return ( return (
<div className={ styles.body }> <div className={ styles.body }>
<Form> <Form>
<Select <Dropdown
className={ styles.coinselector } className={ styles.coinselector }
hint={ hint={
<FormattedMessage <FormattedMessage
@ -71,13 +73,10 @@ export default class OptionsStep extends Component {
defaultMessage='fund account from' defaultMessage='fund account from'
/> />
} }
options={ coins }
onChange={ this.onSelectCoin } onChange={ this.onSelectCoin }
value={ coinSymbol } value={ coinSymbol }
> />
{
coins.map(this.renderCoinSelectItem)
}
</Select>
<Input <Input
hint={ hint={
<FormattedMessage <FormattedMessage
@ -119,40 +118,21 @@ export default class OptionsStep extends Component {
renderCoinSelectItem = (coin) => { renderCoinSelectItem = (coin) => {
const { image, name, symbol } = coin; const { image, name, symbol } = coin;
const item = ( return {
<div className={ styles.coinselect }> image,
<img text: name,
className={ styles.coinimage } value: symbol
src={ image } };
/>
<div className={ styles.coindetails }>
<div className={ styles.coinsymbol }>
{ symbol }
</div>
<div className={ styles.coinname }>
{ name }
</div>
</div>
</div>
);
return (
<MenuItem
key={ symbol }
value={ symbol }
label={ item }
>
{ item }
</MenuItem>
);
} }
onChangeRefundAddress = (event, refundAddress) => { onChangeRefundAddress = (event, refundAddress) => {
this.props.store.setRefundAddress(refundAddress); this.props.store.setRefundAddress(refundAddress);
} }
onSelectCoin = (event, index, coinSymbol) => { onSelectCoin = (event, data) => {
this.props.store.setCoinSymbol(coinSymbol); const { value } = data;
this.props.store.setCoinSymbol(value);
} }
onToggleAcceptTerms = () => { onToggleAcceptTerms = () => {

View File

@ -38,7 +38,7 @@ function render () {
return component; return component;
} }
describe('modals/Shapeshift/OptionsStep', () => { describe('views/Account/Shapeshift/OptionsStep', () => {
beforeEach(() => { beforeEach(() => {
render(); render();
}); });
@ -103,7 +103,7 @@ describe('modals/Shapeshift/OptionsStep', () => {
}); });
it('sets the coinSymbol on the store', () => { it('sets the coinSymbol on the store', () => {
instance.onSelectCoin(null, 0, 'XMR'); instance.onSelectCoin(null, { value: 'XMR' });
expect(store.setCoinSymbol).to.have.been.calledWith('XMR'); expect(store.setCoinSymbol).to.have.been.calledWith('XMR');
}); });
}); });

View File

@ -34,7 +34,7 @@ function render (props = {}) {
return component; return component;
} }
describe('modals/Shapeshift/Price', () => { describe('views/Account/Shapeshift/Price', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -29,7 +29,7 @@ function render (props = {}) {
return component; return component;
} }
describe('modals/Shapeshift/Value', () => { describe('views/Account/Shapeshift/Value', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });

View File

@ -42,7 +42,7 @@ function render (props = {}) {
return component; return component;
} }
describe('modals/Shapeshift', () => { describe('views/Account/Shapeshift', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(render()).to.be.ok; expect(render()).to.be.ok;
}); });