Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FormGroup, FormSelect, TextInput, TextArea): Add warning state #4554

Merged
merged 5 commits into from Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-catalog-view-extension/package.json
Expand Up @@ -35,7 +35,7 @@
"clean": "rimraf dist"
},
"dependencies": {
"@patternfly/patternfly": "4.23.1",
"@patternfly/patternfly": "4.23.2",
"@patternfly/react-core": "^4.31.3",
"@patternfly/react-styles": "^4.4.6",
"classnames": "^2.2.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-charts/package.json
Expand Up @@ -29,7 +29,7 @@
},
"homepage": "https://github.com/patternfly/patternfly-react#readme",
"dependencies": {
"@patternfly/patternfly": "4.23.1",
"@patternfly/patternfly": "4.23.2",
"@patternfly/react-styles": "^4.4.6",
"@patternfly/react-tokens": "^4.5.3",
"hoist-non-react-statics": "^3.3.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-core/package.json
Expand Up @@ -45,7 +45,7 @@
"tslib": "^1.11.1"
},
"devDependencies": {
"@patternfly/patternfly": "4.23.1",
"@patternfly/patternfly": "4.23.2",
"@rollup/plugin-commonjs": "^11.0.2",
"@rollup/plugin-node-resolve": "^7.1.1",
"@rollup/plugin-replace": "^2.3.1",
Expand Down
13 changes: 9 additions & 4 deletions packages/react-core/src/components/Form/FormGroup.tsx
Expand Up @@ -17,9 +17,10 @@ export interface FormGroupProps extends Omit<React.HTMLProps<HTMLDivElement>, 'l
isRequired?: boolean;
/**
* Sets the FormGroup validated. If you set to success, text color of helper text will be modified to indicate valid state.
* If set to error, text color of helper text will be modified to indicate error state.
* If set to error, text color of helper text will be modified to indicate error state.
* If set to warning, text color of helper text will be modified to indicate warning state.
*/
validated?: 'success' | 'error' | 'default';
validated?: 'success' | 'warning' | 'error' | 'default';
/** Sets the FormGroup isInline. */
isInline?: boolean;
/** Removes top spacer from label. */
Expand Down Expand Up @@ -57,7 +58,11 @@ export const FormGroup: React.FunctionComponent<FormGroupProps> = ({
helperText
) : (
<div
className={css(styles.formHelperText, validated === ValidatedOptions.success && styles.modifiers.success)}
className={css(
styles.formHelperText,
validated === ValidatedOptions.success && styles.modifiers.success,
validated === ValidatedOptions.warning && styles.modifiers.warning
)}
id={`${fieldId}-helper`}
aria-live="polite"
>
Expand All @@ -76,7 +81,7 @@ export const FormGroup: React.FunctionComponent<FormGroupProps> = ({
</div>
);

const showValidHelperTxt = (validationType: 'success' | 'error' | 'default') =>
const showValidHelperTxt = (validationType: 'success' | 'warning' | 'error' | 'default') =>
validationType !== ValidatedOptions.error && helperText ? validHelperText : '';

return (
Expand Down
Expand Up @@ -137,6 +137,16 @@ describe('FormGroup component', () => {
expect(view).toMatchSnapshot();
});

test('should render form group validated warning variant', () => {
const view = mount(
<FormGroup label="label" fieldId="label-id" validated={ValidatedOptions.warning} helperText="Validated FormGroup">
<input id="id" />
</FormGroup>
);
expect(view.find('.pf-c-form__helper-text.pf-m-warning').length).toBe(1);
expect(view).toMatchSnapshot();
});

test('should render correctly when label is not a string with Children = Array', () => {
const view = mount(
<FormGroup fieldId="id" label={returnFunction()}>
Expand Down
Expand Up @@ -250,6 +250,49 @@ exports[`FormGroup component should render form group validated success variant
</FormGroup>
`;

exports[`FormGroup component should render form group validated warning variant 1`] = `
<FormGroup
fieldId="label-id"
helperText="Validated FormGroup"
label="label"
validated="warning"
>
<div
className="pf-c-form__group"
>
<div
className="pf-c-form__group-label"
>
<label
className="pf-c-form__label"
htmlFor="label-id"
>
<span
className="pf-c-form__label-text"
>
label
</span>
</label>

</div>
<div
className="pf-c-form__group-control"
>
<input
id="id"
/>
<div
aria-live="polite"
className="pf-c-form__helper-text pf-m-warning"
id="label-id-helper"
>
Validated FormGroup
</div>
</div>
</div>
</FormGroup>
`;

exports[`FormGroup component should render form group variant with function helperText 1`] = `
<FormGroup
fieldId="label-id"
Expand Down
2 changes: 1 addition & 1 deletion packages/react-core/src/components/Form/examples/Form.md
Expand Up @@ -359,7 +359,7 @@ class InvalidForm extends React.Component {
if (parseInt(value, 10) >= 21) {
this.setState({ validated: 'success', helperText: 'Enjoy your stay' });
} else {
this.setState({ validated: 'error', invalidText: 'You must be at least 21 to continue' });
this.setState({ validated: 'warning', helperText: 'You must be at least 21 to continue' });
}
} else {
this.setState({ validated: 'error', invalidText: 'Age has to be a number' });
Expand Down
5 changes: 3 additions & 2 deletions packages/react-core/src/components/FormSelect/FormSelect.tsx
Expand Up @@ -18,7 +18,7 @@ export interface FormSelectProps
* If set to success, select will be modified to indicate valid state.
* If set to error, select will be modified to indicate error state.
*/
validated?: 'success' | 'error' | 'default';
validated?: 'success' | 'warning' | 'error' | 'default';
/** Flag indicating the FormSelect is disabled */
isDisabled?: boolean;
/** Sets the FormSelectrequired. */
Expand Down Expand Up @@ -67,7 +67,8 @@ export class FormSelect extends React.Component<FormSelectProps> {
className={css(
styles.formControl,
className,
validated === ValidatedOptions.success && styles.modifiers.success
validated === ValidatedOptions.success && styles.modifiers.success,
validated === ValidatedOptions.warning && styles.modifiers.warning
)}
aria-invalid={validated === ValidatedOptions.error}
{...getOUIAProps(FormSelect.displayName, ouiaId, ouiaSafe)}
Expand Down
Expand Up @@ -147,6 +147,17 @@ test('validated error FormSelect input', () => {
expect(view).toMatchSnapshot();
});

test('validated warning FormSelect input', () => {
const view = shallow(
<FormSelect validated={ValidatedOptions.warning} aria-label="validated FormSelect">
<FormSelectOption key={1} value={props.options[1].value} label={props.options[1].label} />
</FormSelect>
);
expect(view.find('.pf-c-form-control.pf-m-warning').length).toBe(1);
expect(view).toMatchSnapshot();
});


test('required FormSelect input', () => {
const view = shallow(
<FormSelect required aria-label="required FormSelect">
Expand Down
Expand Up @@ -251,7 +251,7 @@ exports[`required FormSelect input 1`] = `
aria-invalid={false}
aria-label="required FormSelect"
className="pf-c-form-control"
data-ouia-component-id={9}
data-ouia-component-id={10}
data-ouia-component-type="PF4/FormSelect"
data-ouia-safe={true}
disabled={false}
Expand Down Expand Up @@ -314,3 +314,26 @@ exports[`validated success FormSelect input 1`] = `
/>
</select>
`;

exports[`validated warning FormSelect input 1`] = `
<select
aria-invalid={false}
aria-label="validated FormSelect"
className="pf-c-form-control pf-m-warning"
data-ouia-component-id={9}
data-ouia-component-type="PF4/FormSelect"
data-ouia-safe={true}
disabled={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
required={false}
value=""
>
<FormSelectOption
key="1"
label="Mr"
value="mr"
/>
</select>
`;
5 changes: 3 additions & 2 deletions packages/react-core/src/components/TextArea/TextArea.tsx
Expand Up @@ -19,7 +19,7 @@ export interface TextAreaProps extends Omit<HTMLProps<HTMLTextAreaElement>, 'onC
* If set to success, textarea will be modified to indicate valid state.
* If set to error, textarea will be modified to indicate error state.
*/
validated?: 'success' | 'error' | 'default';
validated?: 'success' | 'warning' | 'error' | 'default';
/** Value of the TextArea. */
value?: string | number;
/** A callback for when the TextArea value changes. */
Expand Down Expand Up @@ -64,7 +64,8 @@ export class TextArea extends React.Component<TextAreaProps> {
styles.formControl,
className,
resizeOrientation !== TextAreResizeOrientation.both && styles.modifiers[orientation],
validated === ValidatedOptions.success && styles.modifiers.success
validated === ValidatedOptions.success && styles.modifiers.success,
validated === ValidatedOptions.warning && styles.modifiers.warning
)}
onChange={this.handleChange}
{...(typeof this.props.defaultValue !== 'string' && { value })}
Expand Down
Expand Up @@ -36,6 +36,14 @@ test('validated text area success', () => {
expect(view).toMatchSnapshot();
});

test('validated text area warning', () => {
const view = shallow(
<TextArea {...props} required validated={ValidatedOptions.warning} aria-label="validated textarea" />
);
expect(view.find('.pf-c-form-control.pf-m-warning').length).toBe(1);
expect(view).toMatchSnapshot();
});

test('validated text area error', () => {
const view = shallow(
<TextArea {...props} required validated={ValidatedOptions.error} aria-label="validated textarea" />
Expand Down
Expand Up @@ -55,6 +55,17 @@ exports[`validated text area success 1`] = `
/>
`;

exports[`validated text area warning 1`] = `
<textarea
aria-invalid={false}
aria-label="validated textarea"
className="pf-c-form-control pf-m-warning"
onChange={[Function]}
required={true}
value="test textarea"
/>
`;

exports[`vertically resizable text area 1`] = `
<textarea
aria-invalid={false}
Expand Down
Expand Up @@ -92,14 +92,14 @@ class InvalidTextArea extends React.Component {
},
this.simulateNetworkCall(() => {
if (value && value.length > 0) {
if (value.length > 10) {
if (value.length >= 10) {
this.setState({validated: 'success', helperText: 'Thanks for your comments!'});
} else {
this.setState({validated: 'error', invalidText: 'Your being too brief, please enter at least 10 characters.'});
}
}
else {
this.setState({validated: 'error', invalidText: 'You must have something to say'});
this.setState({validated: 'warning', helperText: 'You must have something to say'});
}
})
);
Expand Down
5 changes: 3 additions & 2 deletions packages/react-core/src/components/TextInput/TextInput.tsx
Expand Up @@ -30,7 +30,7 @@ export interface TextInputProps extends Omit<React.HTMLProps<HTMLInputElement>,
* If set to success, input will be modified to indicate valid state.
* If set to error, input will be modified to indicate error state.
*/
validated?: 'success' | 'error' | 'default';
validated?: 'success' | 'warning' | 'error' | 'default';
/** A callback for when the input value changes. */
onChange?: (value: string, event: React.FormEvent<HTMLInputElement>) => void;
/** Type that the input accepts. */
Expand Down Expand Up @@ -60,7 +60,7 @@ export class TextInputBase extends React.Component<TextInputProps> {
'aria-label': null,
className: '',
isRequired: false,
validated: 'default' as 'success' | 'error' | 'default',
validated: 'default' as 'success' | 'warning' | 'error' | 'default',
isDisabled: false,
isReadOnly: false,
type: TextInputTypes.text,
Expand Down Expand Up @@ -101,6 +101,7 @@ export class TextInputBase extends React.Component<TextInputProps> {
className={css(
styles.formControl,
validated === ValidatedOptions.success && styles.modifiers.success,
validated === ValidatedOptions.warning && styles.modifiers.warning,
className
)}
onChange={this.handleChange}
Expand Down
Expand Up @@ -46,6 +46,15 @@ test('validated text input success', () => {
expect(view).toMatchSnapshot();
});

test('validated text input success', () => {
const view = mount(
<TextInput {...props} required validated={ValidatedOptions.warning} aria-label="validated text input" />
);
expect(view.find('.pf-c-form-control.pf-m-warning').length).toBe(1);
expect(view).toMatchSnapshot();
});


test('validated text input', () => {
const view = shallow(
<TextInput {...props} required validated={ValidatedOptions.error} aria-label="validated text input" />
Expand Down
Expand Up @@ -106,3 +106,39 @@ exports[`validated text input success 1`] = `
</TextInputBase>
</ForwardRef>
`;

exports[`validated text input success 2`] = `
<ForwardRef
aria-label="validated text input"
onChange={[MockFunction]}
required={true}
validated="warning"
value="test input"
>
<TextInputBase
aria-label="validated text input"
className=""
innerRef={null}
isDisabled={false}
isReadOnly={false}
isRequired={false}
onChange={[MockFunction]}
required={true}
type="text"
validated="warning"
value="test input"
>
<input
aria-invalid={false}
aria-label="validated text input"
className="pf-c-form-control pf-m-warning"
disabled={false}
onChange={[Function]}
readOnly={false}
required={false}
type="text"
value="test input"
/>
</TextInputBase>
</ForwardRef>
`;
1 change: 1 addition & 0 deletions packages/react-core/src/helpers/constants.ts
Expand Up @@ -7,5 +7,6 @@ export const KEYHANDLER_DIRECTION = { UP: 'up', DOWN: 'down', RIGHT: 'right', LE
export enum ValidatedOptions {
success = 'success',
error = 'error',
warning = 'warning',
default = 'default'
}
2 changes: 1 addition & 1 deletion packages/react-docs/package.json
Expand Up @@ -25,7 +25,7 @@
"dependencies": {
"@mdx-js/mdx": "^1.1.5",
"@mdx-js/react": "^1.1.5",
"@patternfly/patternfly": "4.23.1",
"@patternfly/patternfly": "4.23.2",
"@patternfly/react-catalog-view-extension": "^4.4.26",
"@patternfly/react-charts": "^6.5.8",
"@patternfly/react-core": "^4.31.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-icons/package.json
Expand Up @@ -32,7 +32,7 @@
"@fortawesome/free-brands-svg-icons": "^5.7.2",
"@fortawesome/free-regular-svg-icons": "^5.7.2",
"@fortawesome/free-solid-svg-icons": "^5.7.2",
"@patternfly/patternfly": "4.23.1",
"@patternfly/patternfly": "4.23.2",
"fs-extra": "^6.0.1",
"glob": "^7.1.2",
"rimraf": "^2.6.2",
Expand Down
5 changes: 5 additions & 0 deletions packages/react-integration/cypress/integration/form.spec.ts
Expand Up @@ -49,6 +49,11 @@ describe('Form Demo Test', () => {
cy.get('#age-validated').then(textinput => {
expect(textinput.attr('aria-invalid')).to.be.equal('false');
});
cy.get('#age-validated').clear();
cy.get('#age2-helper.pf-m-warning').should('exist');
cy.get('#age-validated').then(textinput => {
expect(textinput.attr('aria-invalid')).to.be.equal('false');
});
});

it('Verify form group label has no top spacer', () => {
Expand Down