From 96bebb92f858ce73ba30b8b1d67905786562fc1f Mon Sep 17 00:00:00 2001 From: Mathew Morris Date: Mon, 16 Sep 2019 12:00:58 -0500 Subject: [PATCH] fix(Input): Padding, Icon color, & Floating changes (#78) --- src/Form/FormError.js | 5 +- src/Form/Input.js | 99 ++++++++++++++----- src/Form/Input.stories.js | 26 ++++- src/Form/Label.js | 20 +++- src/Form/__snapshots__/DateInput.spec.js.snap | 11 ++- .../__snapshots__/PhoneInput.spec.js.snap | 11 ++- src/theme.js | 2 +- 7 files changed, 138 insertions(+), 36 deletions(-) diff --git a/src/Form/FormError.js b/src/Form/FormError.js index 4f07ca1..6be534a 100644 --- a/src/Form/FormError.js +++ b/src/Form/FormError.js @@ -10,9 +10,10 @@ const FormErrorContainer = createComponent({ tag: 'span', style: css` display: block; - margin: 4px 0 0 4px; + margin: 8px 0 0 1px; color: ${p => p.theme.colors.red}; - font-size: 10px; + font-size: 12px; + font-weight: 500; `, }); diff --git a/src/Form/Input.js b/src/Form/Input.js index ba3b8b8..f7007b2 100644 --- a/src/Form/Input.js +++ b/src/Form/Input.js @@ -12,6 +12,7 @@ const InputContainer = createComponent({ name: 'InputContainer', style: css` position: relative; + color: ${p => p.theme.colors.greyDarker}; `, }); @@ -19,6 +20,7 @@ const StyledInput = createComponent({ name: 'Input', tag: 'input', style: ({ + isFloatable, isFloating, theme, borderRadius = theme.radius, @@ -33,6 +35,7 @@ const StyledInput = createComponent({ outline: none; width: 100%; padding: 8px; + padding-right: 24px; border-radius: ${borderRadius}px; transition: 250ms all; -webkit-appearance: none; @@ -42,7 +45,8 @@ const StyledInput = createComponent({ box-sizing: border-box; &:hover, - &:active { + &:active, + & + label &:hover { border-color: ${theme.colors.greyDark}; } @@ -52,6 +56,7 @@ const StyledInput = createComponent({ ::placeholder { color: ${theme.colors.greyDarker}; + opacity: ${isFloatable ? 0 : 1}; } &[disabled] { @@ -64,14 +69,8 @@ const StyledInput = createComponent({ } } - ${isFloating && - css` - line-height: 14px; - padding-top: 14px; - padding-bottom: 0px; - `}; - ${leftIcon && + !isFloatable && css` padding-left: ${(leftIconProps.size || 16) + 12}px; `}; @@ -80,20 +79,52 @@ const StyledInput = createComponent({ css` padding-right: ${(rightIconProps.size || 16) + 32}px; `}; + + ${isFloating && + css` + line-height: 14px; + padding-top: 14px; + padding-bottom: 0px; + `}; `, }); const StyledIcon = styled(Icon)` - position: absolute; - top: 50%; - transform: translateY(-50%); + ${({ theme, isDisabled }) => css` + position: absolute; + top: 50%; + transform: translateY(-50%); + transition: 250ms all; + + ${isDisabled && + css` + color: ${theme.colors.grey}; + `} + `} `; const LeftIcon = createComponent({ name: 'InputLeftIcon', as: StyledIcon, - style: css` + style: ({ isFocused, isFloating, isFloatable, theme }) => css` left: 8px; + + ${isFloatable && + css` + position: static; + padding-right: 4px; + `} + + ${isFloating && + css` + font-size: 12px; + line-height: 14px; + + ${isFocused && + css` + color: ${theme.colors.primary}; + `} + `} `, }); @@ -105,7 +136,16 @@ const RightIcon = createComponent({ `, }); -const StyledTextArea = StyledInput.withComponent('textarea'); +const StyledTextArea = createComponent({ + name: 'TextArea', + as: StyledInput.withComponent('textarea'), + style: ({ isFloatable, isFloating }) => css` + ${isFloatable && isFloating && + css` + padding-top: 24px; + `} + `, +}); const AutogrowShadow = createComponent({ name: 'AutogrowShadow', @@ -281,6 +321,12 @@ export class Input extends Component { this.ref.current.blur(); } + handleLabelClick = () => { + if (this.props.floating) { + this.focus(); + } + }; + render() { const { style, @@ -307,7 +353,7 @@ export class Input extends Component { const { focused, height, value } = this.state; - const isFloating = floating && value !== undefined && `${value}`.trim(); + const isFloating = (floating && value !== undefined && !!`${value}`.trim()) || (floating && focused); const inputProps = { ...rest, @@ -330,15 +376,16 @@ export class Input extends Component { disabled, }; + const statusProps = { + isFloatable: floating, + isFloating, + isFocused: focused, + isDisabled: disabled, + }; + const Label = label ? ( - + + {leftIcon && } {label} ) : null; @@ -350,9 +397,13 @@ export class Input extends Component { {floating && Label} - {leftIcon && } + {leftIcon && !floating && ( + + )} - {rightIcon && } + {rightIcon && ( + + )} {multiline ? : } diff --git a/src/Form/Input.stories.js b/src/Form/Input.stories.js index 9546682..c5666a0 100644 --- a/src/Form/Input.stories.js +++ b/src/Form/Input.stories.js @@ -1,4 +1,5 @@ import React from 'react'; +import { object, select, boolean } from '@storybook/addon-knobs/react'; import Formbot from './Formbot'; import Button from '../Button'; import { Input } from './Input'; @@ -61,7 +62,9 @@ export const Autogrow = () => ; -export const Disabled = () => ; +export const Disabled = () => ; + +export const Error = () => ; export const Styles = () => ( ( }} /> ); + +export const Icon = () => { + const iconOptions = { + Information: 'information-outline', + Visibility: 'eye-outline', + Alert: 'alert', + 'Area 51': 'alien', + }; + + return ( + + ); +}; diff --git a/src/Form/Label.js b/src/Form/Label.js index 0913ccf..37d3d8f 100644 --- a/src/Form/Label.js +++ b/src/Form/Label.js @@ -13,12 +13,24 @@ const Label = createComponent({ ${isFloatable && css` position: absolute; - top: 6px; - left: 8px; - opacity: ${isFloating ? 1 : 0}; margin: 0; - font-size: 12px; + font-size: 16px; line-height: 14px; + left: 8px; + top: 50%; + transform: translateY(-50%); + user-select: none; + + &:hover { + cursor: text; + } + + ${isFloating && + css` + font-size: 12px; + top: 6px; + transform: none; + `} `}; ${isFocused && diff --git a/src/Form/__snapshots__/DateInput.spec.js.snap b/src/Form/__snapshots__/DateInput.spec.js.snap index 6b4354b..de8ac49 100644 --- a/src/Form/__snapshots__/DateInput.spec.js.snap +++ b/src/Form/__snapshots__/DateInput.spec.js.snap @@ -14,6 +14,7 @@ exports[` snapshot 1`] = ` .c2 { position: relative; + color: #767980; } .c3 { @@ -23,18 +24,20 @@ exports[` snapshot 1`] = ` outline: none; width: 100%; padding: 8px; + padding-right: 24px; border-radius: 8px; -webkit-transition: 250ms all; transition: 250ms all; -webkit-appearance: none; font-family: inherit; - font-size: 14px; + font-size: 16px; color: #494D55; box-sizing: border-box; } .c3:hover, -.c3:active { +.c3:active, +.c3 + label .c3:hover { border-color: #A4A6AA; } @@ -44,18 +47,22 @@ exports[` snapshot 1`] = ` .c3::-webkit-input-placeholder { color: #767980; + opacity: 1; } .c3::-moz-placeholder { color: #767980; + opacity: 1; } .c3:-ms-input-placeholder { color: #767980; + opacity: 1; } .c3::placeholder { color: #767980; + opacity: 1; } .c3[disabled] { diff --git a/src/Form/__snapshots__/PhoneInput.spec.js.snap b/src/Form/__snapshots__/PhoneInput.spec.js.snap index d1ecaec..512e5d9 100644 --- a/src/Form/__snapshots__/PhoneInput.spec.js.snap +++ b/src/Form/__snapshots__/PhoneInput.spec.js.snap @@ -14,6 +14,7 @@ exports[` snapshot 1`] = ` .c2 { position: relative; + color: #767980; } .c3 { @@ -23,18 +24,20 @@ exports[` snapshot 1`] = ` outline: none; width: 100%; padding: 8px; + padding-right: 24px; border-radius: 8px; -webkit-transition: 250ms all; transition: 250ms all; -webkit-appearance: none; font-family: inherit; - font-size: 14px; + font-size: 16px; color: #494D55; box-sizing: border-box; } .c3:hover, -.c3:active { +.c3:active, +.c3 + label .c3:hover { border-color: #A4A6AA; } @@ -44,18 +47,22 @@ exports[` snapshot 1`] = ` .c3::-webkit-input-placeholder { color: #767980; + opacity: 1; } .c3::-moz-placeholder { color: #767980; + opacity: 1; } .c3:-ms-input-placeholder { color: #767980; + opacity: 1; } .c3::placeholder { color: #767980; + opacity: 1; } .c3[disabled] { diff --git a/src/theme.js b/src/theme.js index a9c5e54..7d30166 100644 --- a/src/theme.js +++ b/src/theme.js @@ -62,7 +62,7 @@ export default (overrides = {}) => { const radii = [0, 2, 4]; const typography = { - fontSize: 14, + fontSize: 16, bodyFontFamily: 'Avenir', headerFontFamily: 'Tiempos', };