Textarea
여러 줄 텍스트를 입력하는 컴포넌트입니다. Input과 같은 Style과 State를 사용하며 Leading과 Trailing element는 지원하지 않습니다.
🚩 Playground
Style, Resize와 Optional element를 조합해 실제 여러 줄 입력 상태를 확인합니다.
Appearance
Behavior
Anatomy
Textarea를 구성하는 실제 요소와 문서에서 사용하는 명칭입니다.
Textarea structure
- 1.Container
- 2.Textarea field
Container: 전체 입력 영역입니다. 최소 높이는 88px이며 약 3.5줄의 입력 공간을 확보합니다.
Textarea field: 실제 여러 줄 입력 영역입니다. Auto size가 true이면 내용에 따라 Container와 함께 높이가 증가합니다.
Properties · Style
Input과 동일하게 Outline과 Filled를 지원합니다.
Outline
Filled
Properties · Sizing
Auto size가 상위 속성이며, 값에 따라 Height와 Resize의 적용 여부가 결정됩니다.
Auto size · false
기본값입니다. Height로 초기 높이를 설정하고 Resize 사용 여부를 선택할 수 있습니다.
Auto size · true
내용에 따라 높이가 자동으로 증가합니다. 하위 속성인 Height와 Resize는 적용하지 않으며, viewport에서 고정 영역을 제외한 Max height를 넘지 않아야 합니다.
Resize · true / false
기본값은 true이며 Auto size가 false일 때만 활성화됩니다. 세로 방향으로 높이를 변경할 수 있지만 동일한 Max height 제한을 넘지 않아야 합니다.
Height · Minimum 80px
Auto size가 false일 때 초기 높이를 설정합니다. 기본값과 허용되는 최소값은 모두 80px입니다.
Properties · State
Input과 같은 단색 Focus/Error 외곽선 구조를 사용합니다.
Empty / Placeholder
Default · With value
Focus
Invalid
Disabled
Read only
Properties · Elements
Textarea는 Container와 Textarea field만으로 구성하며 내부 선택 요소를 지원하지 않습니다.
Container + Textarea field
Guidelines
Textarea를 고르고 높이를 정할 때 적용하는 기준입니다.
여러 줄이 필요한 값에만 사용하기
Textarea · 여러 줄
문의 내용
Input · 한 줄
이름
- 문의 내용, 설명, 메모처럼 줄바꿈이 생기는 값에 Textarea를 사용합니다.
- 제목이나 이름처럼 한 줄로 끝나는 값은 Input을 사용합니다. Textarea는 최소 80px를 차지하므로, 한 줄 값에 두면 쓰이지 않는 빈 영역이 남고 폼의 수직 리듬이 끊깁니다.
내부 요소와 Layout 선택은 제공하지 않기
Do
전체 너비를 모두 채우게 두세요.
Don’t
Textarea에 폭을 따로 지정하지 마세요.
- Prefix와 Suffix, Clear button, Leading element와 Trailing element를 제공하지 않습니다. Container와 Textarea field만으로 구성합니다.
- Layout은
fill만이며 선택 Property가 없습니다. 폭을 따로 지정하면 같은 폼의 다른 필드와 오른쪽 끝이 어긋납니다. - Input에서 쓰던 요소가 필요하다고 느껴지면 값이 한 줄인지, 또는 Label과 도움말처럼 Field가 담당할 일인지 다시 봅니다.
기본 높이는 3.5줄을 유지하기
기본 제공 · 3.5줄 (80px)
별도 제어 · 기본 제공 높이보다 큰 값
- 기본 높이는 80px이며 내용이 넘칠 때 3.5줄이 보입니다. 이 값보다 줄일 수 없습니다.
- 받을 내용이 길면 초기 높이를 따로 지정할 수 있습니다. 기본 제공 높이보다 큰 값만 쓸 수 있습니다.
초기 높이는 반 줄이 걸치는 지점으로 맞추기
Do
마지막 줄이 일부 잘려 보이게 두세요.
Don’t
줄 수에 딱 맞춰 끊지 마세요.
- 글자가 일부 잘려 보여야 아래에 더 쓸 자리가 있다는 것이 읽힙니다. 기본값 80px이 그 이유로 정해진 값이며, Do는 그 기본값을 그대로 쓴 상태입니다.
- 줄 수에 딱 맞추면 입력 영역이 거기서 끝난 것처럼 보이고, 스크롤이 있다는 것을 알 방법이 없습니다.
- 초기 높이를 따로 지정할 때도 같은 기준을 씁니다. 구현이 이 값을 검사하지 않으므로 높이를 정하는 쪽에서 맞춥니다.
Scrollbar는 Hover와 Focus에서만 보이기
Do
조작하지 않는 동안에는 Scrollbar를 감춰 두세요.
Don’t
Scrollbar를 항상 보이게 두지 마세요.
- Scrollbar thumb은 기본 상태에서 투명하고, Textarea를 Hover하거나 입력에 focus가 있을 때 보입니다. 조작하지 않는 동안에는 값만 남기고 장치는 감춥니다. 세로선이 늘 남아 있으면 값보다 장치가 먼저 읽힙니다.
- Hover만으로 조건을 잡지 않습니다. 키보드로 들어와 방향키로 스크롤하는 사람은 Hover가 없으므로 감춰진 분량을 끝까지 알 수 없습니다. thumb의 길이가 그 정보입니다.
- Scrollbar가 차지하는 공간은 언제나 확보합니다. 스크롤이 생기거나 사라져도 텍스트가 좌우로 움직이지 않습니다.
- 그래서 내용이 더 있다는 것을 알리는 것은 마지막 줄이 반쯤 잘려 보이는 것입니다. 앞의 높이 규칙이 이 규칙과 함께 동작합니다.
Resize는 세로만 허용하기
Resize 켬 · Default · 세로만
Resize 끔 · 높이 고정
resize의 기본값은true이며 세로 방향만 제공합니다. 가로는 제공하지 않습니다. 폭이 달라지면 같은 폼의 다른 필드와 시작점과 끝점이 어긋납니다.- 받을 내용의 분량을 사용자가 스스로 조절하는 편이 낫기 때문에 켠 상태를 기본으로 둡니다. 높이를 고정해야 하는 자리에서만 끕니다.
자동 높이는 아래 콘텐츠가 밀리지 않는 자리에서만 켜기
문의 내용
문의 내용
답변 수신 여부
Do
마지막 콘텐츠이거나 아래가 밀리지 않는 자리에서 켜세요.
Don’t
아래에 다른 콘텐츠가 있는 자리에서 켜지 마세요.
autoSize는 기본값이 아니므로 필요한 자리에서 명시적으로 켭니다.- 켤 수 있는 자리는 셋입니다. 그 화면에 이 입력만 있는 경우, 마지막 콘텐츠인 경우, 아래 콘텐츠가 밀리지 않는 배치인 경우입니다.
- 입력하는 동안 아래 콘텐츠가 계속 내려가면 방금 읽던 자리를 잃습니다. 두 예시에 직접 입력해 차이를 확인할 수 있습니다.
Resize와 Auto size는 같이 사용하지 않기
Do
한쪽만 켜세요.
Don’t
두 Property를 함께 넘기지 마세요.
- 높이를 사용자가 직접 정하는 것과 내용에 맡겨 자동으로 정하는 것은, 같은 값을 두 주체가 정하는 일이므로 함께 성립하지 않습니다. 어느 쪽으로 갈지 먼저 정하고 한쪽만 켭니다.
- 구현은
autoSize가 켜져 있으면resize를 적용하지 않습니다.resize의 기본값이true이므로,autoSize를 켜는 순간 켜져 있던 세로 조절이 조용히 꺼집니다. - Don't 쪽은 두 Property가 모두 적용된 상태를 그린 것입니다. 내용에 맞춰 늘어나는 동시에 손잡이로 끌 수도 있으니 높이를 누가 정하는지 알 수 없습니다. 구현은 이 상태를 만들지 않고 resize를 무시하므로, 실제로 두 Property를 함께 넘기면 손잡이 없이 자동 확장만 남습니다. 오류로 알려주지 않아 화면을 봐야 압니다.
높이가 자라면 최대 높이를 뷰포트 안에 두기
resize로 사용자가 늘리는 경우와autoSize로 자동으로 자라는 경우 모두, 최대 높이가 뷰포트 높이를 넘지 않게 합니다.- 정확한 차감 값은 아직 정하지 않았습니다. 확정되기 전까지 임의의 수치를 쓰지 않습니다.
Property map
현재 확인된 Textarea의 상위 Property와 허용 값을 정리합니다.
| Property | Values | Default | Status |
|---|---|---|---|
| variant | outline | filled | outline | Confirmed |
| autoSize | false | true | false | Parent property |
| resize | true | false | true | autoSize=false only |
| height | ≥ 80px | 80px | autoSize=false only |
| minHeight | 80px | 80px | Always applied |
| maxHeight | viewport − reserved layout space | 현재 정의 없음 | Required; value pending |
명세 문서
docs/system/components/textarea.md
Textarea
packages/ui/src/textarea.tsx
여러 줄 텍스트를 입력하는 공용 컴포넌트다. Input과 같은 시각적 스타일과 상태 규칙을 사용하지만 내부 선택 요소는 지원하지 않는다.
Anatomy
- Container: 전체 입력 영역이다.
- Textarea field: 여러 줄 값을 입력하는 필수 요소다.
Prefix, Clear button, Suffix, Leading element와 Trailing element는 지원하지 않는다.
Properties
Style
outline: 기본값. Neutral border와 기본 surface를 사용한다.filled: Neutral 배경을 사용하며 Focus 상태에서는 배경이 기본 surface로 바뀐다.
Layout
fill만 지원하며 부모 너비를 채운다.- Layout 선택 Property는 제공하지 않는다.
containerClassName: Container에만 적용하는 class다. Textarea field에는className을 사용한다
Auto size
false: 기본값. 기본 높이를 유지하며 Resize 설정을 적용한다.true: 내용에 따라 높이가 자동으로 증가한다. 이때 Resize 설정은 적용하지 않는다.
Resize
true: 기본값. 세로 방향으로만 크기를 변경할 수 있다.false: 사용자가 크기를 변경할 수 없다.
Resize는 autoSize=false일 때만 적용한다.
Height
autoSize=false일 때 초기 높이를 숫자(px)로 설정할 수 있다.- 최소값은 80px이며 그보다 작은 값은 80px로 제한한다.
- 기본값은 80px이다.
Maximum height
autoSize=true로 자동 확장되는 경우와resize=true로 사용자가 높이를 변경하는 경우 모두 최대 높이 제한을 적용해야 한다.- 최대 높이는
viewport − reserved layout space를 기준으로 한다. - Reserved layout space에는 고정 헤더와 콘텐츠 내부 패딩 등 Textarea 바깥에서 항상 차지하는 영역이 포함된다.
- 정확한 차감 높이와 실행 가능한 기본값은 현재 정의되지 않았다. 값이 확정되기 전까지 임의의 수치를 구현하지 않는다.
State
- Empty / Placeholder
- Default
- Focus
- Invalid
- Disabled
- Read only
Focus는 oe-focus-ring의 1px border와 외부 1px ring을 같은 진한 색으로 사용한다. Invalid도 oe-danger-border-primary의 1px border와 외부 1px ring을 같은 색으로 사용한다. 외부 ring을 사용해 상태 전환 시 내부 크기와 배치가 흔들리지 않게 한다.
Disabled는 foreground와 background 위계를 낮추고 상호작용을 제한하되, Outline 스타일에서는 기본 Neutral border를 유지한다. Filled 스타일은 기존의 투명 border 구조를 유지한다.
Guidelines
Studio 화면의 Guidelines와 소제목을 동일하게 유지한다.
여러 줄이 필요한 값에만 사용하기
문의 내용, 설명, 메모처럼 줄바꿈이 생기는 값에 사용한다. 제목이나 이름처럼 한 줄로 끝나는 값은 Input을 사용한다. Textarea는 최소 80px를 차지하므로, 한 줄 값에 두면 쓰이지 않는 빈 영역이 남고 폼의 수직 리듬이 끊긴다.
내부 요소와 Layout 선택은 제공하지 않기
Prefix와 Suffix, Clear button, Leading element와 Trailing element를 제공하지 않는다. Container와 Textarea field만으로 구성한다. Layout은 fill만이며 선택 Property가 없다. 폭은 부모가 정하며, 폭을 따로 지정하면 같은 폼의 다른 필드와 오른쪽 끝이 어긋난다.
Input에서 쓰던 요소가 필요하다고 느껴지면 값이 한 줄인지, 또는 Label과 도움말처럼 Field가 담당할 일인지 다시 본다.
기본 높이는 3.5줄을 유지하기
기본 높이는 80px이며, 내용이 넘칠 때 3.5줄이 보인다. 이 값보다 줄일 수 없다. 받을 내용이 길면 초기 높이를 따로 지정할 수 있으며, 기본 제공 높이보다 큰 값만 쓸 수 있다.
초기 높이는 반 줄이 걸치는 지점으로 맞추기
글자가 일부 잘려 보여야 아래에 더 쓸 자리가 있다는 것이 읽힌다. 기본값 80px이 그 이유로 정해진 값이며 내용이 넘칠 때 3.5줄이 보인다. 줄 수에 딱 맞추면 입력 영역이 거기서 끝난 것처럼 보이고 스크롤이 있다는 것을 알 방법이 없다.
보이는 줄 수는 (높이 − Container border 2px − 위쪽 내부 여백 8px) ÷ 줄높이 20px로 정해진다. 아래쪽 내부 여백은 스크롤 영역 안에 있어 끝까지 내렸을 때만 보이므로 이 계산에 넣지 않는다. 반 줄이 걸치는 높이는 80px, 100px, 120px처럼 20 × 정수 + 20이다.
초기 높이를 따로 지정할 때도 같은 기준을 쓴다. 구현이 이 값을 검사하지 않으므로 높이를 정하는 쪽에서 맞춘다.
Scrollbar는 Hover와 Focus에서만 보이기
Scrollbar thumb은 기본 상태에서 투명하고, Textarea를 Hover하거나 입력에 focus가 있을 때 보인다. 조작하지 않는 동안에는 값만 남기고 장치는 감춘다. 세로선이 늘 남아 있으면 값보다 장치가 먼저 읽힌다.
Hover만으로 조건을 잡지 않는다. 키보드로 들어와 방향키로 스크롤하는 사람은 Hover가 없으므로 감춰진 분량을 끝까지 알 수 없다. thumb의 길이가 그 정보다.
Scrollbar가 차지하는 공간은 언제나 확보한다. 스크롤이 생기거나 사라져도 텍스트가 좌우로 움직이지 않는다. 그래서 내용이 더 있다는 것을 알리는 것은 마지막 줄이 반쯤 잘려 보이는 것이며, 앞의 높이 규칙이 이 규칙과 함께 동작한다.
Resize는 세로만 허용하기
resize의 기본값은 true이며 세로 방향만 제공한다. 가로는 제공하지 않는다. 폭이 달라지면 같은 폼의 다른 필드와 시작점과 끝점이 어긋난다.
받을 내용의 분량을 사용자가 스스로 조절하는 편이 낫기 때문에 켠 상태를 기본으로 둔다. 높이를 고정해야 하는 자리에서만 끈다.
자동 높이는 아래 콘텐츠가 밀리지 않는 자리에서만 켜기
autoSize는 기본값이 아니므로 필요한 자리에서 명시적으로 켠다. 켤 수 있는 자리는 셋이다. 그 화면에 이 입력만 있는 경우, 마지막 콘텐츠인 경우, 아래 콘텐츠가 밀리지 않는 배치인 경우다.
입력하는 동안 아래 콘텐츠가 계속 내려가면 사용자가 방금 읽던 자리를 잃는다.
Resize와 Auto size는 같이 사용하지 않기
높이를 사용자가 직접 정하는 것과 내용에 맡겨 자동으로 정하는 것은, 같은 값을 두 주체가 정하는 일이므로 함께 성립하지 않는다. 어느 쪽으로 갈지 먼저 정하고 한쪽만 켠다.
구현은 autoSize가 켜져 있으면 resize를 적용하지 않는다. resize의 기본값이 true이므로 autoSize를 켜는 순간 켜져 있던 세로 조절이 조용히 꺼진다. 두 Property를 함께 넘기면 세로 조절을 요청했는데도 손잡이가 없는 상태가 되며, 오류로 알려주지 않으므로 화면을 봐야 알 수 있다.
높이가 자라면 최대 높이를 뷰포트 안에 두기
resize로 사용자가 늘리는 경우와 autoSize로 자동으로 자라는 경우 모두, 최대 높이가 뷰포트 높이를 넘지 않게 한다. 정확한 차감 값은 아직 정하지 않았으며, 확정되기 전까지 임의의 수치를 쓰지 않는다.
Specification
- Width:
100% - Minimum height:
80px - Textarea field minimum height:
78px(Container border를 포함한 전체 최소 높이 80px) - Typography:
14px / 20px - Radius:
8px - Textarea field horizontal padding:
12px - Textarea field vertical padding:
8px - Placeholder:
oe-foreground-placeholder
스크롤 공간은 항상 동일하게 확보해 스크롤 유무가 바뀌어도 텍스트가 움직이지 않게 한다. 스크롤바 thumb은 기본 상태에서 투명하고 Textarea를 Hover하거나 입력에 focus가 있을 때 표시한다. 입력 내용은 Textarea field 자체의 패딩 안에서 스크롤하며 Container 내부에 별도 하단 공백을 만들지 않는다.
현재 최소 높이는 내용이 넘칠 때 3.5줄이 보이는 값이다. autoSize=true일 때 field-sizing-content를 사용해 내용에 따라 높이를 계산한다.
현재 정의하지 않은 항목
- Size property
- 자동 높이의 최대값과 이후 스크롤 정책
- 최대 높이 계산에 사용할 reserved layout space의 정확한 값
- Textarea 내부에 Character count를 표시하는 배치다. 기본 소유자는 field.md의 Footer이며, 내부 표시가 필요한 실제 사례가 확인되면 다시 검토한다.
Label, Helper text, Error message와 Character count는 field.md가 소유한다.
상세 페이지 우측의 On this page에서 현재 섹션을 확인하고 이동할 수 있다. Field와 Input은 rail 아래의 낮은 위계 Related 링크로 제공한다.