Merge pull request #88 from lbryio/better-form-hints
Convert form hints to separate component with better style (WIP)
This commit is contained in:
commit
6ac9853fd4
4 changed files with 102 additions and 24 deletions
|
@ -4,9 +4,11 @@ var Icon = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
style: React.PropTypes.object,
|
style: React.PropTypes.object,
|
||||||
fixed: React.PropTypes.bool,
|
fixed: React.PropTypes.bool,
|
||||||
|
className: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var className = 'icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon;
|
var className = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon + ' ' +
|
||||||
|
(this.props.className || ''));
|
||||||
return <span className={className} style={this.props.style}></span>
|
return <span className={className} style={this.props.style}></span>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
var requiredFieldWarningStyle = {
|
|
||||||
color: '#cc0000',
|
|
||||||
transition: 'opacity 400ms ease-in',
|
|
||||||
};
|
|
||||||
|
|
||||||
var FormField = React.createClass({
|
var FormField = React.createClass({
|
||||||
|
_fieldRequiredText: 'This field is required',
|
||||||
_type: null,
|
_type: null,
|
||||||
_element: null,
|
_element: null,
|
||||||
|
|
||||||
|
@ -13,7 +9,8 @@ var FormField = React.createClass({
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
warningState: 'hidden',
|
adviceState: 'hidden',
|
||||||
|
adviceText: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
|
@ -25,22 +22,26 @@ var FormField = React.createClass({
|
||||||
this._element = this.props.type;
|
this._element = this.props.type;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
warnRequired: function() {
|
showAdvice: function(text) {
|
||||||
this.setState({
|
this.setState({
|
||||||
warningState: 'shown',
|
adviceState: 'shown',
|
||||||
|
adviceText: text,
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
warningState: 'fading',
|
adviceState: 'fading',
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
warningState: 'hidden',
|
adviceState: 'hidden',
|
||||||
});
|
});
|
||||||
}, 450);
|
}, 450);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
},
|
},
|
||||||
|
warnRequired: function() {
|
||||||
|
this.showAdvice(this._fieldRequiredText);
|
||||||
|
},
|
||||||
focus: function() {
|
focus: function() {
|
||||||
this.refs.field.focus();
|
this.refs.field.focus();
|
||||||
},
|
},
|
||||||
|
@ -55,24 +56,43 @@ var FormField = React.createClass({
|
||||||
return this.refs.field.options[this.refs.field.selectedIndex];
|
return this.refs.field.options[this.refs.field.selectedIndex];
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var warningStyle = Object.assign({}, requiredFieldWarningStyle);
|
|
||||||
if (this.state.warningState == 'fading') {
|
|
||||||
warningStyle.opacity = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass all unhandled props to the field element
|
// Pass all unhandled props to the field element
|
||||||
var otherProps = Object.assign({}, this.props);
|
var otherProps = Object.assign({}, this.props);
|
||||||
delete otherProps.type;
|
delete otherProps.type;
|
||||||
delete otherProps.hidden;
|
delete otherProps.hidden;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={this.props.hidden ? 'hidden' : ''}>
|
!this.props.hidden
|
||||||
<this._element type={this._type} name={this.props.name} ref="field" placeholder={this.props.placeholder}
|
? <div className="form-field-container">
|
||||||
{...otherProps}>
|
<this._element type={this._type} className="form-field" name={this.props.name} ref="field" placeholder={this.props.placeholder}
|
||||||
{this.props.children}
|
{...otherProps}>
|
||||||
</this._element>
|
{this.props.children}
|
||||||
<span className={this.state.warningState == 'hidden' ? 'hidden' : ''} style={warningStyle}> This field is required</span>
|
</this._element>
|
||||||
</span>
|
<FormFieldAdvice field={this.refs.field} state={this.state.adviceState}>{this.state.adviceText}</FormFieldAdvice>
|
||||||
|
</div>
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var FormFieldAdvice = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
state: React.PropTypes.string.isRequired,
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
this.props.state != 'hidden'
|
||||||
|
? <div className="form-field-advice-container">
|
||||||
|
<div className={'form-field-advice' + (this.props.state == 'fading' ? ' form-field-advice--fading' : '')}>
|
||||||
|
<Icon icon="icon-caret-up" className="form-field-advice__arrow" />
|
||||||
|
<div className="form-field-advice__content-container">
|
||||||
|
<span className="form-field-advice__content">
|
||||||
|
{this.props.children}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
: null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,7 +38,14 @@ var PublishPage = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missingFieldFound) {
|
let fileProcessing = false;
|
||||||
|
if (this.state.fileInfo && !this.state.tempFileReady) {
|
||||||
|
this.refs.file.showAdvice('Your file is still processing.');
|
||||||
|
this.refs.file.focus();
|
||||||
|
fileProcessing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingFieldFound || fileProcessing) {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: false,
|
submitting: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -234,6 +234,55 @@ input[type="text"], input[type="search"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-field-container {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field-advice-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field-advice {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
transition: opacity 400ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field-advice--fading {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field-advice__arrow {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 18px;
|
||||||
|
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 0.3;
|
||||||
|
color: darken($color-primary, 5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.form-field-advice__content-container {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-field-advice__content {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
background-color: darken($color-primary, 5%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
Loading…
Add table
Reference in a new issue