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-stateopen/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-...] 속성 선택자를 감싸는 변형자다.