Skip to content

Instantly share code, notes, and snippets.

@Temzasse
Created August 17, 2017 18:47
Show Gist options
  • Save Temzasse/f9d824797afdb25c2d25fb2dea0463b0 to your computer and use it in GitHub Desktop.
Save Temzasse/f9d824797afdb25c2d25fb2dea0463b0 to your computer and use it in GitHub Desktop.
TextField with floating label (with styles)
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components';
import { darken } from 'polished';
const propTypes = {
label: PropTypes.string,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
};
class TextField extends Component {
state = {
isFocused: false,
}
handleFocus = () => {
this.setState({ isFocused: true });
};
handleBlur = () => {
this.setState({ isFocused: false });
};
handleLabelClick = () => {
const { isFocused } = this.state;
const { value } = this.props;
if (!isFocused && !value) {
this.setState({ isFocused });
this._input.focus();
}
};
render() {
const { label, value, ...rest } = this.props;
const { isFocused } = this.state;
return (
<TextFieldWrapper>
{label &&
<Label
up={isFocused || value}
onClick={this.handleLabelClick}
>
{label}
</Label>
}
<Input
value={value}
onChange={this.props.onChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
innerRef={node => { this._input = node; }}
{...rest}
/>
</TextFieldWrapper>
);
}
}
const defaultColor = 'darkslategray';
const padV = 16;
const padH = 16;
const labelSize = 14;
const TextFieldWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
color: ${props => props.theme.textColor || defaultColor};
`;
const Label = styled.label`
color: inherit;
font-size: ${labelSize}px;
will-change: transform;
transition: transform 0.3s cubic-bezier(.06,.67,.32,.82);
transform: translate(${padH}px, ${1.333 * labelSize + padV}px);
${props => props.up && css`
transform: scale(0.8) translate(-2px, -2px);
`}
`;
const Input = styled.input`
background-color: transparent;
color: inherit;
outline: none;
border-radius: 3px;
font-size: 16px;
width: 100%;
padding: ${padV}px ${padH}px;
border: 1px solid ${props => props.theme.borderColor || defaultColor};
&:focus {
border: 1px solid ${props =>
darken(0.1, props.theme.borderColor || defaultColor)
};
}
`;
TextField.propTypes = propTypes;
export default TextField;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment