Skip to content

Commit

Permalink
feat(text-input): add warn prop (#5918)
Browse files Browse the repository at this point in the history
* feat(text-input): add warn prop

* fix(text-input): add aria-describedby for warning state

* fix(text-input): fix prettier issues

* fix(text-input): hide helper text when warning message shown

* fix(text-input): support props.warn with fluid form

* fix(text-input): correct warning icon

* fix(text-input): fix style-lint issues

Co-authored-by: Andrea N. Cardona <[email protected]>
Co-authored-by: TJ Egan <[email protected]>
  • Loading branch information
3 people authored Jul 20, 2020
1 parent 4d9cf18 commit a5e27b7
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 21 deletions.
36 changes: 29 additions & 7 deletions packages/components/docs/sass.md
Original file line number Diff line number Diff line change
Expand Up @@ -7003,7 +7003,6 @@ $text-error: if(
- [file-uploader [mixin]](#file-uploader-mixin)
- [form [mixin]](#form-mixin)
- [number-input [mixin]](#number-input-mixin)
- [select [mixin]](#select-mixin)

### ✅icon-01 [variable]

Expand Down Expand Up @@ -7393,6 +7392,7 @@ $support-03: if(
- [carbon--theme [mixin]](#carbon--theme-mixin)
- [inline-notifications [mixin]](#inline-notifications-mixin)
- [toast-notifications [mixin]](#toast-notifications-mixin)
- [text-input [mixin]](#text-input-mixin)

### ✅support-04 [variable]

Expand Down Expand Up @@ -17979,20 +17979,31 @@ Form styles

input[data-invalid],
.#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--text-input--warn,
.#{$prefix}--text-area__wrapper[data-invalid],
.#{$prefix}--select-input__wrapper[data-invalid],
.#{$prefix}--time-picker[data-invalid],
.#{$prefix}--list-box[data-invalid] {
~ .#{$prefix}--form-requirement {
max-height: rem(200px);
display: block;
}
}

input[data-invalid],
.#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--text-area__wrapper[data-invalid],
.#{$prefix}--select-input__wrapper[data-invalid],
.#{$prefix}--time-picker[data-invalid],
.#{$prefix}--list-box[data-invalid] {
~ .#{$prefix}--form-requirement {
color: $text-error;
}
}

//Fluid Form
.#{$prefix}--form--fluid
.#{$prefix}--text-input__field-wrapper[data-invalid] {
.#{$prefix}--form--fluid .#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--form--fluid .#{$prefix}--text-input__field-wrapper[data-warn] {
display: block;
}

Expand All @@ -18017,7 +18028,6 @@ Form styles
.#{$prefix}--form-requirement {
@include reset;
@include type-style('caption-01');

margin: $carbon--spacing-02 0 0;
max-height: 0;
overflow: hidden;
Expand Down Expand Up @@ -22448,7 +22458,6 @@ Select styles

.#{$prefix}--form-requirement {
display: block;
color: $text-error;
font-weight: 400;
overflow: visible;
}
Expand Down Expand Up @@ -22600,7 +22609,6 @@ Select styles
- [ui-04 [variable]](#ui-04-variable)
- [hover-ui [variable]](#hover-ui-variable)
- [disabled-02 [variable]](#disabled-02-variable)
- [text-error [variable]](#text-error-variable)
- [field-02 [variable]](#field-02-variable)
- [ui-05 [variable]](#ui-05-variable)
- [support-01 [variable]](#support-01-variable)
Expand Down Expand Up @@ -23806,6 +23814,15 @@ Text input styles
fill: $support-01;
}

.#{$prefix}--text-input__invalid-icon--warning {
fill: $support-03;

path[data-icon-path='inner-path'] {
opacity: 1;
fill: $carbon__black-100;
}
}

// TODO: deprecate this style block
.#{$prefix}--text-input--password__visibility {
@include tooltip--trigger('icon', 'bottom');
Expand Down Expand Up @@ -23929,12 +23946,16 @@ Text input styles
display: none;
}

.#{$prefix}--form--fluid .#{$prefix}--text-input--invalid {
.#{$prefix}--form--fluid .#{$prefix}--text-input--invalid,
.#{$prefix}--form--fluid .#{$prefix}--text-input--warn {
border-bottom: none;
}

.#{$prefix}--form--fluid
.#{$prefix}--text-input--invalid
+ .#{$prefix}--text-input__divider,
.#{$prefix}--form--fluid
.#{$prefix}--text-input--warn
+ .#{$prefix}--text-input__divider {
display: block;
margin: 0 1rem;
Expand Down Expand Up @@ -24013,6 +24034,7 @@ Text input styles
- [carbon--spacing-08 [variable]](#carbon--spacing-08-variable)
- [field-02 [variable]](#field-02-variable)
- [support-01 [variable]](#support-01-variable)
- [support-03 [variable]](#support-03-variable)
- [icon-02 [variable]](#icon-02-variable)
- [disabled-01 [variable]](#disabled-01-variable)
- [disabled-02 [variable]](#disabled-02-variable)
Expand Down
15 changes: 13 additions & 2 deletions packages/components/src/components/form/_form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,31 @@

input[data-invalid],
.#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--text-input--warn,
.#{$prefix}--text-area__wrapper[data-invalid],
.#{$prefix}--select-input__wrapper[data-invalid],
.#{$prefix}--time-picker[data-invalid],
.#{$prefix}--list-box[data-invalid] {
~ .#{$prefix}--form-requirement {
max-height: rem(200px);
display: block;
}
}

input[data-invalid],
.#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--text-area__wrapper[data-invalid],
.#{$prefix}--select-input__wrapper[data-invalid],
.#{$prefix}--time-picker[data-invalid],
.#{$prefix}--list-box[data-invalid] {
~ .#{$prefix}--form-requirement {
color: $text-error;
}
}

//Fluid Form
.#{$prefix}--form--fluid
.#{$prefix}--text-input__field-wrapper[data-invalid] {
.#{$prefix}--form--fluid .#{$prefix}--text-input__field-wrapper[data-invalid],
.#{$prefix}--form--fluid .#{$prefix}--text-input__field-wrapper[data-warn] {
display: block;
}

Expand Down
1 change: 0 additions & 1 deletion packages/components/src/components/select/_select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@

.#{$prefix}--form-requirement {
display: block;
color: $text-error;
font-weight: 400;
overflow: visible;
}
Expand Down
15 changes: 14 additions & 1 deletion packages/components/src/components/text-input/_text-input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@
fill: $support-01;
}

.#{$prefix}--text-input__invalid-icon--warning {
fill: $support-03;

path[data-icon-path='inner-path'] {
opacity: 1;
fill: $carbon__black-100;
}
}

// TODO: deprecate this style block
.#{$prefix}--text-input--password__visibility {
@include tooltip--trigger('icon', 'bottom');
Expand Down Expand Up @@ -206,12 +215,16 @@
display: none;
}

.#{$prefix}--form--fluid .#{$prefix}--text-input--invalid {
.#{$prefix}--form--fluid .#{$prefix}--text-input--invalid,
.#{$prefix}--form--fluid .#{$prefix}--text-input--warn {
border-bottom: none;
}

.#{$prefix}--form--fluid
.#{$prefix}--text-input--invalid
+ .#{$prefix}--text-input__divider,
.#{$prefix}--form--fluid
.#{$prefix}--text-input--warn
+ .#{$prefix}--text-input__divider {
display: block;
margin: 0 1rem;
Expand Down
8 changes: 8 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5283,6 +5283,8 @@ Map {
"onChange": [Function],
"onClick": [Function],
"type": "text",
"warn": false,
"warnText": "",
},
"propTypes": Object {
"className": Object {
Expand Down Expand Up @@ -5364,6 +5366,12 @@ Map {
],
"type": "oneOfType",
},
"warn": Object {
"type": "bool",
},
"warnText": Object {
"type": "string",
},
},
"render": [Function],
},
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/components/TextInput/TextInput-story.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ const props = {
'Form validation UI content (invalidText)',
'A valid value is required'
),
warn: boolean('Show warning state (warn)', false),
warnText: text(
'Warning state text (warnText)',
'This will overwrite your current settings'
),
helperText: text('Helper text (helperText)', 'Optional help text'),
inline: boolean('Inline variant (inline)', false),
onClick: action('onClick'),
Expand Down
57 changes: 48 additions & 9 deletions packages/react/src/components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
import React, { useContext } from 'react';
import classNames from 'classnames';
import { settings } from 'carbon-components';
import { WarningFilled16 } from '@carbon/icons-react';
import { WarningFilled16, WarningAltFilled16 } from '@carbon/icons-react';
import PasswordInput from './PasswordInput';
import ControlledPasswordInput from './ControlledPasswordInput';
import { textInputProps } from './util';
Expand All @@ -28,6 +28,8 @@ const TextInput = React.forwardRef(function TextInput(
hideLabel,
invalid,
invalidText,
warn,
warnText,
helperText,
light,
size,
Expand All @@ -37,9 +39,11 @@ const TextInput = React.forwardRef(function TextInput(
ref
) {
const errorId = id + '-error-msg';
const warnId = id + '-warn-msg';
const textInputClasses = classNames(`${prefix}--text-input`, className, {
[`${prefix}--text-input--light`]: light,
[`${prefix}--text-input--invalid`]: invalid,
[`${prefix}--text-input--warn`]: warn,
[`${prefix}--text-input--${size}`]: size,
});
const sharedTextInputProps = {
Expand Down Expand Up @@ -90,13 +94,30 @@ const TextInput = React.forwardRef(function TextInput(
{labelText}
</label>
) : null;
const error = invalid ? (
<div className={`${prefix}--form-requirement`} id={errorId}>
{invalidText}
</div>
) : null;
let error = null;
if (invalid) {
error = (
<div className={`${prefix}--form-requirement`} id={errorId}>
{invalidText}
</div>
);
} else if (warn) {
error = (
<div className={`${prefix}--form-requirement`} id={warnId}>
{warnText}
</div>
);
}
const input = (
<input {...textInputProps({ invalid, sharedTextInputProps, errorId })} />
<input
{...textInputProps({
invalid,
sharedTextInputProps,
errorId,
warn,
warnId,
})}
/>
);
const helper = helperText ? (
<div className={helperTextClasses}>{helperText}</div>
Expand All @@ -117,19 +138,25 @@ const TextInput = React.forwardRef(function TextInput(
<div className={fieldOuterWrapperClasses}>
<div
className={`${prefix}--text-input__field-wrapper`}
data-invalid={invalid || null}>
data-invalid={invalid || null}
data-warn={warn || null}>
{invalid && (
<WarningFilled16
className={`${prefix}--text-input__invalid-icon`}
/>
)}
{!invalid && warn && (
<WarningAltFilled16
className={`${prefix}--text-input__invalid-icon ${prefix}--text-input__invalid-icon--warning`}
/>
)}
{input}
{isFluid && <hr className={`${prefix}--text-input__divider`} />}
{/* <hr className={`${prefix}--text-input__divider`} /> */}
{isFluid && !inline && error}
</div>
{!isFluid && error}
{!invalid && !isFluid && !inline && helper}
{!invalid && !warn && !isFluid && !inline && helper}
</div>
</div>
);
Expand Down Expand Up @@ -211,6 +238,16 @@ TextInput.propTypes = {
*/
invalidText: PropTypes.string,

/**
* Specify whether the control is currently in warning state
*/
warn: PropTypes.bool,

/**
* Provide the text that is displayed when the control is in warning state
*/
warnText: PropTypes.string,

/**
* Provide text that is used alongside the control label for additional help
*/
Expand All @@ -233,6 +270,8 @@ TextInput.defaultProps = {
onClick: () => {},
invalid: false,
invalidText: '',
warn: false,
warnText: '',
helperText: '',
light: false,
inline: false,
Expand Down
13 changes: 12 additions & 1 deletion packages/react/src/components/TextInput/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ const invalidProps = ({ invalid, errorId }) => ({
'aria-describedby': errorId,
});

export const textInputProps = ({ invalid, sharedTextInputProps, errorId }) => ({
const warnProps = ({ warnId }) => ({
'aria-describedby': warnId,
});

export const textInputProps = ({
invalid,
sharedTextInputProps,
errorId,
warn,
warnId,
}) => ({
...sharedTextInputProps,
...(invalid ? invalidProps({ invalid, errorId }) : {}),
...(!invalid && warn ? warnProps({ warnId }) : {}),
});

0 comments on commit a5e27b7

Please sign in to comment.