Better display of tags (#4564)

* WIP

* Update accounts on whitelist change in Parity Bar

* Fix AccountCard width in Parity Bar (Signer)

* Added AccountCard Example

* Use horizontal tags

* Better Tags display

* Scrollable tags

* Update PR Grumbles

* Fix tests (add tags)

* PR Grumble
This commit is contained in:
Nicolas Gotchac 2017-02-16 17:42:19 +01:00 committed by Gav Wood
parent 00c843afea
commit b825c8e074
12 changed files with 262 additions and 49 deletions

View File

@ -126,6 +126,7 @@ export default class Personal {
case 'parity_setDappsAddresses':
case 'parity_setNewDappsWhitelist':
this._defaultAccount(true);
this._listAccounts();
return;
}
});

View File

@ -74,7 +74,7 @@ $codeColor: #93a1a1;
flex: 1;
overflow: auto;
padding: 0.5em;
background-color: #$codeBackground;
background-color: $codeBackground;
color: $codeColor;
font-size: 0.75em;
@ -86,5 +86,6 @@ $codeColor: #93a1a1;
.component {
flex: 3;
padding-left: 0.5em;
overflow: auto;
}
}

View File

@ -17,6 +17,7 @@
import { observer } from 'mobx-react';
import React, { Component } from 'react';
import AccountCard from '~/ui/AccountCard/accountCard.example';
import CurrencySymbol from '~/ui/CurrencySymbol/currencySymbol.example';
import QrCode from '~/ui/QrCode/qrCode.example';
import SectionList from '~/ui/SectionList/sectionList.example';
@ -25,6 +26,7 @@ import Portal from '~/ui/Portal/portal.example';
import PlaygroundStore from './store';
import styles from './playground.css';
PlaygroundStore.register(<AccountCard />);
PlaygroundStore.register(<CurrencySymbol />);
PlaygroundStore.register(<QrCode />);
PlaygroundStore.register(<SectionList />);

View File

@ -16,18 +16,14 @@
*/
.account {
padding: 1em;
margin: 0.5em 0;
display: flex;
flex-direction: column;
align-items: flex-start;
align-items: stretch;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: row;
margin: 0.5em 0;
overflow: hidden;
transition: transform ease-out 0.1s;
transform: scale(1);
overflow: hidden;
&.copied {
animation-duration: 0.25s;
@ -53,6 +49,38 @@
}
}
.mainContainer {
flex: 1 1 auto;
overflow: hidden;
padding: 1em;
}
.tagsContainer {
flex: 0 0 auto;
position: relative;
width: 3em;
}
.tags {
background-color: rgba(0, 0, 0, 0.4);
box-sizing: content-box;
height: calc(100% - 0.5em);
overflow-x: hidden;
overflow-y: scroll;
padding: 0.25em;
padding-right: 2em;
position: absolute;
right: -2.5em;
transition: background-color 0.2s ease-out;
width: calc(100% + 0.25em);
&:hover {
background-color: rgba(0, 0, 0, 0.8);
padding-left: 0.5em;
width: auto;
}
}
.infoContainer {
display: flex;
flex-direction: row;

View File

@ -0,0 +1,110 @@
// 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, { Component } from 'react';
import PlaygroundExample from '~/playground/playgroundExample';
import AccountCard from './accountCard';
export default class AccountCardExample extends Component {
render () {
const account = {
address: '0x639ba260535db072a41115c472830846e4e9ad0f',
description: 'This is a description for the main account',
meta: {
tags: [ 'important', 'zargo' ]
},
name: 'Main Account'
};
const balance = {
tokens: [
{
value: 100000000000000000000,
token: {
tag: 'ETH'
}
}
]
};
const accountManyTags = {
...account,
meta: { tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => `tag #${n}`) }
};
const accountNoTags = {
...account,
meta: { tags: [] }
};
return (
<div>
<PlaygroundExample name='Standard Account Card'>
<AccountCard
account={ account }
balance={ balance }
/>
</PlaygroundExample>
<PlaygroundExample name='Small Account Card'>
<div style={ { width: 300 } }>
<AccountCard
account={ account }
balance={ balance }
/>
</div>
</PlaygroundExample>
<PlaygroundExample name='Many Tags Account Card'>
<div style={ { width: 300 } }>
<AccountCard
account={ accountManyTags }
balance={ balance }
/>
</div>
</PlaygroundExample>
<PlaygroundExample name='No Tags Account Card'>
<div style={ { width: 300 } }>
<AccountCard
account={ accountNoTags }
balance={ balance }
/>
</div>
</PlaygroundExample>
<PlaygroundExample name='Two Account Card'>
<div style={ { display: 'flex' } }>
<div style={ { margin: '0 0.5em' } }>
<AccountCard
account={ account }
balance={ balance }
/>
</div>
<div style={ { margin: '0 0.5em' } }>
<AccountCard
account={ account }
balance={ balance }
/>
</div>
</div>
</PlaygroundExample>
</div>
);
}
}

View File

