1import {
2 chakra,
3 FormControl,
4 FormErrorMessage,
5 FormLabel,
6 InputGroup,
7 InputLeftAddon,
8 InputRightAddon,
9 InputRightElement,
10 Textarea as ChakraTextarea,
11 TextareaProps as ChakraTextareaProps,
12} from '@chakra-ui/react';
13import { XMarkIcon } from '@heroicons/react/24/outline';
14import classNames from 'classnames';
15import React, { PropsWithChildren, ReactNode } from 'react';
16
17const ClearIcon = chakra(XMarkIcon, {
18 baseStyle: {
19 w: 4,
20 h: 4,
21 },
22});
23
24export type TextareaProps = PropsWithChildren<
25 {
26 value?: string;
27 className?: string;
28 endAdornment?: ReactNode;
29 startAdornment?: ReactNode;
30 type?: string;
31 placeholder?: string;
32 onChange?: (e: any) => void;
33 onBlur?: (e: any) => void;
34 onClick?: (e: any) => void;
35 name?: string;
36 error?: string;
37 disabled?: boolean;
38 step?: number;
39 label?: string;
40 clearable?: boolean;
41 } & ChakraTextareaProps
42>;
43
44export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
45 (
46 {
47 disabled,
48 step,
49 label,
50 className,
51 startAdornment,
52 endAdornment,
53 placeholder,
54 onChange,
55 onBlur,
56 name,
57 value,
58 onClick,
59 error,
60 clearable = false,
61 ...props
62 },
63 ref
64 ) => {
65 const clear = () => {
66 if (onChange)
67 onChange({
68 target: {
69 value: '',
70 name,
71 },
72 });
73 };
74 const { size = 'md' } = props;
75
76 return (
77 <FormControl isInvalid={!!error}>
78 {label && <FormLabel>{label}</FormLabel>}
79 <InputGroup
80 size={size}
81 w="full"
82 rounded="md"
83 _focusWithin={{
84 outline: '2px solid',
85 outlineColor: 'primary.200',
86 }}
87 bg={disabled ? 'gray.100' : 'transparent'}
88 _dark={{ bg: disabled ? 'gray.600' : 'transparent' }}
89 >
90 {startAdornment && <InputLeftAddon>{startAdornment}</InputLeftAddon>}
91 {/* @ts-ignore */}
92 <ChakraTextarea
93 name={name}
94 ref={ref}
95 step={step}
96 className={classNames(className)}
97 placeholder={placeholder}
98 onChange={onChange}
99 onBlur={onBlur}
100 value={value}
101 onClick={onClick}
102 disabled={disabled}
103 flexGrow={1}
104 _focusVisible={{
105 outline: 'none',
106 borderTopColor: 'transparent',
107 borderRightColor: 'transparent',
108 borderBottomColor: 'transparent',
109 }}
110 _disabled={{
111 cursor: 'not-allowed',
112 }}
113 {...props}
114 roundedLeft={startAdornment ? '0' : 'md'}
115 roundedRight={endAdornment ? '0' : 'md'}
116 />
117 {endAdornment && (
118 <InputRightAddon
119 borderLeftRadius={0}
120 borderRightRadius="6px"
121 bg="transparent"
122 >
123 {endAdornment}
124 </InputRightAddon>
125 )}
126 {clearable && value && value.length && (
127 <InputRightElement
128 borderLeftRadius={0}
129 borderRightRadius="6px"
130 bg="transparent"
131 onClick={clear}
132 cursor="pointer"
133 >
134 <ClearIcon />
135 </InputRightElement>
136 )}
137 </InputGroup>
138 {!!error && <FormErrorMessage>{error}</FormErrorMessage>}
139 </FormControl>
140 );
141 }
142);