Skip to content

Commit

Permalink
fix: simplify code
Browse files Browse the repository at this point in the history
  • Loading branch information
kkmch committed Sep 5, 2023
1 parent 8d6d45c commit 8858b80
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 78 deletions.
18 changes: 10 additions & 8 deletions src/components/controls/TextArea/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {useForkRef} from '../../utils/useForkRef';
import {useUniqId} from '../../utils/useUniqId';
import {ClearButton, mapTextInputSizeToButtonSize} from '../common';
import {OuterAdditionalContent} from '../common/OuterAdditionalContent/OuterAdditionalContent';
import {useDescribedBy} from '../common/useDescribedBy';
import type {
BaseInputControlProps,
InputControlPin,
Expand Down Expand Up @@ -89,12 +88,15 @@ export const TextArea = React.forwardRef<HTMLSpanElement, TextAreaProps>(functio
const isClearControlVisible = Boolean(hasClear && !disabled && inputValue);
const id = originalId || innerId;

const ariaDescribedBy = useDescribedBy({
ariaDescribedBy: controlProps?.['aria-describedby'],
note,
error,
controlId: id,
});
const errorMessageId = useUniqId();
const noteId = useUniqId();
const ariaDescribedBy = [
controlProps?.['aria-describedby'],
note ? noteId : undefined,
isErrorMsgVisible ? errorMessageId : undefined,
]
.filter(Boolean)
.join(' ');

const commonProps = {
id,
Expand All @@ -116,7 +118,7 @@ export const TextArea = React.forwardRef<HTMLSpanElement, TextAreaProps>(functio
controlProps: {
...controlProps,
'aria-describedby': ariaDescribedBy,
'aria-invalid': controlProps?.['aria-invalid'] ?? Boolean(error),
'aria-invalid': Boolean(error) || undefined,
},
};

Expand Down
18 changes: 10 additions & 8 deletions src/components/controls/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {useForkRef} from '../../utils/useForkRef';
import {useUniqId} from '../../utils/useUniqId';
import {ClearButton, mapTextInputSizeToButtonSize} from '../common';
import {OuterAdditionalContent} from '../common/OuterAdditionalContent/OuterAdditionalContent';
import {useDescribedBy} from '../common/useDescribedBy';
import type {
BaseInputControlProps,
InputControlPin,
Expand Down Expand Up @@ -115,20 +114,23 @@ export const TextInput = React.forwardRef<HTMLSpanElement, TextInputProps>(funct
const labelSize = useElementSize(isLabelVisible ? labelRef : null, size);
const leftContentSize = useElementSize(isLeftContentVisible ? leftContentRef : null, size);

const ariaDescribedBy = useDescribedBy({
ariaDescribedBy: originalControlProps?.['aria-describedby'],
note,
error,
controlId: id,
});
const errorMessageId = useUniqId();
const noteId = useUniqId();
const ariaDescribedBy = [
originalControlProps?.['aria-describedby'],
note ? noteId : undefined,
isErrorMsgVisible ? errorMessageId : undefined,
]
.filter(Boolean)
.join(' ');

const controlProps: TextInputProps['controlProps'] = {
...originalControlProps,
style: {
...originalControlProps?.style,
...(isLabelVisible && labelSize.width ? {paddingLeft: `${labelSize.width}px`} : {}),
},
'aria-invalid': originalControlProps?.['aria-invalid'] ?? Boolean(error),
'aria-invalid': Boolean(error) || undefined,
'aria-describedby': ariaDescribedBy,
};
const commonProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';

import {fireEvent, render, screen} from '@testing-library/react';
import {fireEvent, queryHelpers, render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import {CONTROL_ERROR_ICON_QA, CONTROL_ERROR_MESSAGE_QA} from '../../utils';
import {getControlErrorTextId, getControlNoteId} from '../../utils';
import {TextInput} from '../TextInput';

describe('TextInput input', () => {
Expand Down Expand Up @@ -198,24 +197,26 @@ describe('TextInput input', () => {
});

test('render described input with error message and note', () => {
const inputId = 'input-id';
const errorText = 'Some error text';
const noteText = 'Note text';
const {container} = render(
<TextInput error={errorText} id={inputId} note={noteText} />,
);
const {container} = render(<TextInput error={errorText} note={noteText} />);

const input = screen.getByRole('textbox');
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const errorTextElement = container.querySelector(
`#${getControlErrorTextId(inputId)}`,
);
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const noteTextElement = container.querySelector(`#${getControlNoteId(inputId)}`);

expect(input.getAttribute('aria-describedby')).toBe(
`${getControlNoteId(inputId)} ${getControlErrorTextId(inputId)}`,
const [noteId = '', errorMessageId = ''] = (
input.getAttribute('aria-describedby') ?? ''
).split(/\s+/);
expect(noteId).not.toBe('');
expect(errorMessageId).not.toBe('');

const errorTextElement = queryHelpers.queryByAttribute(
'id',
container,
errorMessageId,
);
const noteTextElement = queryHelpers.queryByAttribute('id', container, noteId);
if (!errorTextElement || !noteTextElement) {
throw new Error('Both error message and note elements should be present');
}
expect(errorTextElement?.textContent).toBe(errorText);
expect(noteTextElement?.textContent).toBe(noteText);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
import React from 'react';

import {block} from '../../../utils/cn';
import {getControlErrorTextId, getControlNoteId} from '../../utils';

import './OuterAdditionalContent.scss';

const b = block('outer-additional-content');

interface OuterAdditionalContentProps {
isVisible?: boolean;
note?: React.ReactNode;
error?: React.ReactNode;
controlId?: string;
errorMessage?: React.ReactNode;
noteId?: string;
errorMessageId?: string;
}

export const OuterAdditionalContent = ({
error,
isVisible,
errorMessage,
note,
controlId,
noteId,
errorMessageId,
}: OuterAdditionalContentProps) => {
return isVisible || note ? (
return errorMessage || note ? (
<div className={b()}>
{isVisible && (
<div className={b('error')} id={getControlErrorTextId(controlId)}>
{error}
{errorMessage && (
<div className={b('error')} id={errorMessageId}>
{errorMessage}
</div>
)}
{note && (
<div className={b('note')} id={getControlNoteId(controlId)}>
<div className={b('note')} id={noteId}>
{note}
</div>
)}
Expand Down
29 changes: 0 additions & 29 deletions src/components/controls/common/useDescribedBy.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/components/controls/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,3 @@ export const errorPropsMapper = (

return {errorMessage, errorPlacement, validationState};
};

export const getControlErrorTextId = (controlId?: string) =>
controlId ? `${controlId}-error-text` : undefined;

export const getControlNoteId = (controlId?: string) =>
controlId ? `${controlId}-note-text` : undefined;

0 comments on commit 8858b80

Please sign in to comment.