blog
Radix UI의 data-* 상태 속성과 Tailwind data 변형자
Front-end / CSS#Radix UI#shadcn/ui#Tailwind CSS#data attribute
Radix UI는 상태를 data-* 속성으로 노출한다
Radix UI(그리고 이를 기반으로 한 shadcn/ui)는 컴포넌트의 상태를 DOM의 data-* 속성으로 표시한다.
<!-- Select 트리거: 닫힘 / 열림 -->
<button data-state="closed">선택하세요</button>
<button data-state="open">선택하세요</button>
<!-- 값을 선택하지 않아 placeholder가 보이는 상태 -->
<button data-placeholder="">선택하세요</button>
자주 보는 속성:
| 속성 | 의미 |
|---|---|
data-state | open/closed, checked/unchecked, active/inactive 등 |
data-placeholder | 값이 없어 placeholder를 표시 중 |
data-disabled | 비활성화 |
data-highlighted | 키보드·마우스로 강조된 항목 |
data-side | 팝오버가 열린 방향(top, bottom, left, right) |
어떤 속성이 붙는지는 컴포넌트마다 다르므로 Radix 문서의 각 컴포넌트 "Data attributes" 표를 확인한다.
Tailwind로 상태별 스타일 지정
Tailwind의 data-* 변형자는 CSS 속성 선택자로 변환된다.
<SelectTrigger className="text-gray-900 data-[placeholder]:text-gray-400 data-[state=open]:ring-2" />
/* 생성되는 CSS (개념) */
.data-\[placeholder\]\:text-gray-400[data-placeholder] { color: ...; }
.data-\[state\=open\]\:ring-2[data-state="open"] { box-shadow: ...; }
data-[placeholder]: 속성이 존재하면 매칭된다(값 무관).data-[state=open]: 속성 값이open일 때 매칭된다.
클래스는 항상 붙어 있고, Radix가 상태에 따라 속성을 붙였다 뗐다 하므로 스타일이 자동으로 바뀐다. 상태를 React state로 따로 들고 className을 조건부로 바꿀 필요가 없다.
문법 정리
| 변형자 | 선택자 | 지원 버전 |
|---|---|---|
data-[state=open]: | [data-state="open"] | v3.2+ |
data-[placeholder]: | [data-placeholder] | v3.2+ |
data-placeholder: | [data-placeholder] | v4 (불리언 속성 축약) |
aria-expanded: | [aria-expanded="true"] | v3.2+ |
aria-[sort=ascending]: | [aria-sort="ascending"] | v3.2+ |
group-data-[state=open]: | 부모 .group의 속성 기준 | v3.2+ |
자식 아이콘을 부모 상태에 맞춰 돌리는 패턴이 자주 쓰인다.
<AccordionTrigger className="group">
제목
<ChevronDown className="transition-transform group-data-[state=open]:rotate-180" />
</AccordionTrigger>
Tailwind의 변형자는 모두 변형자:유틸리티 형식을 따른다. hover:가 :hover 가상 클래스를 감싸듯, data-[...]:는 [data-...] 속성 선택자를 감싸는 변형자다.