Merge pull request #39 from andrerfneves/feature/new-round-pixel-perfecting

Feature/new round pixel perfecting
This commit is contained in:
André Neves 2019-01-17 19:25:43 -05:00 committed by GitHub
commit eea3510867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 187 additions and 22 deletions

BIN
app/assets/images/eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -57,12 +57,19 @@ const Secondary = styled(DefaultButton)`
} }
`; `;
const Icon = styled.img`
height: 9px;
width: 12px;
margin-right: 10px;
`;
type Props = { type Props = {
label: string, label: string,
onClick?: () => void, onClick?: () => void,
to?: string, to?: string,
variant?: 'primary' | 'secondary', variant?: 'primary' | 'secondary',
disabled?: boolean, disabled?: boolean,
icon?: string,
className?: string, className?: string,
isLoading?: boolean, isLoading?: boolean,
}; };
@ -73,25 +80,41 @@ export const Button = ({
to, to,
variant, variant,
disabled, disabled,
icon,
className, className,
isLoading, isLoading,
}: Props) => { }: Props) => {
if (to && onClick) throw new Error('Should define either "to" or "onClick"'); if (to && onClick) throw new Error('Should define either "to" or "onClick"');
const props = { onClick, disabled: disabled || isLoading, className }; const props = {
onClick, disabled: disabled || isLoading, icon: null, className,
};
const buttonLabel = isLoading ? 'Loading...' : label; const buttonLabel = isLoading ? 'Loading...' : label;
const component = variant === 'primary' ? ( const component = variant === 'primary' ? (
<Primary {...props}>{buttonLabel}</Primary> <Primary {...props}>
{icon
? <Icon src={icon} />
: null
}
{buttonLabel}
</Primary>
) : ( ) : (
<Secondary {...props}>{buttonLabel}</Secondary> <Secondary {...props}>
{icon
? <Icon src={icon} />
: null
}
{buttonLabel}
</Secondary>
); );
return to ? <Link to={String(to)}>{component}</Link> : component; return to ? <Link to={String(to)}>{component}</Link> : component;
}; };
Button.defaultProps = { Button.defaultProps = {
to: null, to: '',
icon: null,
variant: 'primary', variant: 'primary',
onClick: null, onClick: null,
disabled: false, disabled: false,

View File

@ -9,6 +9,8 @@ import ClickOutside from 'react-click-outside';
import { TextComponent } from './text'; import { TextComponent } from './text';
import truncateAddress from '../utils/truncateAddress';
/* eslint-disable max-len */ /* eslint-disable max-len */
const MenuWrapper = styled.div` const MenuWrapper = styled.div`
background-image: ${props => `linear-gradient(to right, ${darken( background-image: ${props => `linear-gradient(to right, ${darken(
@ -18,6 +20,7 @@ const MenuWrapper = styled.div`
border-radius: ${props => props.theme.boxBorderRadius}; border-radius: ${props => props.theme.boxBorderRadius};
margin-left: -10px; margin-left: -10px;
max-width: 400px; max-width: 400px;
overflow: hidden;
`; `;
const MenuItem = styled.button` const MenuItem = styled.button`
@ -30,6 +33,7 @@ const MenuItem = styled.button`
padding: 15px; padding: 15px;
cursor: pointer; cursor: pointer;
font-weight: 700; font-weight: 700;
overflow: hidden;
width: 100%; width: 100%;
text-align: left; text-align: left;
@ -50,6 +54,18 @@ const MenuItem = styled.button`
} }
`; `;
const OptionItem = styled(MenuItem)`
&:hover {
background-color: #F9D114;
}
`;
const Option = styled(TextComponent)`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const PopoverWithStyle = styled(Popover)` const PopoverWithStyle = styled(Popover)`
& > .Popover-tip { & > .Popover-tip {
fill: ${props => props.theme.colors.activeItem}; fill: ${props => props.theme.colors.activeItem};
@ -60,6 +76,7 @@ type Props = {
renderTrigger: (toggleVisibility: () => void, isOpen: boolean) => Node, renderTrigger: (toggleVisibility: () => void, isOpen: boolean) => Node,
options: Array<{ label: string, onClick: () => void }>, options: Array<{ label: string, onClick: () => void }>,
label?: string | null, label?: string | null,
truncate?: boolean,
}; };
type State = { type State = {
@ -73,11 +90,14 @@ export class DropdownComponent extends Component<Props, State> {
static defaultProps = { static defaultProps = {
label: null, label: null,
truncate: false,
}; };
render() { render() {
const { isOpen } = this.state; const { isOpen } = this.state;
const { label, options, renderTrigger } = this.props; const {
label, options, truncate, renderTrigger,
} = this.props;
const body = [ const body = [
<ClickOutside <ClickOutside
@ -90,9 +110,9 @@ export class DropdownComponent extends Component<Props, State> {
</MenuItem> </MenuItem>
)} )}
{options.map(({ label: optionLabel, onClick }) => ( {options.map(({ label: optionLabel, onClick }) => (
<MenuItem onClick={onClick} key={optionLabel}> <OptionItem onClick={onClick} key={optionLabel}>
<TextComponent value={optionLabel} /> <Option value={truncate ? truncateAddress(optionLabel) : optionLabel} />
</MenuItem> </OptionItem>
))} ))}
</MenuWrapper> </MenuWrapper>
</ClickOutside>, </ClickOutside>,

View File

@ -0,0 +1,103 @@
// @flow
import React, { Component } from 'react';
import styled from 'styled-components';
import { ColumnComponent } from './column';
import { Button } from './button';
import { QRCode } from './qrcode';
import truncateAddress from '../utils/truncateAddress';
import eyeIcon from '../assets/images/eye.png';
const AddressWrapper = styled.div`
align-items: center;
display: flex;
background-color: #000;
border-radius: 6px;
padding: 7px 13px;
width: 100%;
`;
const Input = styled.input`
border-radius: ${props => props.theme.boxBorderRadius};
border: none;
background-color: ${props => props.theme.colors.inputBackground};
color: ${props => props.theme.colors.text};
padding: 15px;
width: 100%;
outline: none;
font-family: ${props => props.theme.fontFamily};
::placeholder {
opacity: 0.5;
}
`;
const QRCodeWrapper = styled.div`
align-items: center;
display: flex;
background-color: #000;
border-radius: 6px;
padding: 20px;
margin-top: 10px;
width: 100%;
`;
type Props = {
address: string,
};
type State = {
isVisible: boolean,
};
export class WalletAddress extends Component<Props, State> {
state = {
isVisible: false,
};
show = () => {
this.setState(
() => ({ isVisible: true }),
);
};
hide = () => {
this.setState(
() => ({ isVisible: false }),
);
};
render() {
const { address } = this.props;
const { isVisible } = this.state;
const toggleVisibility = isVisible ? this.hide : this.show;
return (
<ColumnComponent width='100%'>
<AddressWrapper>
<Input
value={isVisible ? address : truncateAddress(address)}
onChange={() => {}}
onFocus={event => event.currentTarget.select()}
/>
<Button
icon={eyeIcon}
label={`${isVisible ? 'Hide' : 'Show'} full address and QR Code`}
onClick={toggleVisibility}
variant='secondary'
/>
</AddressWrapper>
{isVisible
? (
<QRCodeWrapper>
<QRCode value={address} />
</QRCodeWrapper>
)
: null}
</ColumnComponent>
);
}
}

View File

@ -0,0 +1,28 @@
---
name: Wallet Address
---
import { Playground, PropsTable } from 'docz'
import { WalletAddress } from './wallet-address.js'
import { DoczWrapper } from '../theme.js'
# Wallet Address
## Properties
<PropsTable of={WalletAddress} />
## Basic usage
<Playground>
<DoczWrapper>
{() => (
<div style={{ width: '700px' }}>
<WalletAddress
address='t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1'
/>
</div>
)}
</DoczWrapper>
</Playground>

View File

@ -7,11 +7,11 @@ import { normalize } from 'polished'; // eslint-disable-line
import { DARK } from './constants/themes'; import { DARK } from './constants/themes';
const darkOne = '#7B00DD'; const darkOne = '#F4B728';
const lightOne = '#ffffff'; const lightOne = '#ffffff';
const brandOne = '#000'; const brandOne = '#000';
const brandTwo = '#3B3B3F'; const brandTwo = '#3B3B3F';
const activeItem = '#F5CB00'; const activeItem = '#F4B728';
const text = '#FFF'; const text = '#FFF';
const cardBackgroundColor = '#000'; const cardBackgroundColor = '#000';
const sidebarLogoGradientBegin = '#F4B728'; const sidebarLogoGradientBegin = '#F4B728';

View File

@ -3,10 +3,8 @@ import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { InputLabelComponent } from '../components/input-label'; import { InputLabelComponent } from '../components/input-label';
import { InputComponent } from '../components/input';
import { QRCode } from '../components/qrcode';
import { RowComponent } from '../components/row'; import { RowComponent } from '../components/row';
import { ColumnComponent } from '../components/column'; import { WalletAddress } from '../components/wallet-address';
type Props = { type Props = {
addresses: Array<string>, addresses: Array<string>,
@ -27,21 +25,14 @@ const Label = styled(InputLabelComponent)`
export const ReceiveView = ({ addresses }: Props) => ( export const ReceiveView = ({ addresses }: Props) => (
<Wrapper> <Wrapper>
<Label value='Addresses: ' />
{(addresses || []).map(address => ( {(addresses || []).map(address => (
<Row <Row
key={address} key={address}
alignItems='center' alignItems='center'
justifyContent='space-between' justifyContent='space-between'
> >
<ColumnComponent width='85%'> <WalletAddress address={address} />
<Label value='Your Address: ' />
<InputComponent
value={address}
onChange={() => {}}
onFocus={event => event.currentTarget.select()}
/>
</ColumnComponent>
<QRCode value={address} />
</Row> </Row>
))} ))}
</Wrapper> </Wrapper>