Skip to content

Commit

Permalink
Refactor(web-react): Remove useValidationText hook
Browse files Browse the repository at this point in the history
- Removed useValidationText hook and implement ValidationText same way
as HelperText component
- Connected ValidationText with its input by aria-describedby
  • Loading branch information
pavelklibani committed Sep 7, 2023
1 parent 7302bfd commit f1d1d9e
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 103 deletions.
19 changes: 9 additions & 10 deletions packages/web-react/src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { forwardRef, ForwardedRef } from 'react';
import classNames from 'classnames';
import { useStyleProps } from '../../hooks';
import { SpiritCheckboxProps } from '../../types';
import { useValidationText, HelperText } from '../Field';
import { HelperText, ValidationText } from '../Field';
import useAriaDescribedBy from '../Field/useAriaDescribedBy';
import { useCheckboxStyleProps } from './useCheckboxStyleProps';

Expand Down Expand Up @@ -32,14 +32,6 @@ const _Checkbox = (props: SpiritCheckboxProps, ref: ForwardedRef<HTMLInputElemen
ariaDescribedBy,
});

const renderValidationText = useValidationText({
validationId: validationTextId,
validationElementType: 'span',
validationState,
validationText,
validationTextClassName: classProps.validationText,
});

return (
<label {...styleProps} htmlFor={id} className={classNames(classProps.root, styleProps.className)}>
<input
Expand All @@ -61,7 +53,14 @@ const _Checkbox = (props: SpiritCheckboxProps, ref: ForwardedRef<HTMLInputElemen
{helperText}
</HelperText>
)}
{renderValidationText}
{validationState && validationText && (
<ValidationText
className={classProps.validationText}
elementType="span"
id={validationTextId}
validationText={validationText}
/>
)}
</span>
</label>
);
Expand Down
10 changes: 7 additions & 3 deletions packages/web-react/src/components/Field/ValidationText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ import { ValidationTextProp } from '../../types';
export interface ValidationTextProps extends ValidationTextProp {
className?: string;
elementType?: ElementType;
id?: string;
}

const defaultProps = {
className: undefined,
elementType: 'div',
id: undefined,
};