@ -58,28 +58,45 @@ export default class AccountCard extends Component {
onFocus={ this.onFocus }
onKeyDown={ this.handleKeyDown }
>
<div className={ styles.infoContainer }>
<IdentityIcon address={ address } />
<div className={ styles.accountInfo }>
<div className={ styles.accountName }>
<IdentityName
address={ address }
name={ name }
unknown
/>
<div className={ styles.mainContainer }>
<div className={ styles.infoContainer }>
<IdentityIcon address={ address } />
<div className={ styles.accountInfo }>
<div className={ styles.accountName }>
<IdentityName
address={ address }
name={ name }
unknown
/>
</div>
{ this.renderDescription(description) }
{ this.renderAddress(address) }
</div>
{ this.renderDescription(description) }
{ this.renderAddress(address) }
</div>
<Balance
balance={ balance }
className={ styles.balance }
showOnlyEth
showZeroValues
/>
</div>
<Tags tags={ tags } />
<Balance
balance={ balance }
className={ styles.balance }
showOnlyEth
showZeroValues
/>
{
tags && tags.length > 0
? (
<div className={ styles.tagsContainer }>
<div className={ styles.tags }>
<Tags
floating={ false }
horizontal
tags={ tags }
/>
</div>
</div>
) : null
}
</div>
);
}

View File

@ -33,7 +33,9 @@ function render (props = {}) {
address: TEST_ADDRESS,
description: 'testDescription',
name: TEST_NAME,
meta: {}
meta: {
tags: [ 'tag 1', 'tag 2' ]
}
};
}

View File

@ -18,16 +18,39 @@
.tags {
display: flex;
flex-wrap: wrap;
position: absolute;
right: 0.25rem;
top: 0;
&.floating {
position: absolute;
right: 0.25rem;
top: 0;
}
&.horizontal {
flex-direction: column;
}
}
.floating .tag {
margin-top: 0.75em;
}
.horizontal .tag {
margin: 0.25em 0;
.text {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 150%;
}
}
.tag {
font-size: 0.75rem;
background: rgba(255, 255, 255, 0.07);
border-radius: 16px;
margin: 0.75em 0.5em 0 0;
margin: 0 0.5em;
padding: 0.25em 1em;
opacity: 1;
transition: opacity 0.2s ease-out;

View File

@ -22,20 +22,37 @@ import styles from './tags.css';
export default class Tags extends Component {
static propTypes = {
floating: PropTypes.bool,
horizontal: PropTypes.bool,
handleAddSearchToken: PropTypes.func,
setRefs: PropTypes.func,
tags: arrayOrObjectProptype()
}
};
static defaultProps = {
horizontal: false,
floating: true
};
render () {
const { tags } = this.props;
const { floating, horizontal, tags } = this.props;
if (!tags || tags.length === 0) {
return null;
}
const classes = [ styles.tags ];
if (floating) {
classes.push(styles.floating);
}
if (horizontal) {
classes.push(styles.horizontal);
}
return (
<div className={ styles.tags }>
<div className={ classes.join(' ') }>
{ this.renderTags() }
</div>
);
@ -66,7 +83,7 @@ export default class Tags extends Component {
onClick={ onClick }
ref={ setRef }
>
{ tag }
<span className={ styles.text }>{ tag }</span>
</div>
);
});

View File

@ -111,10 +111,18 @@ export default class AccountStore {
}
subscribeDefaultAccount () {
return this._api.subscribe('parity_defaultAccount', (error, defaultAccount) => {
const promiseDefaultAccount = this._api.subscribe('parity_defaultAccount', (error, defaultAccount) => {
if (!error) {
this.setDefaultAccount(defaultAccount);
}
});
const promiseEthAccounts = this._api.subscribe('eth_accounts', (error) => {
if (!error) {
this.loadAccounts();
}
});
return Promise.all([ promiseDefaultAccount, promiseEthAccounts ]);
}
}

View File

@ -84,7 +84,6 @@ $modalZ: 10001;
.parityBg {
position: fixed;
transition-property: left, top, right, bottom;
transition-duration: 0.25s;
transition-timing-function: ease;
@ -95,20 +94,25 @@ $modalZ: 10001;
}
}
.accountsSection {
padding: 0 1em;
width: 920px;
}
.expanded {
border-radius: 4px 4px 0 0;
display: flex;
flex-direction: column;
flex-direction: row;
min-height: 30vh;
max-height: 80vh;
max-width: calc(100vw - 1em);
max-width: calc(100vw - 2em);
.content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
overflow: auto;
display: flex;
background: rgba(0, 0, 0, 0.8);
max-width: calc(100vw - 2em);
}
}
@ -130,7 +134,8 @@ $modalZ: 10001;
color: white !important;
display: inline-block;
img, svg {
img,
svg {
height: 24px !important;
width: 24px !important;
margin: 2px 0.5em 0 0;
@ -160,7 +165,7 @@ $modalZ: 10001;
min-width: 2em !important;
img {
margin: 6px 0.5em 0 0.5em;
margin: 6px 0.5em 0;
}
}
@ -177,7 +182,7 @@ $modalZ: 10001;
.labelBubble {
position: absolute;
top: 0px;
top: 0;
right: -10px;
}
@ -187,7 +192,7 @@ $modalZ: 10001;
background: rgba(0, 0, 0, 0.25);
margin-bottom: 0;
&:after {
&::after {
clear: both;
}
}
@ -243,11 +248,9 @@ $modalZ: 10001;
width: 1em;
height: 1em;
margin-left: 0.5em;
background-color: white;
opacity: 0.25;
border-radius: 50%;
transition-property: opacity;
transition-duration: 0.1s;
transition-timing-function: ease-in-out;

View File

@ -328,6 +328,7 @@ class ParityBar extends Component {
displayType === DISPLAY_ACCOUNTS
? (
<SectionList
className={ styles.accountsSection }
items={ this.accountStore.accounts }
noStretch
renderItem={ this.renderAccount }