Ui 2 components cleanups (#5653)

* Add autoFocus for search

* Remove old/unused renderer

* LabelComponent -> LabelWrapper

* Consistent LabelWrapper usage
This commit is contained in:
Jaco Greeff 2017-05-18 11:48:53 +02:00 committed by GitHub
parent e0927f099e
commit 20bda5f5a0
21 changed files with 104 additions and 118 deletions

View File

@ -74,6 +74,7 @@ export default class ActionbarSearch extends Component {
<div className={ inputContainerClasses.join(' ') }> <div className={ inputContainerClasses.join(' ') }>
<InputChip <InputChip
addOnBlur addOnBlur
autoFocus
className={ styles.input } className={ styles.input }
hint={ hint={
<FormattedMessage <FormattedMessage
@ -81,7 +82,6 @@ export default class ActionbarSearch extends Component {
defaultMessage='Enter search input...' defaultMessage='Enter search input...'
/> />
} }
ref='inputChip'
tokens={ tokens } tokens={ tokens }
onBlur={ this.handleSearchBlur } onBlur={ this.handleSearchBlur }
@ -126,10 +126,6 @@ export default class ActionbarSearch extends Component {
handleSearchClick = () => { handleSearchClick = () => {
const { showSearch } = this.state; const { showSearch } = this.state;
if (!showSearch) {
this.refs.inputChip.focus();
}
this.handleOpenSearch(!showSearch); this.handleOpenSearch(!showSearch);
} }

View File

@ -90,11 +90,6 @@
position: relative; position: relative;
} }
.label {
margin: 1rem 0.5rem 0.25em;
color: rgba(255, 255, 255, 0.498039);
}
.underline { .underline {
position: relative; position: relative;
margin: 0 0.5rem 0 0.5rem; margin: 0 0.5rem 0 0.5rem;

View File

@ -29,6 +29,7 @@ import { validateAddress } from '@parity/shared/util/validation';
import AccountCard from '~/ui/AccountCard'; import AccountCard from '~/ui/AccountCard';
import CopyToClipboard from '~/ui/CopyToClipboard'; import CopyToClipboard from '~/ui/CopyToClipboard';
import InputAddress from '~/ui/Form/InputAddress'; import InputAddress from '~/ui/Form/InputAddress';
import LabelWrapper from '~/ui/Form/LabelWrapper';
import Loading from '~/ui/Loading'; import Loading from '~/ui/Loading';
import Portal from '~/ui/Portal'; import Portal from '~/ui/Portal';
@ -193,10 +194,11 @@ class AddressSelect extends Component {
onKeyDown={ this.handleKeyDown } onKeyDown={ this.handleKeyDown }
open={ expanded } open={ expanded }
title={ title={
<div className={ styles.title }> <LabelWrapper
<label className={ styles.label } htmlFor={ id }> className={ styles.title }
{ label } htmlFor={ id }
</label> label={ label }
>
<div className={ styles.outerInput }> <div className={ styles.outerInput }>
<input <input
id={ id } id={ id }
@ -217,7 +219,7 @@ class AddressSelect extends Component {
) )
} }
</div> </div>
</div> </LabelWrapper>
} }
> >
{ this.renderCurrentInput() } { this.renderCurrentInput() }

View File

@ -15,16 +15,20 @@
// 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 { Checkbox as SemCheckbox } from 'semantic-ui-react'; import { Checkbox as SemanticCheckbox } from 'semantic-ui-react';
import { nodeOrStringProptype } from '@parity/shared/util/proptypes'; import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
import LabelWrapper from '../LabelWrapper';
export default function Checkbox ({ checked = false, className, label, onClick, style }) { export default function Checkbox ({ checked = false, className, label, onClick, style }) {
return ( return (
<SemCheckbox <SemanticCheckbox
checked={ checked } checked={ checked }
className={ className } className={ className }
label={ <label>{ label }</label> } label={
<LabelWrapper label={ label } />
}
onClick={ onClick } onClick={ onClick }
style={ style } style={ style }
/> />

View File

@ -19,7 +19,7 @@ import { Dropdown as SemanticDropdown } from 'semantic-ui-react';
import { parseI18NString } from '@parity/shared/util/messages'; import { parseI18NString } from '@parity/shared/util/messages';
import LabelComponent from '../LabelComponent'; import LabelWrapper from '../LabelWrapper';
import styles from './dropdown.css'; import styles from './dropdown.css';
@ -30,7 +30,7 @@ export default function Dropdown ({ className, disabled = false, error, fullWidt
const _onChange = (event, { value }) => onChange(event, value); const _onChange = (event, { value }) => onChange(event, value);
return ( return (
<LabelComponent label={ label }> <LabelWrapper label={ label }>
<SemanticDropdown <SemanticDropdown
className={ `${styles.dropdown} ${className}` } className={ `${styles.dropdown} ${className}` }
disabled={ disabled } disabled={ disabled }
@ -49,7 +49,7 @@ export default function Dropdown ({ className, disabled = false, error, fullWidt
text={ parseI18NString(context, text) } text={ parseI18NString(context, text) }
value={ value } value={ value }
/> />
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -46,14 +46,7 @@ export default class FileSelect extends Component {
<Dropzone <Dropzone
onDrop={ this.onDrop } onDrop={ this.onDrop }
multiple={ false } multiple={ false }
className={ className={ `${styles.dropzone} ${error && styles.error} ${className}` }
[
styles.dropzone,
error
? styles.error
: '',
className
].join(' ') }
> >
<div className={ styles.label }> <div className={ styles.label }>
{ error || label } { error || label }

View File

@ -23,7 +23,7 @@ import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
import { parseI18NString } from '@parity/shared/util/messages'; import { parseI18NString } from '@parity/shared/util/messages';
import CopyToClipboard from '~/ui/CopyToClipboard'; import CopyToClipboard from '~/ui/CopyToClipboard';
import LabelComponent from '~/ui/Form/LabelComponent'; import LabelWrapper from '~/ui/Form/LabelWrapper';
import styles from './input.css'; import styles from './input.css';
@ -113,7 +113,7 @@ export default class Input extends Component {
const { value } = this.state; const { value } = this.state;
return ( return (
<LabelComponent <LabelWrapper
className={ styles.container } className={ styles.container }
label={ label } label={ label }
> >
@ -146,7 +146,7 @@ export default class Input extends Component {
<input /> <input />
{ children } { children }
</SemanticInput> </SemanticInput>
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -22,7 +22,7 @@ import { Input as SemanticInput } from 'semantic-ui-react';
import { parseI18NString } from '@parity/shared/util/messages'; import { parseI18NString } from '@parity/shared/util/messages';
import { arrayOrObjectProptype, nodeOrStringProptype } from '@parity/shared/util/proptypes'; import { arrayOrObjectProptype, nodeOrStringProptype } from '@parity/shared/util/proptypes';
import LabelComponent from '~/ui/Form/LabelComponent'; import LabelWrapper from '~/ui/Form/LabelWrapper';
import Chip from './Chip'; import Chip from './Chip';
@ -32,6 +32,7 @@ export default class InputChip extends Component {
}; };
static propTypes = { static propTypes = {
autoFocus: PropTypes.bool,
addOnBlur: PropTypes.bool, addOnBlur: PropTypes.bool,
clearOnBlur: PropTypes.bool, clearOnBlur: PropTypes.bool,
className: PropTypes.string, className: PropTypes.string,
@ -51,12 +52,13 @@ export default class InputChip extends Component {
textValue: '' textValue: ''
}; };
// TODO: autoFocus to be implemented (same as with Form/Input)
render () { render () {
const { className, hint, label, tokens } = this.props; const { className, hint, label, tokens } = this.props;
const { textValue } = this.state; const { textValue } = this.state;
return ( return (
<LabelComponent <LabelWrapper
className={ className } className={ className }
label={ label } label={ label }
> >
@ -74,7 +76,7 @@ export default class InputChip extends Component {
<div> <div>
{ tokens.map(this.renderChip) } { tokens.map(this.renderChip) }
</div> </div>
</LabelComponent> </LabelWrapper>
); );
} }
@ -90,21 +92,6 @@ export default class InputChip extends Component {
); );
} }
chipRenderer = (state, key) => {
const { isDisabled, isFocused, handleClick, handleRequestDelete, value } = state;
return (
<Chip
isDisabled={ isDisabled }
isFocused={ isFocused }
key={ key }
label={ value }
onClick={ handleClick }
onDelete={ handleRequestDelete }
/>
);
}
handleTokenAdd = (value) => { handleTokenAdd = (value) => {
const { tokens } = this.props; const { tokens } = this.props;
const newTokens = uniq([].concat(tokens, value)); const newTokens = uniq([].concat(tokens, value));

View File

@ -19,7 +19,7 @@ import DateTime from 'react-datetime';
import { parseI18NString } from '@parity/shared/util/messages'; import { parseI18NString } from '@parity/shared/util/messages';
import LabelComponent from '~/ui/Form/LabelComponent'; import LabelWrapper from '~/ui/Form/LabelWrapper';
import styles from './inputDateTime.css'; import styles from './inputDateTime.css';
@ -29,7 +29,7 @@ export default function InputDateTime ({ className, hint, label, onChange, value
const _onChange = (value) => onChange && onChange(null, value); const _onChange = (value) => onChange && onChange(null, value);
return ( return (
<LabelComponent <LabelWrapper
className={ `${styles.container} ${className}` } className={ `${styles.container} ${className}` }
label={ label } label={ label }
> >
@ -43,7 +43,7 @@ export default function InputDateTime ({ className, hint, label, onChange, value
value={ value } value={ value }
/> />
</div> </div>
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -16,21 +16,29 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
import styles from './label.css'; import styles from './label.css';
export default function Label ({ className, label }) { export default function Label ({ className, children, htmlFor, label }) {
if (!label) { if (!label && !children) {
return null; return null;
} }
return ( return (
<label className={ [styles.label, className].join(' ') }> <label
className={ `${styles.label} ${className}` }
htmlFor={ htmlFor }
>
{ label } { label }
{ children }
</label> </label>
); );
} }
Label.propTypes = { Label.propTypes = {
className: PropTypes.string, className: PropTypes.string,
label: PropTypes.node children: PropTypes.node,
htmlFor: PropTypes.string,
label: nodeOrStringProptype()
}; };

View File

@ -14,4 +14,4 @@
// 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/>.
export default from './labelComponent'; export default from './labelWrapper';

View File

@ -16,19 +16,25 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
import Label from '../Label'; import Label from '../Label';
export default function LabelComponent ({ className, children, label }) { export default function LabelWrapper ({ className, children, htmlFor, label }) {
return ( return (
<div className={ className }> <div className={ className }>
<Label label={ label } /> <Label
htmlFor={ htmlFor }
label={ label }
/>
{ children } { children }
</div> </div>
); );
} }
LabelComponent.propTypes = { LabelWrapper.propTypes = {
className: PropTypes.string, className: PropTypes.string,
children: PropTypes.node.isRequired, children: PropTypes.node,
label: PropTypes.node htmlFor: PropTypes.string,
label: nodeOrStringProptype()
}; };

View File

@ -22,10 +22,3 @@
font-size: 0.75em; font-size: 0.75em;
margin: -2em 0 1.5em 0; margin: -2em 0 1.5em 0;
} }
.label {
user-select: none;
line-height: 18px;
font-size: 12px;
color: rgba(255, 255, 255, 0.498039);
}

View File

@ -19,6 +19,7 @@ import { debounce } from 'lodash';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import zxcvbn from 'zxcvbn'; import zxcvbn from 'zxcvbn';
import LabelWrapper from '~/ui/Form/LabelWrapper';
import Progress from '~/ui/Progress'; import Progress from '~/ui/Progress';
import styles from './passwordStrength.css'; import styles from './passwordStrength.css';
@ -64,13 +65,15 @@ export default class PasswordStrength extends Component {
const { score, feedback } = strength; const { score, feedback } = strength;
return ( return (
<div className={ styles.strength }> <LabelWrapper
<label className={ styles.label }> className={ styles.strength }
label={
<FormattedMessage <FormattedMessage
id='ui.passwordStrength.label' id='ui.passwordStrength.label'
defaultMessage='password strength' defaultMessage='password strength'
/> />
</label> }
>
<Progress <Progress
color={ this.getStrengthBarColor(score) } color={ this.getStrengthBarColor(score) }
isDeterminate isDeterminate
@ -80,7 +83,7 @@ export default class PasswordStrength extends Component {
<div className={ styles.feedback }> <div className={ styles.feedback }>
{ this.renderFeedback(feedback) } { this.renderFeedback(feedback) }
</div> </div>
</div> </LabelWrapper>
); );
} }

View File

@ -15,19 +15,21 @@
// 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 { Radio } from 'semantic-ui-react'; import { Radio as SemanticRadio } from 'semantic-ui-react';
import { arrayOrObjectProptype } from '@parity/shared/util/proptypes'; import { arrayOrObjectProptype } from '@parity/shared/util/proptypes';
import LabelComponent from '../LabelComponent'; import LabelWrapper from '../LabelWrapper';
import Label from '../Label';
import styles from './radioButtons.css'; import styles from './radioButtons.css';
export default function RadioButtons ({ className, label, name, onChange, value, values }) { export default function RadioButtons ({ className, label, name, onChange, value, values }) {
const _onChange = (event, { value }) => onChange(event, value); const _onChange = (event, { value }) => onChange(event, value);
return ( return (
<LabelComponent <LabelWrapper
className={ [styles.container, className].join(' ') } className={ `${styles.container} ${className}` }
label={ label } label={ label }
> >
{ {
@ -36,12 +38,14 @@ export default function RadioButtons ({ className, label, name, onChange, value,
className={ styles.radioContainer } className={ styles.radioContainer }
key={ key } key={ key }
> >
<Radio <SemanticRadio
checked={ value === key } checked={ value === key }
className={ styles.radio } className={ styles.radio }
label={ label={
<label className={ styles.label }> <Label className={ styles.label }>
<div className={ styles.name }>{ label }</div> <div className={ styles.name }>
{ label }
</div>
{ {
description && ( description && (
<div className={ styles.description }> <div className={ styles.description }>
@ -49,7 +53,7 @@ export default function RadioButtons ({ className, label, name, onChange, value,
</div> </div>
) )
} }
</label> </Label>
} }
name={ name } name={ name }
onChange={ _onChange } onChange={ _onChange }
@ -58,7 +62,7 @@ export default function RadioButtons ({ className, label, name, onChange, value,
</div> </div>
)) ))
} }
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -17,11 +17,11 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Radio as SemanticRadio } from 'semantic-ui-react'; import { Radio as SemanticRadio } from 'semantic-ui-react';
import LabelComponent from '../LabelComponent'; import LabelWrapper from '../LabelWrapper';
export default function Toggle ({ className, label, onToggle, style, toggled }) { export default function Toggle ({ className, label, onToggle, style, toggled }) {
return ( return (
<LabelComponent label={ label }> <LabelWrapper label={ label }>
<SemanticRadio <SemanticRadio
checked={ toggled } checked={ toggled }
className={ className } className={ className }
@ -29,7 +29,7 @@ export default function Toggle ({ className, label, onToggle, style, toggled })
style={ style } style={ style }
toggle toggle
/> />
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -27,6 +27,7 @@ import Button from '~/ui/Button';
import Dropdown from '~/ui/Form/Dropdown'; import Dropdown from '~/ui/Form/Dropdown';
import Input from '~/ui/Form/Input'; import Input from '~/ui/Form/Input';
import InputAddressSelect from '~/ui/Form/InputAddressSelect'; import InputAddressSelect from '~/ui/Form/InputAddressSelect';
import LabelWrapper from '~/ui/Form/LabelWrapper';
import Toggle from '~/ui/Form/Toggle'; import Toggle from '~/ui/Form/Toggle';
import { AddIcon, RemoveIcon } from '~/ui/Icons'; import { AddIcon, RemoveIcon } from '~/ui/Icons';
@ -125,11 +126,13 @@ export default class TypedInput extends Component {
}); });
return ( return (
<div className={ styles.inputs }> <LabelWrapper
<label>{ label }</label> className={ styles.inputs }
label={ label }
>
{ fixedLength || readOnly ? null : this.renderLength() } { fixedLength || readOnly ? null : this.renderLength() }
{ inputs } { inputs }
</div> </LabelWrapper>
); );
} }

View File

@ -17,7 +17,7 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { List as SemanticList } from 'semantic-ui-react'; import { List as SemanticList } from 'semantic-ui-react';
import LabelComponent from '../Form/LabelComponent'; import LabelWrapper from '../Form/LabelWrapper';
import Item from './Item'; import Item from './Item';
import styles from './list.css'; import styles from './list.css';
@ -28,7 +28,7 @@ export default function List ({ className, items, label, onClick, style }) {
}; };
return ( return (
<LabelComponent label={ label }> <LabelWrapper label={ label }>
<SemanticList className={ `${styles.list} ${className}` }> <SemanticList className={ `${styles.list} ${className}` }>
{ {
items.filter((item) => item).map(({ buttons, description, icon, isActive, key, label }, index) => ( items.filter((item) => item).map(({ buttons, description, icon, isActive, key, label }, index) => (
@ -44,7 +44,7 @@ export default function List ({ className, items, label, onClick, style }) {
)) ))
} }
</SemanticList> </SemanticList>
</LabelComponent> </LabelWrapper>
); );
} }

View File

@ -28,12 +28,12 @@ export default function Steps ({ activeStep, className, steps }) {
<div className={ className }> <div className={ className }>
<SemanticStep.Group ordered> <SemanticStep.Group ordered>
{ {
steps.map((label, index) => ( steps.filter((step) => step).map((step, index) => (
<Step <Step
isActive={ activeStep === index } isActive={ activeStep === index }
isCompleted={ activeStep > index } isCompleted={ activeStep > index }
key={ label.key || index } key={ step.key || index }
label={ label.label || label } label={ step.label || step }
/> />
)) ))
} }

View File

@ -15,18 +15,18 @@
// 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 { Menu } from 'semantic-ui-react'; import { Menu as SemanticMenu } from 'semantic-ui-react';
export default function Tab ({ isActive, className, index, label, name, onClick, style }) { export default function Tab ({ isActive, className, index, label, name, onClick, style }) {
return ( return (
<Menu.Item <SemanticMenu.Item
active={ isActive } active={ isActive }
index={ index } index={ index }
name={ name } name={ name }
onClick={ onClick } onClick={ onClick }
> >
{ label } { label }
</Menu.Item> </SemanticMenu.Item>
); );
} }

View File

@ -15,7 +15,7 @@
// 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 { Menu } from 'semantic-ui-react'; import { Menu as SemanticMenu } from 'semantic-ui-react';
import Tab from './Tab'; import Tab from './Tab';
@ -23,30 +23,22 @@ export default function Tabs ({ activeTab, className, tabs, onChange }) {
const onTabClick = (event, { index }) => onChange && onChange(event, index); const onTabClick = (event, { index }) => onChange && onChange(event, index);
return ( return (
<Menu <SemanticMenu
className={ className } className={ className }
pointing pointing
> >
{ {
tabs.map((tab, index) => { tabs.filter((tab) => tab).map((tab, index) => (
if (!tab) { <Tab
return null; isActive={ activeTab === index }
} index={ index }
key={ `tab_${index}` }
const key = `tab_${index}`; label={ tab.label || tab }
onClick={ onTabClick }
return ( />
<Tab ))
isActive={ activeTab === index }
index={ index }
key={ key }
label={ tab.label || tab }
onClick={ onTabClick }
/>
);
})
} }
</Menu> </SemanticMenu>
); );
} }