들어가며
✍️ Headless UI
아래에서 구현한 버튼을 통해 프로젝트 전반에서 재사용 가능한 컴포넌트를 구축하고, 디자인과 기능을 분리하는 경험을 쌓고자 했습니다.
💭 초기 목표
- 토글
: 사용자가 나의카드에서 상태를 쉽게 전환할 수 있도록 합니다. - 기본 버튼
: 링크 연결 및 페이지 이동 기능을 제공합니다. - Submit 버튼
: 폼 제출을 구현합니다.
🖼️ 현실
- Headless UI를 기반으로 다음과 같은 버튼 컴포넌트를 설계하고 구현하였습니다.
- 각 버튼의 특성을 유지하면서도 커스터마이징할 수 있도록 작업했습니다. (버튼 내용: children)
1. MyToggle: 상태 변경을 위한 토글 버튼
- 사용자의 상호작용에 따라 상태를 변경하는 버튼입니다.
- Headless UI의 Switch 컴포넌트를 활용하여, 상태 변화에 따라 UI가 동적으로 업데이트되도록 설계했습니다.
- 상태 관리
- useState를 사용해 enabled라는 상태를 정의하고, 이 상태 값에 따라 버튼의 스타일이 달라지도록 구현했습니다.
const [enabled, setEnabled] = useState(false);
- UI 동적 스타일링
- enabled 값에 따라 배경 색상이 bg-blue-600에서 bg-gray-200로 변경됩니다.
- 버튼 내부의 원(circle)이 translate-x-6 또는 translate-x-1으로 이동하면서 토글 효과를 제공합니다.
className={`${enabled ? 'bg-blue-600' : 'bg-gray-200'} relative inline-flex h-6 w-11 items-center rounded-full`}
- 접근성 고려
- 시각적 버튼 외에도 sr-only 클래스를 사용해 스크린 리더 사용자들에게도 버튼의 기능(알림 활성화)을 설명했습니다.
- sr-only: Screen Reader Only, 요소의 내용을 시각적으로 숨기되 스크린 리더에게는 노출되도록 하는 기능 (웹 접근성을 고려해 콘텐츠 숨기기)
<span className="sr-only">Enable notifications</span>
2. MyFullButton: 링크 연결용 버튼
- 클릭하면 지정된 페이지로 이동하는 기본 버튼입니다.
- Headless UI의 Button과 Next.js의 Link를 조합하여 구현했습니다.
- 구조
- 버튼은 Link 컴포넌트로 감싸져 있으며, href 속성을 통해 이동할 페이지를 동적으로 설정할 수 있습니다.
- 이 구조 덕분에 children으로 버튼 텍스트나 콘텐츠를 필요에 따라 변경할 수 있습니다.
<Link href={href}>
<Button className="rounded bg-blue-600 py-2 px-4 text-sm text-white data-[hover]:bg-blue-500 data-[active]:bg-sky-700">
{children}
</Button>
</Link>
- 스타일링
- Tailwind CSS를 사용해 버튼의 배경 색상을 상태(기본, hover, active)에 따라 동적으로 변경했습니다.
- hover 상태에서는 bg-blue-500, active 상태에서는 bg-sky-700 스타일이 적용됩니다.
className="rounded bg-blue-600 py-2 px-4 text-sm text-white data-[hover]:bg-blue-500 data-[active]:bg-sky-700"
3. MyFullSubmitButton: 폼 제출용 버튼
- 사용자가 폼 데이터를 제출할 수 있도록 설계된 컴포넌트입니다.
- Headless UI의 Button을 활용하여 제출 버튼의 동작과 스타일을 구현했습니다.
- 구조
- 폼을 감싸는 form 태그를 포함하고 있으며, action 속성을 통해 데이터를 전송할 URL을 설정할 수 있습니다.
- 버튼은 type="submit" 속성을 사용하여 폼 제출 이벤트를 트리거합니다.
<form action={action} method="POST">
<Button
type="submit"
className="rounded bg-blue-600 py-2 px-4 text-sm text-white data-[hover]:bg-blue-500 data-[active]:bg-sky-700">
{children}
</Button>
</form>
- 커스터마이징
- 텍스트는 children을 통해 동적으로 설정되며, 버튼 스타일은 재사용 가능한 형태로 일관성을 유지합니다.
✏️ 배운 점
Headless UI의 장점 체감
💡Headless UI란?
: 시각적 디자인과 컴포넌트의 기능을 분리하여 각각 독립적으로 개발된 디자인 시스템
- 특징
- 디자인과 기능 분리
디자인 시스템 변경 시 코드에 미치는 영향을 최소화할 수 있습니다. - 커스터마이징
기본 컴포넌트의 틀을 유지하면서도 children과 className으로 자유롭게 스타일을 조정할 수 있습니다.
- 디자인과 기능 분리
- Headless UI의 기본 제공 구조 덕분에 빠르게 구현할 수 있었습니다.
- 기능에만 집중할 수 있게 만들어주는 도구라는 점을 체감하였습니다.
- https://headlessui.com/
Headless UI
Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
headlessui.com
🎯 목적
- 지속
- Headless UI의 다른 컴포넌트들도 적극적으로 활용해 UI 구축 속도를 높일 계획입니다.
- 현재 작성한 버튼 컴포넌트들을 다양한 시나리오에 대응할 수 있도록 최적화할 것입니다.
- 개선
- 코드 내 반복되는 스타일링 패턴을 공통 유틸리티 클래스로 추출하여 관리합니다.
- 팀원들에게 컴포넌트 활용법을 공유하고 디자인 시스템의 통합성을 강화할 예정입니다.
- 포기
- 기존에 사용하던 일회성 버튼 스타일 코드를 모두 제거하고, Headless UI 기반으로 일원화할 예정입니다.
반응형