Skip to content

Instantly share code, notes, and snippets.

@HriBB
Created August 10, 2016 01:20
Show Gist options
  • Save HriBB/6da0f92d99370bbf794bdace3f88e3ce to your computer and use it in GitHub Desktop.
Save HriBB/6da0f92d99370bbf794bdace3f88e3ce to your computer and use it in GitHub Desktop.
React MDL UploadField for Redux Form
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import './UploadField.scss'
/**
* Upload field polyfill until mdl implements it ... if ever ...
*
* Note: onFocus/onBlur timeouts are needed for mdl animations to work.
*/
export default class UploadField extends Component {
constructor(props) {
super(props)
this.state = { focused: false }
this.opened = false
}
onFocus = (e) => {
this.opened = false
this.props.input.onFocus(e)
this.focusTimeout = setTimeout(() => {
this.focusTimeout = null
this.setState({ focused: true })
})
}
onBlur = (e) => {
this.props.input.onBlur(e)
this.blurTimeout = setTimeout(() => {
this.blurTimeout = null
this.setState({ focused: false })
})
}
onChange = (e) => {
this.props.input.onBlur(e)
if (this.props.onChange) {
this.props.onChange(e)
}
}
onClick = (e) => {
this.opened = true
}
componentWillUnmount() {
if (this.focusTimeout) clearTimeout(this.focusTimeout)
if (this.blurTimeout) clearTimeout(this.blurTimeout)
}
render() {
const { browse } = this.refs
const { input, label, meta: { pristine, touched, visited, error, dirty }, ...other } = this.props
const edited = !pristine && (touched || visited || focused)
const files = browse && browse.files.length
const className = classnames({
'mdl-uploadfield': true,
'mdl-uploadfield--floating-label': true,
'is-dirty': dirty,
'is-focused': this.state.focused,
'is-invalid': error && edited && !files && !this.opened,
})
const props = {
type: 'file',
onFocus: this.onFocus,
onBlur: this.onBlur,
onClick: this.onClick,
onChange: this.onChange
}
return (
<div className={className}>
<input className={'mdl-uploadfield__input'} ref={'browse'} {...input} {...other} {...props}/>
<label className={'mdl-uploadfield__label'}>{label}</label>
{touched && error && <span className="mdl-uploadfield__error">{error}</span>}
</div>
)
}
}
/**
* Upload field polyfill until mdl implements it ... if ever ...
*/
.mdl-uploadfield {
position: relative;
display: inline-block;
padding: 20px 0;
width: 300px;
.mdl-uploadfield__input {
position: relative;
width: 100%;
padding: 4px 0;
border: none;
font-size: 16px;
border-radius: 0;
font-family: "Helvetica", "Arial", sans-serif;
font-weight: 400;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
background-color: #fff;
color: rgba(0, 0, 0, 0.870588);
-webkit-appearance: none;
-moz-appearance: none;
outline: none;
}
.mdl-uploadfield__label {
position: absolute;
display: block;
overflow: hidden;
top: 24px;
left: 0;
right: 0;
bottom: 0;
width: 100%;
font-size: 16px;
pointer-events: none;
white-space: nowrap;
text-align: left;
color: rgba(0, 0, 0, 0.36);
// The after label is the colored underline for the UploadField.
&:after {
background-color: #3f51b5;
bottom: 20px;
content: '';
height: 2px;
left: 45%;
position: absolute;
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
visibility: hidden;
width: 10px;
}
}
.mdl-uploadfield__error {
color: #d50000;
position: absolute;
font-size: 12px;
margin-top: 3px;
visibility: hidden;
display: block;
}
&.is-dirty {
.mdl-uploadfield__input {
color: rgba(0, 0, 0, 0.870588);
}
.mdl-uploadfield__label {
visibility: hidden;
}
}
&.is-focused {
.mdl-uploadfield__input {
outline: none;
}
.mdl-uploadfield__label {
&:after {
left: 0;
visibility: visible;
width: 100%;
}
}
}
&.is-invalid {
.mdl-uploadfield__input {
border-color: #d50000;
box-shadow: none;
}
.mdl-uploadfield__label {
&:after {
background-color: #d50000;
}
}
.mdl-uploadfield__error {
visibility: visible;
}
}
&.mdl-uploadfield--floating-label {
.mdl-uploadfield__label {
color: rgb(63,81,181);
font-size: 12px;
top: 4px;
visibility: visible;
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
&.has-placeholder {
.mdl-uploadfield__label {
transition: none;
}
}
&.is-focused,
&.is-dirty,
&.has-placeholder {
.mdl-uploadfield__label {
color: rgb(63,81,181);
font-size: 12px;
top: 4px;
visibility: visible;
}
}
&.is-invalid {
.mdl-uploadfield__label {
color: rgb(213,0,0);
font-size: 12px;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment