Skip to content

Commit

Permalink
feat: adding optional clearable 'x' button to input text fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jrenee42 committed Oct 19, 2021
1 parent 0cf0520 commit ee2a911
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### 2.12.0 (2021-10-19)

- [#617](https://github.com/influxdata/clockface/pull/617): Add Optional Clearing via an "x" Button to Input Textfields

### 2.11.9 (2021-09-23)

- [#672](https://github.com/influxdata/clockface/pull/672): accordion can have no icon, when there is no body, there is no icon and no interactive styling
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@influxdata/clockface",
"version": "2.11.9",
"version": "2.12.0",
"license": "MIT",
"main": "dist/index.js",
"style": "dist/index.css",
Expand Down
45 changes: 45 additions & 0 deletions src/Components/Inputs/Documentation/Inputs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,51 @@ inputsBaseStories.add(
},
}
)
inputsBaseStories.add(
'Input (Clearable Text)',
() => {
const [value, setValue] = useState<string>(
'hello world how are you it is me working on this input.....'
)

return (
<div className="story--example">
<Input
min={number('min', 0)}
max={number('max', 50)}
value={value}
monospace={boolean('monospace', false)}
onChange={e => setValue(e.target.value)}
onClear={() => setValue('')}
name={text('name', 'Name')}
titleText={text('titleText', 'Title Text')}
disabledTitleText={text('disabledTitleText', 'Disabled Title Text')}
maxLength={number('maxLength', 125)}
icon={
IconFont[
select('icon', {None: 'none', ...mapEnumKeys(IconFont)}, 'None')
]
}
style={object('style', defaultInputStyle)}
status={
ComponentStatus[
select('status', mapEnumKeys(ComponentStatus), 'Default')
]
}
size={
ComponentSize[select('size', mapEnumKeys(ComponentSize), 'Small')]
}
type={InputType.Text}
/>
</div>
)
},
{
readme: {
content: marked(InputReadme),
},
}
)

inputsBaseStories.add(
'Input (Number)',
Expand Down
71 changes: 68 additions & 3 deletions src/Components/Inputs/Input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,17 @@
.cf-input-icon {
pointer-events: none;
top: 50%;
position: absolute;
z-index: $cf-input--status-z;
transition: color 0.25s ease;
font-size: 1.1em;
transform: translate(-50%, -50%);
}

.cf-input-icon {
transform: translate(-50%, -50%);
.cf-input-icon,
.cf-input-clear-btn {
position: absolute;
z-index: $cf-input--status-z;
transition: color 0.25s ease;
color: $cf-input-text--default;
}

Expand All @@ -100,6 +103,64 @@
.cf-input-field:focus + .cf-input-icon {
color: $cf-input-text--focused;
}
/** default size is small, there are
alternate css for the other sizes */
.cf-input-clear-btn {
&.cf-dismiss-button {
background: inherit;
border: none;
transform: none;
opacity: 0.7;

&:after {
content: none;
}

&:hover,
&:focus,
&:active,
&:active:hover,
&:visited,
&:disabled,
&:disabled:hover {
background: transparent;
border: none;
box-shadow: none;
}

&:hover,
&:focus {
opacity: 1;
}
}

&.xsmall {
& .cf-dismiss-button--x {
&:before,
&:after {
width: floor($cf-form-xs-font);
}
}
}

&.medium {
& .cf-dismiss-button--x {
&:before,
&:after {
width: floor($cf-form-md-font * 1.2);
}
}
}

&.large {
& .cf-dismiss-button--x {
&:before,
&:after {
width: floor($cf-form-lg-font * 1.2);
}
}
}
}

/*
Checkbox Type Input
Expand Down Expand Up @@ -164,6 +225,10 @@
padding-left: $height;
}

&.cf-input__has-clear-btn input {
padding-right: $height * 1.05;
}

.cf-input-icon {
left: ($height / 2) + $cf-border;
}
Expand Down
32 changes: 29 additions & 3 deletions src/Components/Inputs/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ import classnames from 'classnames'
// Components
import {Icon} from '../Icon/Base/Icon'
import {StatusIndicator} from './StatusIndicator'
import {DismissButton} from '../Button/Composed/DismissButton'

// Styles
import './Input.scss'

// Types
import {
ComponentStatus,
AutoComplete,
ComponentColor,
ComponentSize,
ComponentStatus,
IconFont,
AutoComplete,
StandardFunctionProps,
InputType,
StandardFunctionProps,
} from '../../Types'

export interface InputProps extends StandardFunctionProps {
Expand Down Expand Up @@ -79,6 +81,11 @@ export interface InputProps extends StandardFunctionProps {
inputStyle?: CSSProperties
/** For use within a form, marks the input as required */
required?: boolean
/**
* Function to be called when the input field is cleared;
* if not included then the 'x' clear button will NOT be added
*/
onClear?: () => void
/** Pass in a RegEx matcher for best results */
pattern?: string
/** Pass through for container ref */
Expand All @@ -105,6 +112,7 @@ export const Input = forwardRef<InputRef, InputProps>(
value = '',
status = ComponentStatus.Default,
onBlur,
onClear,
testID = 'input-field',
pattern,
onFocus,
Expand Down Expand Up @@ -138,6 +146,7 @@ export const Input = forwardRef<InputRef, InputProps>(
'cf-input__focused': isFocused,
'cf-input__has-checkbox': type === InputType.Checkbox,
'cf-input__has-icon': icon,
'cf-input__has-clear-btn': onClear && value,
'cf-input__valid': correctStatus === ComponentStatus.Valid,
'cf-input__error': correctStatus === ComponentStatus.Error,
'cf-input__loading': correctStatus === ComponentStatus.Loading,
Expand Down Expand Up @@ -177,6 +186,22 @@ export const Input = forwardRef<InputRef, InputProps>(

const iconElement = icon && <Icon glyph={icon} className="cf-input-icon" />

const clearClasses = classnames('cf-input-clear-btn', {
large: size === ComponentSize.Large,
medium: size === ComponentSize.Medium,
xsmall: size === ComponentSize.ExtraSmall,
})

const clearElement = onClear && value && (
<DismissButton
onClick={onClear}
className={clearClasses}
titleText="clear this text field"
color={ComponentColor.Tertiary}
size={size}
/>
)

const title =
status === ComponentStatus.Disabled ? disabledTitleText : titleText

Expand Down Expand Up @@ -220,6 +245,7 @@ export const Input = forwardRef<InputRef, InputProps>(
required={required}
pattern={pattern}
/>
{clearElement}
{type === InputType.Checkbox && <div className={inputCheckboxClass} />}
{iconElement}
{children}
Expand Down

0 comments on commit ee2a911

Please # to comment.