Skip to content

Commit 48cc721

Browse files
committed
fix(Textarea): remove duplicate label content for better accessibility
1 parent ac11d32 commit 48cc721

File tree

2 files changed

+62
-58
lines changed

2 files changed

+62
-58
lines changed

packages/orbit-components/src/Textarea/__tests__/index.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ describe("Textarea", () => {
4949
expect(textarea).toHaveAttribute("name", name);
5050
expect(textarea).toHaveAttribute("data-sample", "Sample");
5151
expect(textarea).not.toBeInvalid();
52-
expect(textarea.parentElement).toHaveStyle({ marginBottom: "12px" });
5352
expect(textarea).toHaveStyle({ padding: "12px" });
53+
expect(document.querySelector(".orbit-textarea")).toHaveStyle({ marginBottom: "12px" });
5454
});
5555

5656
it("should trigger event handlers", async () => {

packages/orbit-components/src/Textarea/index.tsx

+61-57
Original file line numberDiff line numberDiff line change
@@ -57,69 +57,73 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, Props>((props, ref) => {
5757
const shown = tooltipShown || tooltipShownHover;
5858

5959
return (
60-
<label
60+
<div
6161
className={cx(
62+
"orbit-textarea",
6263
"font-base relative flex w-full flex-col",
6364
fullHeight && "h-full flex-1",
6465
spaceAfter && getSpaceAfterClasses(spaceAfter),
6566
)}
66-
ref={labelRef}
6767
>
68-
{label && (
69-
<FormLabel
70-
error={!!error}
71-
help={!!help}
72-
required={required}
73-
iconRef={iconRef}
74-
onMouseEnter={() => setTooltipShownHover(true)}
75-
onMouseLeave={() => setTooltipShownHover(false)}
76-
>
77-
{label}
78-
</FormLabel>
79-
)}
80-
81-
<textarea
82-
className={cx(
83-
"w-full appearance-none",
84-
"font-base text-normal p-300 leading-normal",
85-
"rounded-100 relative box-border block overflow-auto",
86-
"min-h-form-box-normal",
87-
"duration-fast transition-shadow ease-in-out",
88-
"border border-transparent",
89-
// TODO: remove when will be migrated from tmp-folder
90-
resize === RESIZE_OPTIONS.VERTICAL ? "resize-y" : "resize-none",
91-
error ? "shadow-form-element-error" : "shadow-form-element",
92-
disabled ? "cursor-not-allowed" : "cursor-text",
93-
fullHeight && "h-full flex-1",
94-
disabled || readOnly
95-
? "bg-form-element-disabled-background"
96-
: [
97-
"bg-form-element-background",
98-
error ? "hover:shadow-form-element-error-hover" : "hover:shadow-form-element-hover",
99-
],
100-
"[&::placeholder]:text-form-element-foreground",
68+
<label ref={labelRef}>
69+
{label && (
70+
<FormLabel
71+
error={!!error}
72+
help={!!help}
73+
required={required}
74+
iconRef={iconRef}
75+
onMouseEnter={() => setTooltipShownHover(true)}
76+
onMouseLeave={() => setTooltipShownHover(false)}
77+
>
78+
{label}
79+
</FormLabel>
10180
)}
102-
data-state={getFieldDataState(!!error)}
103-
data-test={dataTest}
104-
aria-required={!!required}
105-
id={inputId}
106-
name={name}
107-
value={value}
108-
defaultValue={defaultValue}
109-
disabled={disabled}
110-
placeholder={String(placeholder)}
111-
maxLength={maxLength}
112-
onChange={onChange}
113-
rows={rows}
114-
onFocus={handleFocus}
115-
onBlur={onBlur}
116-
tabIndex={tabIndex ? Number(tabIndex) : undefined}
117-
readOnly={readOnly}
118-
ref={ref}
119-
aria-describedby={shown ? `${inputId}-feedback` : undefined}
120-
aria-invalid={error ? true : undefined}
121-
{...dataAttrs}
122-
/>
81+
82+
<textarea
83+
className={cx(
84+
"w-full appearance-none",
85+
"font-base text-normal p-300 leading-normal",
86+
"rounded-100 relative box-border block overflow-auto",
87+
"min-h-form-box-normal",
88+
"duration-fast transition-shadow ease-in-out",
89+
"border border-transparent",
90+
// TODO: remove when will be migrated from tmp-folder
91+
resize === RESIZE_OPTIONS.VERTICAL ? "resize-y" : "resize-none",
92+
error ? "shadow-form-element-error" : "shadow-form-element",
93+
disabled ? "cursor-not-allowed" : "cursor-text",
94+
fullHeight && "h-full flex-1",
95+
disabled || readOnly
96+
? "bg-form-element-disabled-background"
97+
: [
98+
"bg-form-element-background",
99+
error
100+
? "hover:shadow-form-element-error-hover"
101+
: "hover:shadow-form-element-hover",
102+
],
103+
"[&::placeholder]:text-form-element-foreground",
104+
)}
105+
data-state={getFieldDataState(!!error)}
106+
data-test={dataTest}
107+
aria-required={!!required}
108+
id={inputId}
109+
name={name}
110+
value={value}
111+
defaultValue={defaultValue}
112+
disabled={disabled}
113+
placeholder={String(placeholder)}
114+
maxLength={maxLength}
115+
onChange={onChange}
116+
rows={rows}
117+
onFocus={handleFocus}
118+
onBlur={onBlur}
119+
tabIndex={tabIndex ? Number(tabIndex) : undefined}
120+
readOnly={readOnly}
121+
ref={ref}
122+
aria-describedby={shown ? `${inputId}-feedback` : undefined}
123+
aria-invalid={error ? true : undefined}
124+
{...dataAttrs}
125+
/>
126+
</label>
123127
{hasTooltip && (
124128
<ErrorFormTooltip
125129
id={`${inputId}-feedback`}
@@ -131,7 +135,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, Props>((props, ref) => {
131135
referenceElement={labelRef}
132136
/>
133137
)}
134-
</label>
138+
</div>
135139
);
136140
});
137141

0 commit comments

Comments
 (0)