1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 11:22:43 +02:00

Add tx list-item component (#8195)

* Add tx list-item component

New list item compoent for transaction history

* Simplify component logic and remove type checks

* Address remaining feedback

* Remove extra line

* Place className prop on its own line

* Rename to primaryCurrency and secondaryCurrency

* Make the title `isRequired`

* Fix no-undef

* Remove more + buttons to be implemented in seperate PR

* Add minimal store and I18nProvider to storybook

* Use Component to support translations

* Add `metamask` to store

* Rename decorator
This commit is contained in:
ricky 2020-03-17 15:15:53 -04:00 committed by GitHub
parent 4d38a59182
commit 8ba35f673e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 283 additions and 5 deletions

View File

@ -1,7 +1,11 @@
import React from 'react'
import { addDecorator, addParameters } from '@storybook/react'
import { withKnobs } from '@storybook/addon-knobs/react'
import I18nProvider from '../ui/app/helpers/higher-order-components/i18n-provider'
import { Provider } from 'react-redux'
import configureStore from '../ui/app/store/store'
import '../ui/app/css/index.scss'
import en from '../app/_locales/en/messages'
addParameters({
backgrounds: [
@ -17,11 +21,24 @@ const styles = {
alignItems: 'center',
}
const CenterDecorator = story => (
<div style={styles}>
{ story() }
</div>
const store = configureStore({
metamask: { metamask: { currentLocale: 'en' } },
localeMessages: {
current: en,
en: en,
},
})
const metamaskDecorator = story => (
<Provider store={store}>
<I18nProvider>
<div style={styles}>
{ story() }
</div>
</I18nProvider>
</Provider>
)
addDecorator(withKnobs)
addDecorator(CenterDecorator)
addDecorator(metamaskDecorator)

View File

@ -0,0 +1,3 @@
import ListItem from './list-item.component'
export default ListItem

View File

@ -0,0 +1,64 @@
.list-item {
width: 100%;
min-width: 374px;
min-height: 86px;
margin: 0 20px;
background: #FFFFFF;
padding: 24px 16px;
@extend %font;
border-top: 1px solid $mercury;
border-bottom: 1px solid $mercury;
color: $Grey-500;
display: flex;
justify-content: flex-start;
align-items: stretch;
&__icon {
margin: 8px 14px 0 0;
}
&__col {
align-self: flex-start;
}
&__heading {
font-size: 16px;
line-height: 160%;
position: relative;
&-wrap {
display: inline-block;
position: absolute;
top: 2px;
width: 16px;
height: 16px;
margin-left: 8px;
}
}
&__subheading {
font-size: 12px;
line-height: 14px;
}
&__status {
&--unapproved {
color: $flamingo;
}
&--failed {
color: $valencia;
}
}
&__approved {
.list-item__heading {
color: $shark;
}
}
&__amount {
margin: 0 0 0 auto;
text-align: right;
}
}

View File

@ -0,0 +1,138 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Approve from '../icon/approve-icon.component'
import Interaction from '../icon/interaction-icon.component'
import Preloader from '../icon/preloader'
import Send from '../icon/send-icon.component'
import classnames from 'classnames'
const SendIcon = () => (
<Send
className="list-item__icon"
size={28}
color="#2F80ED"
/>
)
const InteractionIcon = () => (
<Interaction
className="list-item__icon"
size={28}
color="#2F80ED"
/>
)
const ApproveIcon = () => (
<Approve
className="list-item__icon"
size={28}
color="#2F80ED"
/>
)
const FailIcon = () => (
<Interaction
className="list-item__icon"
size={28}
color="#D73A49"
/>
)
export default class ListItem extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
className: PropTypes.string,
status: PropTypes.string,
title: PropTypes.string.isRequired,
subtitle: PropTypes.string,
children: PropTypes.node,
primaryCurrency: PropTypes.string,
secondaryCurrency: PropTypes.string,
}
static defaultProps = {
status: 'pending',
}
render () {
const {
className,
status,
title,
subtitle,
children,
primaryCurrency,
secondaryCurrency,
} = this.props
const { t } = this.context
const isApproved = status === 'approved'
const isUnapproved = status === 'unapproved'
const isPending = status === 'pending'
const isFailed = status === 'failed'
let icon = <InteractionIcon />
if (isApproved) {
icon = <ApproveIcon />
} else if (isPending) {
icon = <SendIcon />
} else if (isFailed) {
icon = <FailIcon />
}
let subtitleStatus = null
if (isUnapproved) {
subtitleStatus = (
<span><span className="list-item__status--unapproved">{t('unapproved')}</span> · </span>
)
} else if (isFailed) {
subtitleStatus = (
<span><span className="list-item__status--failed">{t('failed')}</span> · </span>
)
}
return (
<div className={className}>
<div className="list-item__col">
{ icon }
</div>
<div
className={classnames('list-item__col', {
'list-item__approved': isApproved,
})}
>
<h2 className="list-item__heading">
{ title } {isPending && (
<span className="list-item__heading-wrap">
<Preloader
size={16}
color="#D73A49"
/>
</span>
)}
</h2>
<h3 className="list-item__subheading">
{subtitleStatus}
{subtitle}
</h3>
{children && (
<div className="list-item__more">
{ children }
</div>
)}
</div>
<div
className={classnames('list-item__col list-item__amount', {
'list-item__approved': isApproved,
})}
>
<h2 className="list-item__heading">{primaryCurrency}</h2>
<h3 className="list-item__subheading">{secondaryCurrency}</h3>
</div>
</div>
)
}
}

View File

@ -0,0 +1,51 @@
import React from 'react'
import ListItem from './list-item.component'
import { text } from '@storybook/addon-knobs/react'
export default {
title: 'ListItem',
}
export const send = () => (
<ListItem
title={text('title', 'Send DAI')}
className="list-item"
status="pending"
subtitle={text('subtitle', 'Sept 20 · To: 00X4...3058')}
primaryCurrency={text('primaryCurrency', '- 0.0732 DAI')}
secondaryCurrency={text('secondaryCurrency', '- $6.04 USD')}
/>
)
export const pending = () => (
<ListItem
title={text('title', 'Hatch Turtles')}
className="list-item"
status="unapproved"
subtitle={text('subtitle', 'Turtlefarm.com')}
primaryCurrency={text('primaryCurrency', '- 0.0732 ETH')}
secondaryCurrency={text('secondaryCurrency', '- $6.00 USD')}
/>
)
export const approve = () => (
<ListItem
title={text('title', 'Approve spend limit')}
className="list-item"
status="approved"
subtitle={text('subtitle', 'Sept 20 · oxuniverse.com')}
primaryCurrency={text('primaryCurrency', '0.00070 DAI')}
secondaryCurrency={text('secondaryCurrency', '$0.02 USD')}
/>
)
export const failed = () => (
<ListItem
title={text('title', 'Hatch Turtles')}
className="list-item"
status="failed"
subtitle={text('subtitle', 'Turtlefarm.com')}
primaryCurrency={text('primaryCurrency', '- 0.0732 ETH')}
secondaryCurrency={text('secondaryCurrency', '- $6.00 USD')}
/>
)

View File

@ -1,6 +1,7 @@
@import '../../../components/ui/button/buttons';
@import '../../../components/ui/dialog/dialog';
@import '../../../components/ui/snackbar/index';
@import '../../../components/ui/list-item/index';
@import '../../../components/ui/icon/preloader/index';
@import './footer.scss';

View File

@ -17,6 +17,8 @@ $white-linen: #faf6f0; // formerly 'faint orange (textfield shades)'
$rajah: #f5c26d; // formerly 'light orange (button shades)'
$buttercup: #f5a623; // formerly 'dark orange (text)'
$tundora: #4a4a4a; // formerly 'borders/font/any gray'
$flamingo: #F56821;
$valencia: #D73A49;
$gallery: #efefef;
$alabaster: #f7f7f7;
$shark: #22232c;
@ -60,6 +62,8 @@ $polar: #fafcfe;
$blizzard-blue: #bfdef3;
$mischka: #dddee9;
$web-orange: #f2a202;
$mercury: #E5E5E5;
$lochmara: #037DD6;
/*
notification and error message colors