Skip to content

Commit

Permalink
feat(TextInput): Clear text input (#230)
Browse files Browse the repository at this point in the history
* clear icon across inputs

* styles, tests

* stylelint

* refactoring tests

* Update src/components/TextInput/TextInput.stories.mdx

Co-authored-by: Nathan Young <[email protected]>

Co-authored-by: Nathan Young <[email protected]>
  • Loading branch information
juanfabrega and nathanyoung authored Sep 11, 2020
1 parent 804f0b9 commit c58fd34
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 186 deletions.
4 changes: 3 additions & 1 deletion .stylelintrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"declaration-property-value-blacklist": null,
"max-nesting-depth": null,
"order/properties-alphabetical-order": null,
"selector-max-compound-selectors": 4
"selector-max-compound-selectors": 4,
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true
}
}
16 changes: 9 additions & 7 deletions src/components/SelectInput/SelectInput.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,26 @@ react-select elements for which we do not own the markup */
.react-select-icon {
padding: 0;
padding-right: 2px;
color: var(--form-control-select-icon-color);
color: var(--form-control-icon-color);

&:hover {
color: var(--form-control-select-icon-hover-color)
}

svg {
width: var(--form-control-select-icon-size);
height: var(--form-control-select-icon-size);
color: var(--form-control-icon-hover-color)
}
}

:global(.react-select__dropdown-indicator) {
@extend .react-select-icon;

svg {
width: var(--form-control-select-icon-size);
height: var(--form-control-select-icon-size);
}
}

:global(.react-select__clear-indicator) {
@extend .react-select-icon;

margin-right: var(--form-control-select-clear-icon-margin);
}

&:global(.react-select__control--is-focused) {
Expand Down
17 changes: 16 additions & 1 deletion src/components/SelectInput/SelectInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React, { FC, FocusEvent, ReactNode } from 'react';
import classNames from 'classnames';
import Select, { ValueType, OptionTypeBase, FocusEventHandler } from 'react-select';
import Select, {
components,
ValueType,
OptionTypeBase,
FocusEventHandler,
IndicatorProps,
} from 'react-select';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import FormLabel from '../FormLabel/FormLabel';
import InputValidationMessage from '../InputValidationMessage/InputValidationMessage';
import styles from './SelectInput.module.scss';
Expand Down Expand Up @@ -144,12 +152,19 @@ const SelectInput: FC<SelectInputProps> = ({
isDisabled,
};

const ClearIndicator = (props: IndicatorProps<OptionTypeBase>) => (
<components.ClearIndicator {...props}>
<FontAwesomeIcon icon={faTimes} size="lg" />
</components.ClearIndicator>
);

return (
<div className={wrapperClasses}>
{label && !hideLabel && <FormLabel {...labelProps}>{label}</FormLabel>}
<Select
inputId={id}
aria-label={label}
components={{ ClearIndicator }}
aria-labelledby={label && !hideLabel ? `${id}Label` : undefined}
className={inputClasses}
classNamePrefix="react-select"
Expand Down
71 changes: 57 additions & 14 deletions src/components/TextInput/TextInput.module.scss
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
.text-input {
%disabled-base {
background-color: var(--form-control-disabled-background-color);
color: var(--form-control-disabled-font-color);

&:hover {
cursor: not-allowed;
}
}

.text-input-wrapper {
box-sizing: border-box;
display: flex;
transition-duration: 300ms;
transition-property: border, background-color;
transition-timing-function: cubic-bezier(0.2, 0.8, 0.4, 1);
border: 1px solid var(--form-control-border-color);
border-radius: var(--form-control-size-md-border-radius);
box-shadow: 0 3px 0 rgba(0, 0, 0, 0.05);
background-color: var(--form-control-background-color);
padding: var(--form-control-size-md-padding);
padding: calc(var(--form-control-size-md-padding) - 1px); /* Subtract 1 pixel here to account for nested input */
width: 100%;
line-height: var(--form-control-line-height);
color: var(--form-control-font-color);
font-size: var(--form-control-size-md-font-size);

&::placeholder {
opacity: 1;
/* Override lower placeholder opacity in Firefox */
color: var(--form-control-placeholder-color);
}

&:focus {
&:focus-within {
outline: none;
border-color: var(--form-control-focus-border-color);
}

&:disabled {
background-color: var(--form-control-disabled-background-color);
color: var(--form-control-disabled-font-color);
&.disabled {
@extend %disabled-base;
}

> input {
border: none;
background-color: inherit;
width: 100%;
line-height: var(--form-control-line-height);

&::placeholder {
/* Override lower placeholder opacity in Firefox */
opacity: 1;
color: var(--form-control-placeholder-color);
}

&:focus {
outline: none;
}

&:hover {
cursor: not-allowed;
&:disabled {
@extend %disabled-base;
}
}

Expand All @@ -48,3 +68,26 @@
.text-input-label {
margin-bottom: var(--form-control-label-margin);
}

.clear-button {
/* Reset default button styles */
border: 0;
background: none;
cursor: pointer;
padding: 0;
line-height: 1;
color: inherit;
font-style: inherit;
}

.clear-icon {
transition-duration: 0.2s;
transition-property: color;
cursor: pointer;
color: var(--form-control-icon-color);
font-size: var(--form-control-text-clear-icon-font-size);

&:hover {
color: var(--form-control-icon-hover-color);
}
}
27 changes: 26 additions & 1 deletion src/components/TextInput/TextInput.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,32 @@ Use the `isDisabled` prop to mark the input as disabled. Disabled inputs can hav
</Story>
</Canvas>


## Clearable

Use the `onClear` prop to display a clear icon (x) when the input has a value. `onClear` will fire
a callback function when the clear icon is clicked, which can then be handled to clear the value.

<Canvas>
<Story name="Clearable">
{() => {
const [value, setValue] = useState('clear me');
return (
<div style={{ height: '85px' }}>
<TextInput
id="required"
value={value}
label="Label"
onChange={event => setValue(event.target.value)}
onClear={event => setValue('')}
isRequired
/>
</div>
);
}}
</Story>
</Canvas>

## With Phone Mask

Use the `type` prop to mark the input type as "tel". Use the `inputMask` prop to set the mask as "phone".
Expand Down Expand Up @@ -395,4 +421,3 @@ Use the `className` prop to add a custom class, or classes to an input.




Loading

0 comments on commit c58fd34

Please sign in to comment.