Shape and elevation
경계, radius와 shadow로 표면 관계를 차분하게 설명합니다.
목적
Shape는 component의 종류와 상호작용 범위를 구분하고, elevation은 실제로 겹쳐 있는 레이어 관계를 설명한다. Dot은 둥근 모서리와 shadow를 친근함의 장식으로 반복하지 않는다. 기본 화면은 fill, border, spacing으로 차분하게 구성하고 떠 있는 레이어에만 깊이를 부여한다.
- Flexible: component 크기와 맥락이 달라도 같은 radius 계보를 유지한다.
- Link: 같은 종류의 surface와 overlay는 화면마다 같은 형태와 깊이를 사용한다.
- Glow: shape나 shadow를 대신하는 상시 광원 효과로 사용하지 않는다.
Radius 체계
기본 token은 --radius: 0.625rem이며 component는 파생 값을 사용한다.
| 이름 | 값 | 역할 |
|---|---|---|
lg | var(--radius) | 주요 control과 일반 component |
md | calc(var(--radius) - 2px) | Button, Input 등 중간 control |
sm | calc(var(--radius) - 4px) | 작은 내부 element |
xs | calc(var(--radius) - 6px) | 매우 작은 indicator |
full | 원형 | Avatar, StatusPill, badge, dot indicator |
- public component를 사용할 때 자체 radius를 덮어쓰지 않는다.
- 같은 component의 size만 바뀐다고 radius 계열을 임의로 바꾸지 않는다.
- container와 내부 control의 radius가 서로 경쟁하지 않게 한다.
full은 상태·아바타처럼 실제 capsule 또는 원형 의미가 있을 때만 사용한다.- 제품마다 새로운
rounded-[값]을 만들지 않는다.
Shape의 의미
Control
Button, Input, Select는 같은 form 흐름에서 일관된 높이와 rounded-md 계열을 유지한다. 한 field만 pill 형태로 만들거나 square하게 바꾸지 않는다.
Surface
Card, Dialog, Popover, Sheet는 public component가 제공하는 shape를 우선한다. 독립된 surface라는 이유만으로 모두 같은 큰 radius를 적용하지 않는다.
Status
Badge와 StatusPill의 capsule은 짧은 label과 상태를 하나의 단위로 묶는다. 긴 설명과 action을 pill 안에 넣지 않는다.
Brand
DotIcon의 frame과 DotCharacter의 형태는 public API와 승인 asset을 사용한다. 캐릭터를 circle crop하거나 임의의 frame에 맞춰 변형하지 않는다.
기본 elevation
기본 page surface와 Card는 shadow 없이 border와 fill로 구분하는 것이 원칙이다.
| 단계 | 표현 | 사용 |
|---|---|---|
| base | shadow 없음 | canvas, section, table, 일반 Card |
| floating | soft | Popover, dropdown, toast처럼 가까이 떠 있는 layer |
| modal | soft-lg | Dialog처럼 page interaction을 중단하는 layer |
| focus | ring | keyboard focus를 나타내는 별도 시각 신호 |
현재 shadow token:
soft: 낮고 넓은 여러 단계의 그림자soft-lg: modal에 필요한 더 큰 깊이ring:ringsemantic color를 낮은 alpha로 확장한 focus 보조
shadow 값은 직접 복사하지 않고 theme의 정의를 사용한다.
Elevation 판단
shadow를 추가하기 전에 다음을 확인한다.
- 이 element가 실제로 다른 layer 위에 떠 있는가?
- border와 surface 색만으로 경계를 이해할 수 없는가?
- focus, selected, error를 elevation과 혼동하지 않는가?
- scroll 중 sticky element라면 겹침 관계가 실제로 생기는가?
- overlay가 닫혔을 때 원래 layer 관계로 돌아가는가?
일반 Card, metric, table row에는 shadow가 필요하지 않다. 모든 surface에 shadow를 쓰면 overlay의 깊이가 약해진다.
Border와 fill
- 기본 분리는
line-subtleborder 또는 surface 차이 중 하나를 우선한다. - 선택된 중립 영역은
surface-emphasis와 필요한 border를 사용할 수 있다. - Input은
inputborder와 focus-visible ring으로 interaction state를 표현한다. - error border가 필요해도 label과 오류 문장을 함께 제공한다.
- disabled는 shadow를 제거하거나 opacity만 낮추는 것이 아니라 interaction 상태 전체를 전달한다.
- nested Card 대신 하나의 surface 안에서 row border를 사용한다.
Overlay 관계
- Popover와 DropdownMenu는 trigger와 가까운 floating layer다.
- Dialog와 AlertDialog는 배경 흐름을 중단하는 modal layer다.
- Sheet는 화면 가장자리에서 열리는 보조 layer다.
- Tooltip은 짧은 설명을 위한 가장 작은 layer이며 action이나 긴 콘텐츠를 담지 않는다.
- overlay는
DotThemeportal root 안에서 token과 reset을 유지한다. - overlay 안에 또 다른 modal을 열어 depth를 계속 쌓지 않는다.
overlay의 z-index 숫자를 화면마다 높이지 말고 component 관계로 해결한다.
Sticky와 fixed surface
- sticky header나
WorkflowBar는 content가 아래로 지나갈 때만 fill, border, 필요한 shadow를 사용한다. - fixed action이 content를 가리지 않도록 bottom padding과 safe area를 확보한다.
- scroll 전부터 과한 shadow를 표시하지 않는다.
- sticky element가 여러 개 겹치면 하나의 layer로 합치거나 명확한 순서를 정한다.
- focus target이 sticky surface 아래에 가려지지 않게 한다.
Character와 Glow
- 캐릭터는 승인된 형태, 색, 요소 관계, 여백을 그대로 사용한다.
- background와 구분하려고 캐릭터에 outline, glow, drop shadow를 임의로 추가하지 않는다.
- 2D 표현은 제품·답변·처리 맥락, 3D 표현은 넓고 드문 브랜드 맥락이라는 용도를 유지한다.
- Glow는 overlay elevation이나 focus의 대체가 아니다.
- brand surface가 필요하면
surface-brand-subtle과 승인된 gradient utility 범위 안에서 사용한다.
상태와 접근성
- focus ring은 shadow와 시각적으로 구분되고 잘리지 않아야 한다.
- selected, active, error는 elevation만으로 표현하지 않는다.
- forced colors에서 border와 control 경계가 유지되는지 확인한다.
- modal backdrop과 surface는 content 읽기와 focus 위치를 분명히 해야 한다.
- shadow가 없어도 DOM structure와 heading으로 surface 관계를 이해할 수 있어야 한다.
- reduced motion에서 overlay transition이 사라져도 layer 변화가 focus와 상태로 전달돼야 한다.
예외와 피해야 할 사용
- 화면마다 임의의 radius와 shadow 값을 만들지 않는다.
- Card 안에 Card를 중첩해 section을 표현하지 않는다.
- 중요도를 높이기 위해 radius와 shadow를 키우지 않는다.
- selected row를 떠 있는 Card처럼 만들지 않는다.
- focus ring을 shadow 스타일에 맞추려고 약하게 만들지 않는다.
- 캐릭터의 silhouette와 clear space를 container에 맞춰 자르지 않는다.
- Glow를 shadow나 modal backdrop으로 사용하지 않는다.
- sticky element에 항상 큰 shadow를 표시하지 않는다.
검토 질문
- shape가 component 종류와 interaction 범위를 설명하는가?
- radius가 token 계보 또는 public component contract를 따르는가?
- shadow가 실제 layer 겹침에만 사용되는가?
- border, fill, spacing만으로 충분한 surface는 없는가?
- overlay별 깊이와 focus 관계가 명확한가?
- selected, error, focus를 shadow 없이도 구분할 수 있는가?
- sticky/fixed element가 content와 focus를 가리지 않는가?
- 캐릭터의 형태, 색, 관계, 여백을 변경하지 않았는가?
- Glow를 elevation이나 focus 대체로 사용하지 않았는가?
- 고대비와 reduced-motion 환경에서도 layer 구조를 이해할 수 있는가?