mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Add tabs support for PageContainer
This commit is contained in:
parent
f30b726df7
commit
01c0c98501
@ -665,7 +665,7 @@ describe('MetaMask', function () {
|
||||
})
|
||||
|
||||
it('picks the newly created Test token', async () => {
|
||||
const addCustomToken = await findElement(driver, By.xpath("//div[contains(text(), 'Custom Token')]"))
|
||||
const addCustomToken = await findElement(driver, By.xpath("//li[contains(text(), 'Custom Token')]"))
|
||||
await addCustomToken.click()
|
||||
await delay(regularDelayMs)
|
||||
|
||||
|
@ -109,7 +109,7 @@
|
||||
|
||||
&--selected {
|
||||
color: $curious-blue;
|
||||
border-bottom: 3px solid $curious-blue;
|
||||
border-bottom: 2px solid $curious-blue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
export default class PageContainerHeader extends Component {
|
||||
|
||||
static propTypes = {
|
||||
title: PropTypes.string,
|
||||
subtitle: PropTypes.string,
|
||||
@ -11,8 +11,18 @@ export default class PageContainerHeader extends Component {
|
||||
onBackButtonClick: PropTypes.func,
|
||||
backButtonStyles: PropTypes.object,
|
||||
backButtonString: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
tabs: PropTypes.node,
|
||||
}
|
||||
|
||||
renderTabs () {
|
||||
const { tabs } = this.props
|
||||
|
||||
return tabs && (
|
||||
<ul className="page-container__tabs">
|
||||
{ tabs }
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
renderHeaderRow () {
|
||||
const { showBackButton, onBackButtonClick, backButtonStyles, backButtonString } = this.props
|
||||
@ -31,15 +41,18 @@ export default class PageContainerHeader extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { title, subtitle, onClose, children } = this.props
|
||||
const { title, subtitle, onClose, tabs } = this.props
|
||||
|
||||
return (
|
||||
<div className="page-container__header">
|
||||
<div className={
|
||||
classnames(
|
||||
'page-container__header',
|
||||
tabs && 'page-container__header--no-padding-bottom'
|
||||
)
|
||||
}>
|
||||
|
||||
{ this.renderHeaderRow() }
|
||||
|
||||
{ children }
|
||||
|
||||
{
|
||||
title && <div className="page-container__title">
|
||||
{ title }
|
||||
@ -59,6 +72,7 @@ export default class PageContainerHeader extends Component {
|
||||
/>
|
||||
}
|
||||
|
||||
{ this.renderTabs() }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -5,26 +5,93 @@ import PageContainerHeader from './page-container-header'
|
||||
import PageContainerFooter from './page-container-footer'
|
||||
|
||||
export default class PageContainer extends Component {
|
||||
|
||||
static propTypes = {
|
||||
// PageContainerHeader props
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string,
|
||||
backButtonString: PropTypes.string,
|
||||
backButtonStyles: PropTypes.object,
|
||||
onBackButtonClick: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
showBackButton: PropTypes.bool,
|
||||
onBackButtonClick: PropTypes.func,
|
||||
backButtonStyles: PropTypes.object,
|
||||
backButtonString: PropTypes.string,
|
||||
subtitle: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
// Tabs-related props
|
||||
defaultActiveTabIndex: PropTypes.number,
|
||||
tabsComponent: PropTypes.node,
|
||||
// Content props
|
||||
ContentComponent: PropTypes.func,
|
||||
contentComponentProps: PropTypes.object,
|
||||
contentComponent: PropTypes.node,
|
||||
// PageContainerFooter props
|
||||
onCancel: PropTypes.func,
|
||||
cancelText: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
onCancel: PropTypes.func,
|
||||
onSubmit: PropTypes.func,
|
||||
submitText: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
|
||||
state = {
|
||||
activeTabIndex: 0,
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const { defaultActiveTabIndex } = this.props
|
||||
|
||||
if (defaultActiveTabIndex) {
|
||||
this.setState({ activeTabIndex: defaultActiveTabIndex })
|
||||
}
|
||||
}
|
||||
|
||||
handleTabClick (tabIndex) {
|
||||
const { activeTabIndex } = this.state
|
||||
|
||||
if (tabIndex !== activeTabIndex) {
|
||||
this.setState({
|
||||
activeTabIndex: tabIndex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
renderTabs () {
|
||||
const { tabsComponent } = this.props
|
||||
|
||||
if (!tabsComponent) {
|
||||
return
|
||||
}
|
||||
|
||||
const numberOfTabs = React.Children.count(tabsComponent.props.children)
|
||||
|
||||
return React.Children.map(tabsComponent.props.children, (child, index) => {
|
||||
return child && React.cloneElement(child, {
|
||||
onClick: index => this.handleTabClick(index),
|
||||
tabIndex: index,
|
||||
isActive: numberOfTabs > 1 && index === this.state.activeTabIndex,
|
||||
key: index,
|
||||
className: 'page-container__tab',
|
||||
activeClassName: 'page-container__tab--selected',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
renderActiveTabContent () {
|
||||
const { tabsComponent } = this.props
|
||||
const { children } = tabsComponent.props
|
||||
const { activeTabIndex } = this.state
|
||||
|
||||
return children[activeTabIndex]
|
||||
? children[activeTabIndex].props.children
|
||||
: children.props.children
|
||||
}
|
||||
|
||||
renderContent () {
|
||||
const { contentComponent, tabsComponent } = this.props
|
||||
|
||||
switch (true) {
|
||||
case Boolean(contentComponent):
|
||||
return contentComponent
|
||||
case Boolean(tabsComponent):
|
||||
return this.renderActiveTabContent()
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
@ -35,8 +102,6 @@ export default class PageContainer extends Component {
|
||||
onBackButtonClick,
|
||||
backButtonStyles,
|
||||
backButtonString,
|
||||
ContentComponent,
|
||||
contentComponentProps,
|
||||
onCancel,
|
||||
cancelText,
|
||||
onSubmit,
|
||||
@ -54,9 +119,10 @@ export default class PageContainer extends Component {
|
||||
onBackButtonClick={onBackButtonClick}
|
||||
backButtonStyles={backButtonStyles}
|
||||
backButtonString={backButtonString}
|
||||
tabs={this.renderTabs()}
|
||||
/>
|
||||
<div className="page-container__content">
|
||||
<ContentComponent { ...contentComponentProps } />
|
||||
{ this.renderContent() }
|
||||
</div>
|
||||
<PageContainerFooter
|
||||
onCancel={onCancel}
|
||||
@ -68,5 +134,4 @@ export default class PageContainer extends Component {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { Component } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import PropTypes from 'prop-types'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import { checkExistingAddresses } from './util'
|
||||
import { tokenInfoGetter } from '../../../token-util'
|
||||
import { DEFAULT_ROUTE, CONFIRM_ADD_TOKEN_ROUTE } from '../../../routes'
|
||||
import Button from '../../button'
|
||||
import TextField from '../../text-field'
|
||||
import TokenList from './token-list'
|
||||
import TokenSearch from './token-search'
|
||||
import PageContainer from '../../page-container'
|
||||
import { Tabs, Tab } from '../../tabs'
|
||||
|
||||
const emptyAddr = '0x0000000000000000000000000000000000000000'
|
||||
const SEARCH_TAB = 'SEARCH'
|
||||
@ -285,65 +285,33 @@ class AddToken extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderTabs () {
|
||||
return (
|
||||
<Tabs>
|
||||
<Tab name={this.context.t('search')}>
|
||||
{ this.renderSearchToken() }
|
||||
</Tab>
|
||||
<Tab name={this.context.t('customToken')}>
|
||||
{ this.renderCustomTokenForm() }
|
||||
</Tab>
|
||||
</Tabs>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { displayedTab } = this.state
|
||||
const { history, clearPendingTokens } = this.props
|
||||
|
||||
return (
|
||||
<div className="page-container">
|
||||
<div className="page-container__header page-container__header--no-padding-bottom">
|
||||
<div className="page-container__title">
|
||||
{ this.context.t('addTokens') }
|
||||
</div>
|
||||
<div className="page-container__tabs">
|
||||
<div
|
||||
className={classnames('page-container__tab', {
|
||||
'page-container__tab--selected': displayedTab === SEARCH_TAB,
|
||||
})}
|
||||
onClick={() => this.setState({ displayedTab: SEARCH_TAB })}
|
||||
>
|
||||
{ this.context.t('search') }
|
||||
</div>
|
||||
<div
|
||||
className={classnames('page-container__tab', {
|
||||
'page-container__tab--selected': displayedTab === CUSTOM_TOKEN_TAB,
|
||||
})}
|
||||
onClick={() => this.setState({ displayedTab: CUSTOM_TOKEN_TAB })}
|
||||
>
|
||||
{ this.context.t('customToken') }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="page-container__content">
|
||||
{
|
||||
displayedTab === CUSTOM_TOKEN_TAB
|
||||
? this.renderCustomTokenForm()
|
||||
: this.renderSearchToken()
|
||||
}
|
||||
</div>
|
||||
<div className="page-container__footer">
|
||||
<Button
|
||||
type="default"
|
||||
large
|
||||
className="page-container__footer-button"
|
||||
onClick={() => {
|
||||
clearPendingTokens()
|
||||
history.push(DEFAULT_ROUTE)
|
||||
}}
|
||||
>
|
||||
{ this.context.t('cancel') }
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
large
|
||||
className="page-container__footer-button"
|
||||
onClick={() => this.handleNext()}
|
||||
disabled={this.hasError() || !this.hasSelected()}
|
||||
>
|
||||
{ this.context.t('next') }
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<PageContainer
|
||||
title={this.context.t('addTokens')}
|
||||
tabsComponent={this.renderTabs()}
|
||||
onSubmit={() => this.handleNext()}
|
||||
disabled={this.hasError() || !this.hasSelected()}
|
||||
onCancel={() => {
|
||||
clearPendingTokens()
|
||||
history.push(DEFAULT_ROUTE)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,13 @@ import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const Tab = props => {
|
||||
const { name, onClick, isActive, tabIndex } = props
|
||||
const { name, onClick, isActive, tabIndex, className, activeClassName } = props
|
||||
|
||||
return (
|
||||
<li
|
||||
className={classnames(
|
||||
'tab',
|
||||
isActive && 'tab--active',
|
||||
className || 'tab',
|
||||
isActive && (activeClassName || 'tab--active'),
|
||||
)}
|
||||
onClick={event => {
|
||||
event.preventDefault()
|
||||
@ -26,6 +26,8 @@ Tab.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
isActive: PropTypes.bool,
|
||||
tabIndex: PropTypes.number,
|
||||
className: PropTypes.string,
|
||||
activeClassName: PropTypes.string,
|
||||
}
|
||||
|
||||
export default Tab
|
||||
|
Loading…
Reference in New Issue
Block a user