폼·입력

인디케이터가 미끄러지는 세그먼티드 컨트롤

선택을 바꾸면 흰 thumb가 그 자리로 미끄러지는 세그먼티드 컨트롤. 버튼 위치를 측정해 transform으로 이동하고 키보드도 지원합니다.

ReactTypeScriptuseLayoutEffectCSS transformARIA radiogroup
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약

옵션 버튼 뒤의 인디케이터가 선택한 자리로 부드럽게 미끄러지는, 폼 입력용 세그먼티드 컨트롤입니다.

이럴 때 필요해요

2~5개 중 하나를 고르는 상호배타 선택(보기 모드, 요금제, 정렬 기준)에 라디오 버튼은 투박합니다. 세그먼티드 컨트롤은 선택지를 한 줄에 모아 공간을 아끼고, 미끄러지는 인디케이터로 "지금 무엇이 선택됐는지"를 또렷하게 전달합니다.

어떻게 동작하나

  1. 선택된 버튼의 offsetLeftoffsetWidth를 측정합니다.

  2. 그 값을 인디케이터의 leftwidth로 주고 transition으로 이동시킵니다.

  3. 컨테이너 폭이 바뀌면(반응형) resize에서 다시 측정해 어긋남을 막습니다.

놓치기 쉬운 것

  • 측정은 useLayoutEffect에서 해야 첫 페인트 전에 위치가 잡혀 깜빡이지 않습니다.

  • 반응형으로 폭이 바뀌면 재측정이 필요합니다 안 하면 인디케이터가 어긋납니다.

  • role=radiogrouparia-checked와 화살표 키 이동으로 접근성을 갖춰야 합니다.

이런 곳에 써요

  • 보기 모드 전환(리스트/그리드), 월간/연간 요금 토글

  • 필터정렬 기준 선택, 탭형 세그먼트

소스 코드

· 데모 페이지에서 자동 추출
import type { Metadata } from "next";
import { SegmentedControlDemo } from "./-components/SegmentedControlDemo";

export const metadata: Metadata = {
  title: "세그먼티드 제어 (데모)",
  description:
    "선택지 사이로 미끄러지는 인디케이터(thumb)가 있는 세그먼티드 컨트롤. 버튼 위치 측정 후 transform 슬라이드 + 키보드 ←/→ + ARIA radiogroup.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50/40">
      <SegmentedControlDemo />
    </main>
  );
}
20조회수

댓글