Skip to content

Commit 35a1d38

Browse files
authored
Merge pull request #1958 from dxc-technology/gomezivann/textarea-fix
Fixing Textarea `verticalGrow` as `auto`
2 parents 6e2cafb + f5a575f commit 35a1d38

File tree

2 files changed

+43
-204
lines changed

2 files changed

+43
-204
lines changed

app/src/pages/Textarea.jsx

Lines changed: 30 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -1,204 +1,40 @@
1-
import React, { useRef, useState } from "react";
2-
import { DxcTextarea, DxcButton } from "@dxc-technology/halstack-react";
1+
import React, { useState } from "react";
2+
import {
3+
DxcTextarea,
4+
DxcButton,
5+
DxcFlex,
6+
} from "@dxc-technology/halstack-react";
37

48
function App() {
5-
const ref = useRef(null);
6-
const [value, setValue] = useState("");
7-
const [error, setError] = useState("");
8-
const onChange = ({ value }) => {
9-
setValue(value);
10-
};
11-
const onBlur = ({ value, error }) => {
12-
setValue(value);
13-
error ? setError(error) : setError(null);
14-
};
15-
16-
const [customValue, setCustomValue] = useState("");
17-
const [errorMessage, setErrorMessage] = useState("");
18-
const onChangeCustom = ({ value }) => {
19-
setCustomValue(value);
20-
};
21-
const onBlurCustom = ({ value, error }) => {
22-
setCustomValue(value);
23-
error ? setErrorMessage("Custom length error.") : setErrorMessage(null);
24-
};
9+
const [textValue, setTextValue] = useState("");
2510

26-
const [customPatternValue, setCustomPatternValue] = useState("");
27-
const [customPatternError, setCustomPatternError] = useState("");
28-
const onChangeCustomPattern = ({ value, error }) => {
29-
setCustomPatternValue(value);
30-
error
31-
? setCustomPatternError("Custom pattern error.")
32-
: setCustomPatternError(null);
11+
const updateTextarea = () => {
12+
setTextValue((value) => {
13+
return (
14+
value +
15+
`Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.`
16+
);
17+
});
3318
};
3419

35-
const [disabledInput, setDisabledInput] = useState(false);
36-
3720
return (
3821
<>
39-
<div>
40-
<h4 style={{ marginLeft: "36px" }}>Sizes</h4>
41-
<DxcTextarea
42-
label="Small"
43-
margin={{ left: "medium", right: "medium" }}
44-
size="small"
45-
/>
46-
<DxcTextarea
47-
label="Medium"
48-
margin={{ left: "medium", right: "medium" }}
49-
/>
50-
<DxcTextarea
51-
label="Large"
52-
margin={{ left: "medium", right: "medium" }}
53-
size="large"
54-
/>
55-
<DxcTextarea
56-
label="Fill parent"
57-
margin={{ left: "medium", right: "medium" }}
58-
size="fillParent"
59-
/>
60-
</div>
61-
<div>
62-
<DxcTextarea
63-
label="Default"
64-
helperText="Sample text"
65-
placeholder="Enter your text here..."
66-
optional
67-
margin={{ left: "medium", right: "medium" }}
68-
/>
69-
</div>
70-
<DxcTextarea
71-
label="With 'on' autocomplete"
72-
margin={{ left: "medium", right: "medium" }}
73-
autocomplete="on"
74-
/>
75-
<div>
76-
<DxcTextarea
77-
label="Disabled"
78-
helperText="Sample text"
79-
placeholder="Enter your text here..."
80-
disabled
81-
verticalGrow="manual"
82-
margin={{ left: "medium", right: "medium" }}
83-
/>
84-
</div>
85-
<div>
86-
<DxcTextarea
87-
label="Controlled"
88-
helperText="Sample text"
89-
placeholder="Enter your text here..."
90-
value={value}
91-
onChange={onChange}
92-
onBlur={onBlur}
93-
error={error}
94-
margin={{ left: "medium", right: "medium" }}
95-
/>
96-
</div>
97-
<div>
98-
<DxcTextarea
99-
label="Pattern"
100-
helperText="The value should have at least one letter, one number and one special
101-
character"
102-
placeholder="Enter your text here..."
103-
pattern='^.*(?=.*[a-zA-Z])(?=.*\d)(?=.*[!&$%&? "]).*$'
104-
margin={{ left: "medium", right: "medium" }}
105-
/>
106-
</div>
107-
<div>
108-
<DxcTextarea
109-
label="Length"
110-
helperText="The value should be 5 < value < 10"
111-
placeholder="Enter your text here..."
112-
minLength={5}
113-
maxLength={10}
114-
margin={{ left: "medium", right: "medium" }}
115-
/>
116-
</div>
117-
<div>
118-
<DxcTextarea
119-
label="Custom length error"
120-
helperText="The value should be 5 < value < 10"
121-
placeholder="Enter your text here..."
122-
value={customValue}
123-
error={errorMessage}
124-
onChange={onChangeCustom}
125-
onBlur={onBlurCustom}
126-
minLength={5}
127-
maxLength={10}
128-
margin={{ left: "medium", right: "medium" }}
129-
/>
130-
</div>
131-
<div>
132-
<DxcTextarea
133-
label="Custom pattern error"
134-
helperText="The value should have at least one letter, one number and one special
135-
character"
136-
placeholder="Enter your text here..."
137-
value={customPatternValue}
138-
error={customPatternError}
139-
onChange={onChangeCustomPattern}
140-
pattern='^.*(?=.*[a-zA-Z])(?=.*\d)(?=.*[!&$%&? "]).*$'
141-
margin={{ left: "medium", right: "medium" }}
142-
/>
143-
</div>
144-
<div>
145-
<DxcTextarea
146-
label="Vertical grow 'none'"
147-
placeholder="Enter your text here..."
148-
verticalGrow="none"
149-
margin={{ left: "medium", right: "medium" }}
150-
/>
151-
</div>
152-
<div>
153-
<DxcTextarea
154-
label="Vertical grow 'manual'"
155-
placeholder="Enter your text here..."
156-
verticalGrow="manual"
157-
margin={{ left: "medium", right: "medium" }}
158-
/>
159-
</div>
160-
<div>
161-
<DxcTextarea
162-
label="Vertical grow 'auto' with long initial value"
163-
helperText="Initially should also be changed"
164-
placeholder="Enter your text here..."
165-
value="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
166-
margin={{ left: "medium", right: "medium" }}
167-
/>
168-
</div>
169-
<div>
170-
<DxcTextarea
171-
label="With rows"
172-
placeholder="Enter your text here..."
173-
rows={10}
174-
verticalGrow="manual"
175-
margin={{ left: "medium", right: "medium" }}
176-
/>
177-
</div>
178-
<div>
179-
<DxcTextarea
180-
label="Error"
181-
placeholder="Enter your text here..."
182-
error="Custom and very long error."
183-
margin={{ left: "medium", right: "medium" }}
184-
/>
185-
</div>
186-
<div>
187-
<DxcTextarea
188-
label="Ref"
189-
placeholder="Enter your text here..."
190-
margin={{ left: "medium", right: "medium" }}
191-
ref={ref}
192-
disabled={disabledInput}
193-
/>
194-
<DxcButton
195-
onClick={() => {
196-
setDisabledInput((disabled) => !disabled);
197-
}}
198-
label="Change disable"
199-
margin={{ left: "medium" }}
200-
></DxcButton>
201-
</div>
22+
<DxcFlex direction="row" gap={"1rem"}>
23+
<DxcFlex direction="column" gap={"1rem"}>
24+
<DxcButton label={"Add Text"} onClick={() => updateTextarea()} />
25+
<DxcButton
26+
label={"Clear"}
27+
mode="secondary"
28+
onClick={() => setTextValue("")}
29+
/>
30+
</DxcFlex>
31+
<DxcTextarea
32+
rows={4}
33+
onChange={({ value }) => setTextValue(value)}
34+
value={textValue}
35+
verticalGrow="auto"
36+
/>
37+
</DxcFlex>
20238
</>
20339
);
20440
}

lib/src/textarea/Textarea.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useId, useRef, useState } from "react";
1+
import React, { useEffect, useId, useRef, useState } from "react";
22
import styled, { ThemeProvider } from "styled-components";
33
import { getMargin } from "../common/utils";
44
import useTheme from "../useTheme";
@@ -42,6 +42,7 @@ const DxcTextarea = React.forwardRef<RefType, TextareaPropsType>(
4242
const translatedLabels = useTranslatedLabels();
4343

4444
const textareaRef = useRef(null);
45+
const prevValueRef = useRef(null);
4546
const errorId = `error-${textareaId}`;
4647

4748
const isNotOptional = (value) => value === "" && !optional;
@@ -61,14 +62,6 @@ const DxcTextarea = React.forwardRef<RefType, TextareaPropsType>(
6162
else onChange?.({ value: newValue });
6263
};
6364

64-
const autoVerticalGrow = () => {
65-
const textareaLineHeight = parseInt(window.getComputedStyle(textareaRef.current)["line-height"]);
66-
const textareaPaddingTopBottom = parseInt(window.getComputedStyle(textareaRef.current)["padding-top"]) * 2;
67-
textareaRef.current.style.height = `${textareaLineHeight * rows}px`;
68-
const newHeight = textareaRef.current.scrollHeight - textareaPaddingTopBottom;
69-
textareaRef.current.style.height = `${newHeight}px`;
70-
};
71-
7265
const handleOnBlur = (event) => {
7366
if (isNotOptional(event.target.value))
7467
onBlur?.({ value: event.target.value, error: translatedLabels.formFields.requiredValueErrorMessage });
@@ -84,9 +77,19 @@ const DxcTextarea = React.forwardRef<RefType, TextareaPropsType>(
8477

8578
const handleOnChange = (event) => {
8679
changeValue(event.target.value);
87-
verticalGrow === "auto" && autoVerticalGrow();
8880
};
8981

82+
useEffect(() => {
83+
if (verticalGrow === "auto" && prevValueRef.current !== (value ?? innerValue)) {
84+
const textareaLineHeight = parseInt(window.getComputedStyle(textareaRef.current)["line-height"]);
85+
const textareaPaddingTopBottom = parseInt(window.getComputedStyle(textareaRef.current)["padding-top"]) * 2;
86+
textareaRef.current.style.height = `${textareaLineHeight * rows}px`;
87+
const newHeight = textareaRef.current.scrollHeight - textareaPaddingTopBottom;
88+
textareaRef.current.style.height = `${newHeight}px`;
89+
prevValueRef.current = value ?? innerValue;
90+
}
91+
}, [verticalGrow, value, innerValue, rows]);
92+
9093
return (
9194
<ThemeProvider theme={colorsTheme.textarea}>
9295
<TextareaContainer margin={margin} size={size} ref={ref}>

0 commit comments

Comments
 (0)