Fix input element styling madness

This commit is contained in:
John Lyon-Smith
2018-03-04 14:03:42 -08:00
parent 3ef0a3bdc9
commit eaf26343b8
16 changed files with 265 additions and 225 deletions

View File

@@ -3,8 +3,9 @@ import PropTypes from 'prop-types'
import { reactAutoBind } from 'auto-bind2' import { reactAutoBind } from 'auto-bind2'
import { regExpPattern } from 'regexp-pattern' import { regExpPattern } from 'regexp-pattern'
import { api } from 'src/API' import { api } from 'src/API'
import { Column, BoundInput, BoundButton, BoundCheckbox, BoundEmailIcon } from 'ui' import { Row, Column, BoundInput, BoundButton, BoundCheckbox, BoundEmailIcon } from 'ui'
import { FormBinder } from 'react-form-binder' import { FormBinder } from 'react-form-binder'
import { sizeInfo } from 'ui/style'
export class UserForm extends React.Component { export class UserForm extends React.Component {
static propTypes = { static propTypes = {
@@ -28,15 +29,19 @@ export class UserForm extends React.Component {
nonValue: true, nonValue: true,
isDisabled: (r) => (!!r._id === false) isDisabled: (r) => (!!r._id === false)
}, },
resendEmail: {
nonValue: true,
isDisabled: (r) => (!!r._id === false)
},
firstName: { firstName: {
isValid: (r, v) => (v !== '') isValid: (r, v) => (v !== '')
}, },
lastName: { lastName: {
isValid: (r, v) => (v !== '') isValid: (r, v) => (v !== '')
}, },
role: { administrator: {
isValid: (r, v) => (v !== ''), isValid: (r, v) => (v !== ''),
isDisabled: (r) => (api.loggedInUser._id === r._id) isDisabled: (r) => (api.loggedInUser._id === r._id) // Adding a new user
}, },
project: { project: {
isValid: (r, v) => (v !== '' || v === '') isValid: (r, v) => (v !== '' || v === '')
@@ -99,40 +104,79 @@ export class UserForm extends React.Component {
} }
render() { render() {
return ( const { binder } = this.state
<form onSubmit={this.handleSubmit}>
<Column>
<Column.Item>
<BoundCheckbox label={'Administrator'} name='administrator' binder={this.state.binder} />
</Column.Item>
<Column.Item>
<BoundInput label='First Name' name='firstName'
width={8} binder={this.state.binder} />
</Column.Item>
<Column.Item>
<BoundInput label='Last Name' name='lastName'
width={8} binder={this.state.binder} />
</Column.Item>
<Column.Item>
<BoundInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
binder={this.state.binder} />
<BoundEmailIcon name='emailValidated' binder={this.state.binder} width={4}
onClick={this.handleResendEmail} />
</Column.Item>
<Column.Item>
<BoundButton width={4} size='medium' content='Change Email' label='&nbsp;' name='changeEmail'
binder={this.state.binder} onClick={this.handleChangeEmail} />
</Column.Item>
<Column.Item> return (
<BoundButton color='red' width={4} size='medium' content='Remove' label='&nbsp;' name='remove' <form id='userForm' onSubmit={this.handleSubmit}>
binder={this.state.binder} onClick={this.props.onRemove} /> <Column>
<BoundButton width={4} size='medium' content='Reset' label='&nbsp;' name='reset' <Column.Item height={20} />
binder={this.state.binder} onClick={this.handleReset} /> <Row>
<BoundButton primary submit width={4} size='medium' <Row.Item width={20} />
content={this.state.binder._id ? 'Save' : 'Add'} label='&nbsp;' name='submit' <Row.Item grow>
binder={this.state.binder} /> <Column.Item>
</Column.Item> <Column>
<Column.Item>
<Row>
<Row.Item grow>
<BoundInput label='First Name' name='firstName' binder={binder} />
</Row.Item>
<Row.Item width={20} />
<Row.Item grow>
<BoundInput label='Last Name' name='lastName' binder={binder} />
</Row.Item>
<Row.Item width={20} />
</Row>
</Column.Item>
<Column.Item>
<Row>
<Row.Item>
<BoundInput label='Email' name='email' message='Must be a valid email address. Required.' binder={binder} />
</Row.Item>
<Row.Item width={10} />
<Row.Item>
<BoundEmailIcon name='emailValidated' binder={binder} />
</Row.Item>
</Row>
</Column.Item>
<Column.Item minHeight={sizeInfo.buttonHeight}>
<Row>
<Row.Item>
<BoundButton text='Change Email' name='changeEmail' binder={binder} onClick={this.handleChangeEmail} />
</Row.Item>
<Row.Item grow />
<Row.Item>
<BoundButton text='Resend Confirmation Email' name='resendEmail' binder={binder} onClick={this.handleResendEmail} />
</Row.Item>
</Row>
</Column.Item>
<Column.Item>
<Row>
<Row.Item>
<BoundCheckbox label={'Administrator'} name='administrator' binder={this.state.binder} />
</Row.Item>
<Row.Item grow />
</Row>
</Column.Item>
<Column.Item minHeight={sizeInfo.buttonHeight}>
<Row>
<Row.Item>
<BoundButton text='Reset' name='reset' binder={binder} onClick={this.handleReset} />
</Row.Item>
<Row.Item grow />
<Row.Item>
<BoundButton text='Remove' name='remove' binder={binder} onClick={this.props.onRemove} />
</Row.Item>
<Row.Item>
<BoundButton submit='userForm' text={binder._id ? 'Save' : 'Add'} name='submit' binder={binder} />
</Row.Item>
</Row>
</Column.Item>
</Column>
</Column.Item>
</Row.Item>
<Row.Item width={20} />
</Row>
<Column.Item height={20} />
</Column> </Column>
</form> </form>
) )

View File

@@ -44,7 +44,7 @@ export class UserList extends React.Component {
this.state.users this.state.users
? this.state.users.map((user, index) => ? this.state.users.map((user, index) =>
(<List.Item className='user-list-item' key={user._id || '0'} onClick={this.props.onUserListClick} (<List.Item className='user-list-item' key={user._id || '0'} onClick={this.props.onUserListClick}
active={true || user === this.props.selectedUser} data-index={index}> active={user === this.props.selectedUser} data-index={index}>
<List.Icon name='profile' size={30} /> <List.Icon name='profile' size={30} />
<List.Text> <List.Text>
{ user._id ? user.firstName + ' ' + user.lastName : '[New User]' } { user._id ? user.firstName + ' ' + user.lastName : '[New User]' }

View File

@@ -1,42 +1,33 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Text, Button, Icon } from 'ui' import { Text, Icon } from 'ui'
export default class BoundEmailIcon extends React.Component { export default class BoundEmailIcon extends React.Component {
static propTypes = { static propTypes = {
name: PropTypes.string, name: PropTypes.string,
binder: PropTypes.object, binder: PropTypes.object,
width: PropTypes.number,
onClick: PropTypes.func
} }
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getField('emailValidated') this.state = props.binder.getFieldState(props.name)
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getField(nextProps.name)) this.setState(nextProps.binder.getFieldState(nextProps.name))
} }
} }
render() { render() {
if (this.state.value) { // const { value } = this.state
return (
<div width={this.props.width}> return (
<Text>&nbsp;</Text> <div>
<Icon name='mail' color='green' size='big' /> <Text>&nbsp;</Text>
</div> <br />
) <Icon name='mail' size={30} margin={0} />
} else { </div>
return ( )
<div width={this.props.width}>
<Text>&nbsp;</Text>
<Button icon='mail outline' color='red' labelPosition='left'
content='Resend Email' onClick={this.props.onClick} disabled={this.state.disabled} />
</div>
)
}
} }
} }

View File

@@ -1,8 +1,7 @@
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React, { Component } from 'react' import React, { Component } from 'react'
import style from './Button.style' import { colorInfo, sizeInfo } from './style'
import { sizeInfo } from './style'
import { Text } from '.' import { Text } from '.'
class Button extends Component { class Button extends Component {
@@ -21,13 +20,34 @@ class Button extends Component {
disabled: false, disabled: false,
} }
static style = {
button: {
height: sizeInfo.buttonHeight,
borderRadius: 10,
background: colorInfo.buttonBackgroundHover,
verticalAlign: 'middle',
padding: '0 15px 0 15px',
outline: 'none',
':hover': {
background: colorInfo.buttonBackground,
},
':disabled': {
background: colorInfo.disabledButtonBackground,
},
':active': {
borderWidth: 0,
background: colorInfo.buttonBackgroundActive,
}
}
}
render() { render() {
const { name, submit, visible, disabled, width, text, onClick } = this.props const { name, submit, visible, disabled, width, text, onClick } = this.props
return ( return (
<button name={name} type={!visible ? 'hidden' : submit ? 'submit' : 'button'} <button name={name} type={!visible ? 'hidden' : submit ? 'submit' : 'button'}
disabled={disabled} form={submit} disabled={disabled} form={submit}
style={[style.base, { width, minWidth: sizeInfo.minButtonWidth }]} style={[Button.style.button, { width, minWidth: sizeInfo.minButtonWidth }]}
onClick={onClick}> onClick={onClick}>
<Text color='inverse'>{text}</Text> <Text color='inverse'>{text}</Text>
</button> </button>

View File

@@ -1,22 +0,0 @@
import { colorInfo } from './style'
export default {
base: {
height: '100%',
borderRadius: 10,
background: colorInfo.buttonBackgroundHover,
verticalAlign: 'middle',
padding: '0 15px 0 15px',
outline: 'none',
':hover': {
background: colorInfo.buttonBackground,
},
':disabled': {
background: colorInfo.disabledButtonBackground,
},
':active': {
borderWidth: 0,
background: colorInfo.buttonBackgroundActive,
}
}
}

View File

@@ -1,9 +1,8 @@
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React, { Component } from 'react' import React, { Component } from 'react'
import style from './Checkbox.style'
import { reactAutoBind } from 'auto-bind2' import { reactAutoBind } from 'auto-bind2'
import { fontInfo } from './style' import { fontInfo, colorInfo, sizeInfo } from './style'
class Checkbox extends Component { class Checkbox extends Component {
static propTypes = { static propTypes = {
@@ -14,6 +13,58 @@ class Checkbox extends Component {
name: PropTypes.string, name: PropTypes.string,
} }
static style = {
checkbox: {
position: 'relative',
display: 'inline-block',
cursor: 'pointer',
backgroundColor: colorInfo.buttonBackground,
height: sizeInfo.checkboxSize,
width: sizeInfo.checkboxSize,
':hover': {
backgroundColor: colorInfo.buttonBackgroundHover
}
},
input: {
position: 'absolute',
opacity: 0,
cursor: 'pointer',
},
checkboxUnchecked: {
backgroundColor: colorInfo.uncheckedCheckbox,
':hover': {
backgroundColor: colorInfo.uncheckedCheckboxHover,
}
},
checkboxDisabled: {
backgroundColor: colorInfo.disabledButtonBackground,
},
checkmark: {
position: 'absolute',
content: '',
left: 8,
top: 4,
width: 6,
height: 12,
borderStyle: 'solid',
borderColor: '#FFFFFF',
borderWidth: '0 3px 3px 0',
transform: 'rotate(45deg)',
},
checkmarkUnchecked: {
display: 'none'
},
label: {
marginLeft: 10,
}
}
constructor(props) { constructor(props) {
super(props) super(props)
reactAutoBind(this) reactAutoBind(this)
@@ -32,14 +83,14 @@ class Checkbox extends Component {
return ( return (
<div style={[!visible && { display: 'none' }]}> <div style={[!visible && { display: 'none' }]}>
<div style={[style.checkbox, disabled ? style.checkboxDisabled : !checked ? style.checkboxUnchecked : null]} <div style={[Checkbox.style.checkbox, disabled ? Checkbox.style.checkboxDisabled : !checked ? Checkbox.style.checkboxUnchecked : null]}
onClick={disabled ? null : this.onClick}> onClick={disabled ? null : this.onClick}>
<input id={name} type='checkbox' style={style.input} disabled={disabled} /> <input id={name} type='checkbox' style={Checkbox.style.input} disabled={disabled} />
<div style={[style.checkmark, !checked && style.checkmarkUnchecked]} /> <div style={[Checkbox.style.checkmark, !checked && Checkbox.style.checkmarkUnchecked]} />
</div> </div>
<label <label
htmlFor={name} htmlFor={name}
style={[style.label, { style={[Checkbox.style.label, {
verticalAlign: 'top', verticalAlign: 'top',
fontSize: fontInfo.size.medium, fontSize: fontInfo.size.medium,
fontFamily: fontInfo.family, fontFamily: fontInfo.family,

View File

@@ -1,53 +0,0 @@
import { colorInfo, sizeInfo } from './style'
export default {
checkbox: {
position: 'relative',
display: 'inline-block',
cursor: 'pointer',
backgroundColor: colorInfo.buttonBackground,
height: sizeInfo.checkboxSize,
width: sizeInfo.checkboxSize,
':hover': {
backgroundColor: colorInfo.buttonBackgroundHover
}
},
input: {
position: 'absolute',
opacity: 0,
cursor: 'pointer',
},
checkboxUnchecked: {
backgroundColor: colorInfo.uncheckedCheckbox,
':hover': {
backgroundColor: colorInfo.uncheckedCheckboxHover,
}
},
checkboxDisabled: {
backgroundColor: colorInfo.disabledButtonBackground,
},
checkmark: {
position: 'absolute',
content: '',
left: 8,
top: 4,
width: 6,
height: 12,
borderStyle: 'solid',
borderColor: '#FFFFFF',
borderWidth: '0 3px 3px 0',
transform: 'rotate(45deg)',
},
checkmarkUnchecked: {
display: 'none'
},
label: {
marginLeft: 10,
}
}

View File

@@ -1,7 +1,6 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import style from './Dimmer.style'
import { reactAutoBind } from 'auto-bind2' import { reactAutoBind } from 'auto-bind2'
export class Dimmer extends Component { export class Dimmer extends Component {
@@ -10,6 +9,24 @@ export class Dimmer extends Component {
children: PropTypes.node, children: PropTypes.node,
} }
static style = {
div: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
width: '100vw',
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 100,
background: 'rgba(25, 25, 30, 0.75)'
}
}
constructor(props) { constructor(props) {
super(props) super(props)
reactAutoBind(this) reactAutoBind(this)
@@ -21,7 +38,7 @@ export class Dimmer extends Component {
render() { render() {
return this.props.active ? ( return this.props.active ? (
<div style={style.dimmer} onClick={this.preventPropagation}> <div style={Dimmer.style.div} onClick={this.preventPropagation}>
{this.props.children} {this.props.children}
</div> </div>
) : null ) : null

View File

@@ -1,17 +0,0 @@
export default {
dimmer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
width: '100vw',
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 100,
background: 'rgba(25, 25, 30, 0.75)'
}
}

View File

@@ -1,9 +1,8 @@
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React, { Component } from 'react' import React, { Component } from 'react'
import style from './HeaderButton.style'
import { Icon, Image } from '.' import { Icon, Image } from '.'
import { sizeInfo } from 'ui/style' import { colorInfo, sizeInfo } from 'ui/style'
class HeaderButton extends Component { class HeaderButton extends Component {
static propTypes = { static propTypes = {
@@ -12,6 +11,22 @@ class HeaderButton extends Component {
image: PropTypes.string, image: PropTypes.string,
} }
static style = {
button: {
background: colorInfo.headerButtonBackground,
verticalAlign: 'middle',
borderWidth: 0,
padding: '0 0 0 0',
outline: 'none',
':hover': {
background: colorInfo.headerButtonBackgroundHover,
},
':active': {
background: colorInfo.headerButtonBackgroundActive,
}
}
}
render() { render() {
const size = sizeInfo.headerHeight - sizeInfo.headerBorderWidth const size = sizeInfo.headerHeight - sizeInfo.headerBorderWidth
const { onClick, icon, image } = this.props const { onClick, icon, image } = this.props
@@ -24,7 +39,7 @@ class HeaderButton extends Component {
} }
return ( return (
<button type='button' style={[{ height: size, width: size }, style.base]} onClick={onClick}> <button type='button' style={[{ height: size, width: size }, HeaderButton.style.button]} onClick={onClick}>
{content} {content}
</button> </button>
) )

View File

@@ -1,17 +0,0 @@
import { colorInfo } from './style'
export default {
base: {
background: colorInfo.headerButtonBackground,
verticalAlign: 'middle',
borderWidth: 0,
padding: '0 0 0 0',
outline: 'none',
':hover': {
background: colorInfo.headerButtonBackgroundHover,
},
':active': {
background: colorInfo.headerButtonBackgroundActive,
}
}
}

View File

@@ -1,7 +1,6 @@
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React, { Component } from 'react' import React, { Component } from 'react'
import style from './Input.style'
class Input extends Component { class Input extends Component {
static propTypes = { static propTypes = {
@@ -15,14 +14,40 @@ class Input extends Component {
value: PropTypes.string, value: PropTypes.string,
} }
static style = {
div: {
padding: '5px',
borderWidth: 1,
borderColor: '#b2b2b2',
backgroundColor: '#ffffff',
borderStyle: 'solid',
borderRadius: '5px',
':focus': {
outline: 'none'
},
},
input: {
fontSize: '16px',
color: '#000000',
borderWidth: 0,
padding: 0,
margin: 0,
width: '100%',
outline: 'none',
}
}
render() { render() {
let { name, width, password, placeholder, onChange, visible, disabled, value } = this.props let { name, width, password, placeholder, onChange, visible, disabled, value } = this.props
width = width || '100%' width = width || '100%'
return ( return (
<input name={name} value={value} type={!visible ? 'hidden' : password ? 'password' : 'text'} disabled={disabled} <div style={Input.style.div}>
style={[ { width }, style.base ]} placeholder={placeholder} onChange={onChange} /> <input name={name} value={value} type={!visible ? 'hidden' : password ? 'password' : 'text'} disabled={disabled}
style={[ { width }, Input.style.input ]} placeholder={placeholder} onChange={onChange} />
</div>
) )
} }
} }

View File

@@ -1,15 +0,0 @@
export default {
base: {
padding: '5px',
fontSize: '16px',
borderWidth: '1px',
borderColor: '#b2b2b2',
backgroundColor: '#ffffff',
color: '#000000',
borderStyle: 'solid',
borderRadius: '5px',
':focus': {
outline: 'none'
},
}
}

View File

@@ -18,7 +18,7 @@ class List extends Component {
position: 'absolute', position: 'absolute',
width: '100%', width: '100%',
height: '100%', height: '100%',
fontSize: fontInfo.size.medium, fontSize: fontInfo.size.large,
fontFamily: fontInfo.family, fontFamily: fontInfo.family,
}}> }}>
<Box border={`${sizeInfo.listBorderWidth}px solid ${colorInfo.listBorder}`} radius={sizeInfo.formBoxRadius}> <Box border={`${sizeInfo.listBorderWidth}px solid ${colorInfo.listBorder}`} radius={sizeInfo.formBoxRadius}>
@@ -47,6 +47,9 @@ List.Item = Radium(class ListItem extends Component {
<div style={{ <div style={{
display: 'table-row', display: 'table-row',
background: active ? colorInfo.listBackgroundActive : colorInfo.listBackground, background: active ? colorInfo.listBackgroundActive : colorInfo.listBackground,
':hover': {
background: colorInfo.listBackgroundHover
},
}} onClick={onClick}> }} onClick={onClick}>
{children} {children}
</div> </div>

View File

@@ -1,9 +1,8 @@
import Radium from 'radium' import Radium from 'radium'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import React, { Component } from 'react' import React, { Component } from 'react'
import style from './PanelButton.style'
import { Icon } from '.' import { Icon } from '.'
import { sizeInfo, fontInfo } from 'ui/style' import { sizeInfo, fontInfo, colorInfo } from 'ui/style'
class PanelButton extends Component { class PanelButton extends Component {
static propTypes = { static propTypes = {
@@ -12,13 +11,34 @@ class PanelButton extends Component {
text: PropTypes.string.isRequired, text: PropTypes.string.isRequired,
} }
static style = {
button: {
borderWidth: 2,
borderRadius: '10px',
padding: '0 0 0 0',
background: colorInfo.panelButtonBackground,
verticalAlign: 'middle',
outline: 'none',
':hover': {
background: colorInfo.panelButtonBackgroundHover,
},
':disabled': {
background: colorInfo.disabledPanelButtonBackground,
},
':active': {
borderWidth: 0,
background: colorInfo.panelButtonBackgroundActive,
}
}
}
render() { render() {
const { onClick, icon, text } = this.props const { onClick, icon, text } = this.props
return ( return (
<button type='button' <button type='button'
style={[ style={[
style.button, { height: sizeInfo.panelButtonSize, width: sizeInfo.panelButtonSize } PanelButton.style.button, { height: sizeInfo.panelButtonSize, width: sizeInfo.panelButtonSize }
]} ]}
onClick={onClick}> onClick={onClick}>
<div style={{ position: 'relative' }}> <div style={{ position: 'relative' }}>

View File

@@ -1,22 +0,0 @@
import { colorInfo } from './style'
export default {
button: {
borderWidth: 2,
borderRadius: '10px',
padding: '0 0 0 0',
background: colorInfo.panelButtonBackground,
verticalAlign: 'middle',
outline: 'none',
':hover': {
background: colorInfo.panelButtonBackgroundHover,
},
':disabled': {
background: colorInfo.disabledPanelButtonBackground,
},
':active': {
borderWidth: 0,
background: colorInfo.panelButtonBackgroundActive,
}
}
}