diff --git a/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot b/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
index bd6a51397..2d33ac9e2 100644
--- a/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
+++ b/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
@@ -96,6 +96,10 @@ exports[`Storyshots TextArea Auto Height 1`] = `
margin-left: auto;
}
+.c2 {
+ margin-bottom: 8px;
+}
+
.c0 {
display: -webkit-box;
display: -webkit-flex;
@@ -106,64 +110,34 @@ exports[`Storyshots TextArea Auto Height 1`] = `
flex-direction: column;
}
-.c2 {
- margin-bottom: 8px;
-}
-
-.c7 {
+.c6 {
position: relative;
overflow: hidden;
- padding: 0 8px;
- background-color: var(--charcoal-surface3);
color: var(--charcoal-text2);
+ background-color: var(--charcoal-surface3);
border-radius: 4px;
-webkit-transition: 0.2s background-color,0.2s box-shadow;
transition: 0.2s background-color,0.2s box-shadow;
height: calc(22px * 4 + 18px);
}
-.c7:hover:not(:disabled):not([aria-disabled]),
-.c7:hover[aria-disabled=false] {
+.c6:not([aria-disabled]):hover,
+.c6 [aria-disabled='false']:hover {
background-color: var(--charcoal-surface3-hover);
}
-.c7:not(:disabled):not([aria-disabled]):focus,
-.c7[aria-disabled=false]:focus,
-.c7:not(:disabled):not([aria-disabled]):active,
-.c7[aria-disabled=false]:active {
- outline: none;
- box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
-}
-
-.c7:not(:disabled):not([aria-disabled]):focus:not(:focus-visible),
-.c7[aria-disabled=false]:focus:not(:focus-visible),
-.c7:not(:disabled):not([aria-disabled]):active:not(:focus-visible),
-.c7[aria-disabled=false]:active:not(:focus-visible) {
- outline: none;
-}
-
-.c7:not(:disabled):not([aria-disabled]):focus-visible,
-.c7[aria-disabled=false]:focus-visible {
+.c6:focus-within {
outline: none;
box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
}
-.c7:focus-within {
- -webkit-transition: 0.2s box-shadow;
- transition: 0.2s box-shadow;
-}
-
-.c7:focus-within.c6:focus-within:not(:disabled):not([aria-disabled]),
-.c7:focus-within.c7:focus-within[aria-disabled=false] {
- box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
-}
-
-.c8 {
+.c7 {
border: none;
outline: none;
resize: none;
font-family: inherit;
color: inherit;
+ box-sizing: border-box;
-webkit-transform-origin: top left;
-ms-transform-origin: top left;
transform-origin: top left;
@@ -173,39 +147,30 @@ exports[`Storyshots TextArea Auto Height 1`] = `
width: calc(100% / 0.875);
font-size: calc(14px / 0.875);
line-height: calc(22px / 0.875);
- padding: calc(9px / 0.875) 0;
- height: calc(22px / 0.875 * 4);
+ padding: calc(9px / 0.875) calc(8px / 0.875);
+ height: calc(22px / 0.875 * 4 + 20px);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: none;
- -ms-overflow-style: none;
- -webkit-scrollbar-width: none;
- -moz-scrollbar-width: none;
- -ms-scrollbar-width: none;
- scrollbar-width: none;
}
-.c8::-webkit-input-placeholder {
+.c7::-webkit-input-placeholder {
color: var(--charcoal-text3);
}
-.c8::-moz-placeholder {
+.c7::-moz-placeholder {
color: var(--charcoal-text3);
}
-.c8:-ms-input-placeholder {
+.c7:-ms-input-placeholder {
color: var(--charcoal-text3);
}
-.c8::placeholder {
+.c7::placeholder {
color: var(--charcoal-text3);
}
-.c8::-webkit-scrollbar {
- display: none;
-}
-
@@ -245,12 +210,12 @@ exports[`Storyshots TextArea Auto Height 1`] = `
0/100
@@ -1067,6 +962,18 @@ exports[`Storyshots TextArea Has Label 1`] = `
margin-left: auto;
}
+.c3 {
+ margin-bottom: 8px;
+}
+
+.c12 {
+ font-size: 14px;
+ line-height: 22px;
+ margin-top: 4px;
+ margin-bottom: -4px;
+ color: var(--charcoal-text2);
+}
+
.c1 {
display: -webkit-box;
display: -webkit-flex;
@@ -1077,64 +984,34 @@ exports[`Storyshots TextArea Has Label 1`] = `
flex-direction: column;
}
-.c3 {
- margin-bottom: 8px;
-}
-
-.c11 {
+.c10 {
position: relative;
overflow: hidden;
- padding: 0 8px;
- background-color: var(--charcoal-surface3);
color: var(--charcoal-text2);
+ background-color: var(--charcoal-surface3);
border-radius: 4px;
-webkit-transition: 0.2s background-color,0.2s box-shadow;
transition: 0.2s background-color,0.2s box-shadow;
height: calc(22px * 4 + 18px);
}
-.c11:hover:not(:disabled):not([aria-disabled]),
-.c11:hover[aria-disabled=false] {
+.c10:not([aria-disabled]):hover,
+.c10 [aria-disabled='false']:hover {
background-color: var(--charcoal-surface3-hover);
}
-.c11:not(:disabled):not([aria-disabled]):focus,
-.c11[aria-disabled=false]:focus,
-.c11:not(:disabled):not([aria-disabled]):active,
-.c11[aria-disabled=false]:active {
+.c10:focus-within {
outline: none;
box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
}
-.c11:not(:disabled):not([aria-disabled]):focus:not(:focus-visible),
-.c11[aria-disabled=false]:focus:not(:focus-visible),
-.c11:not(:disabled):not([aria-disabled]):active:not(:focus-visible),
-.c11[aria-disabled=false]:active:not(:focus-visible) {
- outline: none;
-}
-
-.c11:not(:disabled):not([aria-disabled]):focus-visible,
-.c11[aria-disabled=false]:focus-visible {
- outline: none;
- box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
-}
-
-.c11:focus-within {
- -webkit-transition: 0.2s box-shadow;
- transition: 0.2s box-shadow;
-}
-
-.c11:focus-within.c10:focus-within:not(:disabled):not([aria-disabled]),
-.c11:focus-within.c11:focus-within[aria-disabled=false] {
- box-shadow: 0 0 0 4px rgba(0,150,250,0.32);
-}
-
-.c12 {
+.c11 {
border: none;
outline: none;
resize: none;
font-family: inherit;
color: inherit;
+ box-sizing: border-box;
-webkit-transform-origin: top left;
-ms-transform-origin: top left;
transform-origin: top left;
@@ -1144,64 +1021,30 @@ exports[`Storyshots TextArea Has Label 1`] = `
width: calc(100% / 0.875);
font-size: calc(14px / 0.875);
line-height: calc(22px / 0.875);
- padding: calc(9px / 0.875) 0;
- height: calc(22px / 0.875 * 4);
+ padding: calc(9px / 0.875) calc(8px / 0.875);
+ height: calc(22px / 0.875 * 4 + 20px);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: none;
- -ms-overflow-style: none;
- -webkit-scrollbar-width: none;
- -moz-scrollbar-width: none;
- -ms-scrollbar-width: none;
- scrollbar-width: none;
}
-.c12::-webkit-input-placeholder {
+.c11::-webkit-input-placeholder {
color: var(--charcoal-text3);
}
-.c12::-moz-placeholder {
+.c11::-moz-placeholder {
color: var(--charcoal-text3);
}
-.c12:-ms-input-placeholder {
+.c11:-ms-input-placeholder {
color: var(--charcoal-text3);
}
-.c12::placeholder {
+.c11::placeholder {
color: var(--charcoal-text3);
}
-.c12::-webkit-scrollbar {
- display: none;
-}
-
-.c13 {
- font-size: 14px;
- line-height: 22px;
- display: flow-root;
- margin-top: 8px;
- margin-bottom: 0px;
- color: var(--charcoal-text2);
-}
-
-.c13::before {
- display: block;
- width: 0;
- height: 0;
- content: '';
- margin-top: -4px;
-}
-
-.c13::after {
- display: block;
- width: 0;
- height: 0;
- content: '';
- margin-bottom: -4px;
-}
-
.c0 {
display: grid;
gap: 24px;
@@ -1245,13 +1088,13 @@ exports[`Storyshots TextArea Has Label 1`] = `
Assistive text
diff --git a/packages/react/src/components/TextArea/index.tsx b/packages/react/src/components/TextArea/index.tsx
index 204bde0aa..f2c2d7595 100644
--- a/packages/react/src/components/TextArea/index.tsx
+++ b/packages/react/src/components/TextArea/index.tsx
@@ -2,10 +2,11 @@ import { useTextField } from '@react-aria/textfield'
import { useVisuallyHidden } from '@react-aria/visually-hidden'
import { forwardRef, useCallback, useEffect, useRef, useState } from 'react'
import styled, { css } from 'styled-components'
-import FieldLabel, { FieldLabelProps } from '../FieldLabel'
+import { FieldLabelProps } from '../FieldLabel'
import { countCodePointsInString, mergeRefs } from '../../_lib'
import { ReactAreaUseTextFieldCompat } from '../../_lib/compat'
-import { theme } from '../../styled'
+import { AssistiveText, TextFieldLabel } from '../TextField'
+import { useFocusWithClick } from '../TextField/useFocusWithClick'
type DOMProps = Omit<
React.TextareaHTMLAttributes,
@@ -115,6 +116,10 @@ const TextArea = forwardRef(
}
}, [autoHeight, syncHeight])
+ const containerRef = useRef(null)
+
+ useFocusWithClick(containerRef, ariaRef)
+
return (
(
{...(!showLabel ? visuallyHiddenProps : {})}
/>
`
${(p) => p.isDisabled && { opacity: p.theme.elementEffect.disabled.opacity }}
`
-const TextFieldLabel = styled(FieldLabel)`
- ${theme((o) => o.margin.bottom(8))}
-`
-
const StyledTextareaContainer = styled.div<{ rows: number; invalid: boolean }>`
position: relative;
overflow: hidden;
- padding: 0 8px;
- ${(p) =>
- theme((o) => [
- o.bg.surface3.hover,
- o.outline.default.focus,
- p.invalid && o.outline.assertive,
- o.font.text2,
- o.borderRadius(4),
- ])}
-
- &:focus-within {
- ${(p) =>
- theme((o) => (p.invalid ? o.outline.assertive : o.outline.default))}
- }
+ color: var(--charcoal-text2);
+ background-color: var(--charcoal-surface3);
+ border-radius: 4px;
+ transition: 0.2s background-color, 0.2s box-shadow;
${({ rows }) => css`
height: calc(22px * ${rows} + 18px);
`};
+
+ :not([aria-disabled]):hover,
+ [aria-disabled='false']:hover {
+ background-color: var(--charcoal-surface3-hover);
+ }
+ :focus-within {
+ outline: none;
+ box-shadow: 0 0 0 4px
+ ${(p) => (p.invalid ? `rgba(255,43,0,0.32)` : `rgba(0, 150, 250, 0.32);`)};
+ }
+
+ ${(p) =>
+ p.invalid &&
+ css`
+ box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
+ `}
`
const StyledTextarea = styled.textarea<{ noBottomPadding: boolean }>`
@@ -197,6 +206,7 @@ const StyledTextarea = styled.textarea<{ noBottomPadding: boolean }>`
resize: none;
font-family: inherit;
color: inherit;
+ box-sizing: border-box;
/* Prevent zooming for iOS Safari */
transform-origin: top left;
@@ -204,10 +214,11 @@ const StyledTextarea = styled.textarea<{ noBottomPadding: boolean }>`
width: calc(100% / 0.875);
font-size: calc(14px / 0.875);
line-height: calc(22px / 0.875);
- padding: calc(9px / 0.875) 0 ${(p) => (p.noBottomPadding ? 0 : '')};
+ padding: calc(9px / 0.875) calc(8px / 0.875)
+ ${(p) => (p.noBottomPadding ? 0 : '')};
- ${({ rows = 1 }) => css`
- height: calc(22px / 0.875 * ${rows});
+ ${({ rows = 1, noBottomPadding }) => css`
+ height: calc(22px / 0.875 * ${rows} + ${noBottomPadding ? 9 : 20}px);
`};
/* Display box-shadow for iOS Safari */
@@ -216,16 +227,8 @@ const StyledTextarea = styled.textarea<{ noBottomPadding: boolean }>`
background: none;
&::placeholder {
- ${theme((o) => o.font.text3)}
- }
-
- /* Hide scrollbar for Chrome, Safari and Opera */
- &::-webkit-scrollbar {
- display: none;
+ color: var(--charcoal-text3);
}
- /* Hide scrollbar for IE, Edge and Firefox */
- -ms-overflow-style: none; /* IE and Edge */
- scrollbar-width: none; /* Firefox */
`
const MultiLineCounter = styled.span`
@@ -233,15 +236,7 @@ const MultiLineCounter = styled.span`
bottom: 9px;
right: 8px;
- ${theme((o) => [o.typography(14).preserveHalfLeading, o.font.text3])}
-`
-
-const AssistiveText = styled.p<{ invalid: boolean }>`
- ${(p) =>
- theme((o) => [
- o.typography(14),
- o.margin.top(8),
- o.margin.bottom(0),
- o.font[p.invalid ? 'assertive' : 'text2'],
- ])}
+ line-height: 22px;
+ font-size: 14px;
+ color: var(--charcoal-text3);
`
diff --git a/packages/react/src/components/TextField/index.tsx b/packages/react/src/components/TextField/index.tsx
index 770c6f3c1..dba7bf80e 100644
--- a/packages/react/src/components/TextField/index.tsx
+++ b/packages/react/src/components/TextField/index.tsx
@@ -162,7 +162,7 @@ const TextFieldRoot = styled.div<{ isDisabled: boolean }>`
${(p) => p.isDisabled && { opacity: p.theme.elementEffect.disabled.opacity }}
`
-const TextFieldLabel = styled(FieldLabel)`
+export const TextFieldLabel = styled(FieldLabel)`
margin-bottom: 8px;
`
@@ -258,7 +258,7 @@ const SingleLineCounter = styled.span`
color: var(--charcoal-text3);
`
-const AssistiveText = styled.p<{ invalid: boolean }>`
+export const AssistiveText = styled.p<{ invalid: boolean }>`
font-size: 14px;
line-height: 22px;
margin-top: 4px;
diff --git a/packages/react/src/components/TextField/useFocusWithClick.tsx b/packages/react/src/components/TextField/useFocusWithClick.tsx
index e49c9f6c3..4edd94f73 100644
--- a/packages/react/src/components/TextField/useFocusWithClick.tsx
+++ b/packages/react/src/components/TextField/useFocusWithClick.tsx
@@ -3,7 +3,7 @@ import * as React from 'react'
export function useFocusWithClick(
containerRef: React.RefObject,
- inputRef: React.RefObject
+ inputRef: React.RefObject
) {
useEffect(() => {
const el = containerRef.current