export const ValidationText = (props: ValidationTextProps) => {
const { className, validationText, elementType: ElementTag = 'div' } = props;
const { className, validationText, elementType: ElementTag = 'div', id } = props;

return Array.isArray(validationText) ? (
<ul className={className}>
<ul className={className} id={id}>
{validationText.map((item) => (
<li key={`validationText_${item}`}>{item}</li>
))}
</ul>
) : (
<ElementTag className={className}>{validationText}</ElementTag>
<ElementTag className={className} id={id}>
{validationText}
</ElementTag>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import HelperText from '../HelperText';

describe('HelperText', () => {
it('should render helper text', () => {
const dom = render(<HelperText className="HelperText__helperText">Helper Text</HelperText>);

const element = dom.container.querySelector('div') as HTMLElement;
expect(element).not.toBeNull();
expect(element.textContent).toBe('Helper Text');
});

it('should render with custom element type', () => {
const { container } = render(<HelperText elementType="span">Helper Text</HelperText>);

const element = container.querySelector('span') as HTMLElement;
expect(element).not.toBeNull();
expect(element.textContent).toBe('Helper Text');
});

it('should render with className and id', () => {
const { container } = render(
<HelperText className="test__helperText" id="test__helperTextId">
Helper Text
</HelperText>,
);

const element = container.querySelector('.test__helperText') as HTMLElement;
expect(element).not.toBeNull();
expect(element.getAttribute('id')).toBe('test__helperTextId');
expect(element.textContent).toBe('Helper Text');
});
});

This file was deleted.

1 change: 0 additions & 1 deletion packages/web-react/src/components/Field/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export * from './ValidationText';
export * from './HelperText';
export * from './useValidationText';
export * from './useAriaDescribedBy';
export { default as ValidationText } from './ValidationText';
export { default as HelperText } from './HelperText';
27 changes: 0 additions & 27 deletions packages/web-react/src/components/Field/useValidationText.tsx

This file was deleted.

14 changes: 5 additions & 9 deletions packages/web-react/src/components/FieldGroup/FieldGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from 'react';
import classNames from 'classnames';
import { SpiritFieldGroupProps } from '../../types';
import { useStyleProps } from '../../hooks';
import { useValidationText } from '../Field/useValidationText';
import useAriaDescribedBy from '../Field/useAriaDescribedBy';
import HelperText from '../Field/HelperText';
import ValidationText from '../Field/ValidationText';
import { useFieldGroupStyleProps } from './useFieldGroupStyleProps';

const FieldGroup = (props: SpiritFieldGroupProps) => {
Expand All @@ -26,19 +26,13 @@ const FieldGroup = (props: SpiritFieldGroupProps) => {
const { classProps } = useFieldGroupStyleProps({ isFluid, isRequired, validationState });
const { styleProps, props: transferProps } = useStyleProps(rest);

const { helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
const { validationTextId, helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
id,
helperText,
validationText,
ariaDescribedBy,
});

const renderValidationText = useValidationText({
validationTextClassName: classProps.validationText,
validationState,
validationText,
});

return (
<fieldset
{...transferProps}
Expand All @@ -59,7 +53,9 @@ const FieldGroup = (props: SpiritFieldGroupProps) => {
{helperText}
</HelperText>
)}
{renderValidationText}
{validationState && validationText && (
<ValidationText className={classProps.validationText} id={validationTextId} validationText={validationText} />
)}
</fieldset>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import React from 'react';
import classNames from 'classnames';
import { SpiritFileUploaderInputProps } from '../../types';
import { useStyleProps } from '../../hooks';
import { useValidationText } from '../Field';
import { HelperText, ValidationText } from '../Field';
import { DEFAULT_FILE_QUEUE_LIMIT, DEFAULT_FILE_SIZE_LIMIT } from './constants';
import { useFileUploaderStyleProps } from './useFileUploaderStyleProps';
import { useFileUploaderInput } from './useFileUploaderInput';
import { Icon } from '../Icon';
import useAriaDescribedBy from '../Field/useAriaDescribedBy';

const FileUploaderInput = (props: SpiritFileUploaderInputProps) => {
const {
accept,
'aria-describedby': ariaDescribedBy = '',
dropZoneRef,
helperText,
iconName = 'upload',
Expand Down Expand Up @@ -64,10 +66,11 @@ const FileUploaderInput = (props: SpiritFileUploaderInputProps) => {
});
const { styleProps, props: transferProps } = useStyleProps(restProps);

const renderValidationText = useValidationText({
validationTextClassName: classProps.input.validationText,
validationState,
const { validationTextId, helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
id,
helperText,
validationText,
ariaDescribedBy,
});

return (
Expand All @@ -84,6 +87,7 @@ const FileUploaderInput = (props: SpiritFileUploaderInputProps) => {
{label}
</label>
<input
aria-describedby={joinedAriaDescribedBy}
type="file"
accept={accept}
id={id}
Expand All @@ -102,9 +106,20 @@ const FileUploaderInput = (props: SpiritFileUploaderInputProps) => {
&nbsp;
<span className={classProps.input.dropLabel}>{labelText}</span>
</label>
<div className={classProps.input.helper}>{helperText}</div>
{helperText && (
<HelperText className={classProps.input.helper} id={helperTextId}>
{helperText}
</HelperText>
)}
</div>
{renderValidationText}
{validationState && validationText && (
<ValidationText
className={classProps.input.validationText}
elementType="span"
id={validationTextId}
validationText={validationText}
/>
)}
</div>
);
};
Expand Down
16 changes: 6 additions & 10 deletions packages/web-react/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React, { forwardRef, ForwardedRef } from 'react';
import classNames from 'classnames';
import { SpiritSelectProps } from '../../types';
import { useStyleProps } from '../../hooks';
import { useSelectStyleProps } from './useSelectStyleProps';
import { HelperText, useValidationText } from '../Field';
import { HelperText, ValidationText } from '../Field';
import { Icon } from '../Icon';
import useAriaDescribedBy from '../Field/useAriaDescribedBy';
import { useSelectStyleProps } from './useSelectStyleProps';

/* We need an exception for components exported with forwardRef */
/* eslint no-underscore-dangle: ['error', { allow: ['_Select'] }] */
Expand All @@ -28,19 +28,13 @@ const _Select = (props: SpiritSelectProps, ref: ForwardedRef<HTMLSelectElement>)
const { classProps } = useSelectStyleProps({ isDisabled, isFluid, isRequired, isLabelHidden, validationState });
const { styleProps, props: transferProps } = useStyleProps(restProps);

const { helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
const { validationTextId, helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
id,
helperText,
validationText,
ariaDescribedBy,
});

const renderValidationText = useValidationText({
validationTextClassName: classProps.validationText,
validationState,
validationText,
});

return (
<div {...styleProps} className={classNames(classProps.root, styleProps.className)}>
<label htmlFor={id} className={classProps.label}>
Expand All @@ -67,7 +61,9 @@ const _Select = (props: SpiritSelectProps, ref: ForwardedRef<HTMLSelectElement>)
{helperText}
</HelperText>
)}
{renderValidationText}
{validationState && validationText && (
<ValidationText className={classProps.validationText} id={validationTextId} validationText={validationText} />
)}
</div>
);
};
Expand Down
19 changes: 10 additions & 9 deletions packages/web-react/src/components/TextFieldBase/TextFieldBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { forwardRef, ForwardedRef } from 'react';
import classNames from 'classnames';
import { useStyleProps } from '../../hooks';
import { SpiritTextFieldBaseProps, TextFieldBasePasswordToggleProps } from '../../types';
import { HelperText, useValidationText } from '../Field';
import { HelperText, ValidationText } from '../Field';
import useAriaDescribedBy from '../Field/useAriaDescribedBy';
import { useTextFieldBaseStyleProps } from './useTextFieldBaseStyleProps';
import TextFieldBaseInput from './TextFieldBaseInput';
Expand All @@ -27,19 +27,13 @@ const _TextFieldBase = (props: SpiritTextFieldBaseProps, ref: ForwardedRef<HTMLI
} = modifiedProps;
const { styleProps, props: otherProps } = useStyleProps(restProps);

const { helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
const { validationTextId, helperTextId, joinedAriaDescribedBy } = useAriaDescribedBy({
id,
helperText,
validationText,
ariaDescribedBy,
});

const renderValidationText = useValidationText({
validationTextClassName: classProps.validationText,
validationState,
validationText,
});

return (
<div {...styleProps} className={classNames(classProps.root, styleProps.className)}>
<label htmlFor={id} className={classProps.label}>
Expand All @@ -56,7 +50,14 @@ const _TextFieldBase = (props: SpiritTextFieldBaseProps, ref: ForwardedRef<HTMLI
{helperText}
</HelperText>
)}
{renderValidationText}
{validationState && validationText && (
<ValidationText
className={classProps.validationText}
elementType="span"
id={validationTextId}
validationText={validationText}
/>
)}
</div>
);
};
Expand Down

0 comments on commit f1d1d9e

Please sign in to comment.