diff --git a/src/components/text-area/TextArea.js b/src/components/text-area/TextArea.js.flow similarity index 100% rename from src/components/text-area/TextArea.js rename to src/components/text-area/TextArea.js.flow diff --git a/src/components/text-area/TextArea.tsx b/src/components/text-area/TextArea.tsx new file mode 100644 index 0000000000..a7c2a5f445 --- /dev/null +++ b/src/components/text-area/TextArea.tsx @@ -0,0 +1,99 @@ +import * as React from 'react'; +import classNames from 'classnames'; +import uniqueId from 'lodash/uniqueId'; + +import Label from '../label'; +import Tooltip, { TooltipPosition, TooltipTheme, type TooltipProps } from '../tooltip'; + +import './TextArea.scss'; + +export interface TextAreaProps extends React.TextareaHTMLAttributes { + /** Add a class to the component */ + className?: string; + /** Description shown below the label */ + description?: React.ReactNode; + /** Error message shown in the error tooltip */ + error?: React.ReactNode; + /** Renders error tooltip at the specified position (positions are those from Tooltip) */ + errorTooltipPosition?: NonNullable; + /** Hides the label */ + hideLabel?: boolean; + /** Hides (optional) text from the label */ + hideOptionalLabel?: boolean; + /** Makes the text area value required */ + isRequired?: boolean; + /** Is text area resizable */ + isResizable?: boolean; + /** Label displayed for the text area */ + label: React.ReactNode; + /** Ref to the underlying textarea element. @TODO: eventually rename to innerRef for consistancy across all form elements */ + textareaRef?: React.Ref; + /** A CSS class for the tooltip's tether element component */ + tooltipTetherClassName?: string; +} + +const TextArea = ({ + className = '', + description, + error, + errorTooltipPosition, + hideLabel, + hideOptionalLabel, + isRequired, + isResizable, + label, + textareaRef, + tooltipTetherClassName, + ...rest +}: TextAreaProps) => { + const hasError = !!error; + const classes = classNames(className, 'text-area-container', { + 'show-error': hasError, + }); + + const errorMessageID = React.useRef(uniqueId('errorMessage')).current; + const descriptionID = React.useRef(uniqueId('description')).current; + + const ariaAttrs = { + 'aria-invalid': hasError, + 'aria-required': isRequired, + 'aria-errormessage': errorMessageID, + 'aria-describedby': description ? descriptionID : undefined, + }; + + return ( +
+