Skip to content

Commit

Permalink
feat(PasswordInput): support warn and inline props (carbon-design…
Browse files Browse the repository at this point in the history
…-system#8366)

* feat(PasswordInput): support `warn` prop

* feat(PasswordInput): support `inline` prop

* fix(text-input): realign inline text input elements

* docs(TextInput): format proptypes

* chore: update snapshots

* fix(text-input): remove center alignment

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
emyarod and kodiakhq[bot] authored Apr 23, 2021
1 parent be8844d commit d76b928
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@
}
}

.#{$prefix}--text-input__field-wrapper.#{$prefix}--password-input__field-wrapper
.#{$prefix}--text-input__invalid-icon {
right: $carbon--spacing-07;
}

.#{$prefix}--password-input-wrapper .#{$prefix}--text-input__invalid-icon {
right: $carbon--spacing-08;
}
Expand Down
9 changes: 9 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5571,6 +5571,9 @@ Map {
"isRequired": true,
"type": "string",
},
"inline": Object {
"type": "bool",
},
"invalid": Object {
"type": "bool",
},
Expand Down Expand Up @@ -5633,6 +5636,12 @@ Map {
],
"type": "oneOfType",
},
"warn": Object {
"type": "bool",
},
"warnText": Object {
"type": "node",
},
},
"render": [Function],
},
Expand Down
121 changes: 102 additions & 19 deletions packages/react/src/components/TextInput/PasswordInput.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import React, { useState } from 'react';
import React, { useContext, useState } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { settings } from 'carbon-components';
import { View16, ViewOff16, WarningFilled16 } from '@carbon/icons-react';
import {
View16,
ViewOff16,
WarningAltFilled16,
WarningFilled16,
} from '@carbon/icons-react';
import { textInputProps } from './util';
import { FormContext } from '../FluidForm';

const { prefix } = settings;

Expand All @@ -17,6 +23,7 @@ const PasswordInput = React.forwardRef(function PasswordInput(
onChange,
onClick,
hideLabel,
inline,
invalid,
invalidText,
helperText,
Expand All @@ -26,6 +33,8 @@ const PasswordInput = React.forwardRef(function PasswordInput(
hidePasswordLabel = 'Hide password',
showPasswordLabel = 'Show password',
size,
warn,
warnText,
...other
},
ref
Expand All @@ -34,6 +43,7 @@ const PasswordInput = React.forwardRef(function PasswordInput(
const togglePasswordVisibility = () =>
setInputType(inputType === 'password' ? 'text' : 'password');
const errorId = id + '-error-msg';
const warnId = id + '-warn-msg';
const textInputClasses = classNames(
`${prefix}--text-input`,
`${prefix}--password-input`,
Expand Down Expand Up @@ -62,23 +72,58 @@ const PasswordInput = React.forwardRef(function PasswordInput(
ref,
...other,
};
const inputWrapperClasses = classNames(
`${prefix}--form-item`,
`${prefix}--text-input-wrapper`,
`${prefix}--password-input-wrapper`,
{
[`${prefix}--text-input-wrapper--light`]: light,
[`${prefix}--text-input-wrapper--inline`]: inline,
}
);
const labelClasses = classNames(`${prefix}--label`, {
[`${prefix}--visually-hidden`]: hideLabel,
[`${prefix}--label--disabled`]: disabled,
[`${prefix}--label--inline`]: inline,
[`${prefix}--label--inline--${size}`]: inline && !!size,
});
const helperTextClasses = classNames(`${prefix}--form__helper-text`, {
[`${prefix}--form__helper-text--disabled`]: disabled,
[`${prefix}--form__helper-text--inline`]: inline,
});
const fieldOuterWrapperClasses = classNames(
`${prefix}--text-input__field-outer-wrapper`,
{
[`${prefix}--text-input__field-outer-wrapper--inline`]: inline,
}
);
const fieldWrapperClasses = classNames(
`${prefix}--text-input__field-wrapper`,
{
[`${prefix}--text-input__field-wrapper--warning`]: !invalid && warn,
}
);
const label = labelText ? (
<label htmlFor={id} className={labelClasses}>
{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 passwordIsVisible = inputType === 'text';
const passwordVisibilityIcon = passwordIsVisible ? (
<ViewOff16 className={`${prefix}--icon-visibility-off`} />
Expand All @@ -100,7 +145,13 @@ const PasswordInput = React.forwardRef(function PasswordInput(
const input = (
<>
<input
{...textInputProps({ invalid, sharedTextInputProps, errorId })}
{...textInputProps({
invalid,
sharedTextInputProps,
errorId,
warn,
warnId,
})}
disabled={disabled}
data-toggle-password-visibility={inputType === 'password'}
/>
Expand All @@ -122,19 +173,36 @@ const PasswordInput = React.forwardRef(function PasswordInput(
<div className={helperTextClasses}>{helperText}</div>
) : null;

const { isFluid } = useContext(FormContext);

return (
<div
className={`${prefix}--form-item ${prefix}--text-input-wrapper ${prefix}--password-input-wrapper`}>
{label}
<div
className={`${prefix}--text-input__field-wrapper`}
data-invalid={invalid || null}>
{invalid && (
<WarningFilled16 className={`${prefix}--text-input__invalid-icon`} />
)}
{input}
<div className={inputWrapperClasses}>
{!inline ? (
label
) : (
<div className={`${prefix}--text-input__label-helper-wrapper`}>
{label}
{!isFluid && helper}
</div>
)}
<div className={fieldOuterWrapperClasses}>
<div className={fieldWrapperClasses} data-invalid={invalid || 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 && !inline && error}
</div>
{!isFluid && error}
{!invalid && !warn && !isFluid && !inline && helper}
</div>
{error ? error : helper}
</div>
);
});
Expand Down Expand Up @@ -176,6 +244,11 @@ PasswordInput.propTypes = {
*/
id: PropTypes.string.isRequired,

/**
* `true` to use the inline version.
*/
inline: PropTypes.bool,

/**
* Specify whether the control is currently invalid
*/
Expand Down Expand Up @@ -240,6 +313,16 @@ PasswordInput.propTypes = {
* Provide the current value of the `<input>`
*/
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

/**
* 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.node,
};

PasswordInput.defaultProps = {
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ TextInput.propTypes = {
* 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
*/
Expand Down

0 comments on commit d76b928

Please sign in to comment.