본문으로 건너뛰기
레이아웃 / splitter

Splitter

키보드·a11y 갖춘 2-pane 리사이즈 컨테이너.
레이아웃splitterStatic specimensplitter스플리터resize리사이즈
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

키보드·a11y 갖춘 2-pane 리사이즈 컨테이너.

Workbench 불러오는 중…
Component intent의도와 경계 읽기

두 pane 을 가로(좌/우) 또는 세로(상/하)로 나누고 사이 핸들로 크기를 조절한다. Blueprint 의 마우스 전용 ResizeHandle 을 role="separator" + 화살표/Home/End 키보드 + 터치 히트영역 확장으로 일반화했다. controlled(size + onSizeChange)와 uncontrolled(defaultSize) 를 모두 지원하며, 드래그 중에는 rAF 로 첫 pane DOM 에 직접 써 리렌더를 억제하고 커밋은 pointerup 1회만 수행한다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01uncontrolled (좌/우)tsxfragment
uncontrolled (좌/우)
import { Splitter } from "@axe/ui";<Splitter orientation="horizontal" defaultSize="40%" minSize={200}>  <nav>목록</nav>  <main>상세</main></Splitter>
02controlledtsxfragment
controlled
import { Splitter } from "@axe/ui";import { useState } from "react";function Panes() {  const [w, setW] = useState(320);  return (    <Splitter orientation="horizontal" size={w} onSizeChange={setW} minSize={160}>      <aside>사이드</aside>      <section>본문</section>    </Splitter>  );}
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
orientation"horizontal" | "vertical"필수pane 배치 축. horizontal = 좌/우, vertical = 상/하.
defaultSizenumber | string"50%"uncontrolled 초기 크기. number=px, string=CSS length(예 "50%"). string 이면 mount 후 컨테이너 측정으로 px 환산.
sizenumbercontrolled px. 지정 시 defaultSize 무시 — 크기를 소비자가 소유.
onSizeChange(px: number) => void크기 확정 시 호출. 키보드는 즉시, 드래그는 pointerup 에서 1회. controlled 소비자는 여기서 size 를 갱신.
minSizenumber80첫 pane 최소 px.
maxSizenumber첫 pane 최대 px. 미지정 시 컨테이너 측정값 − minSize 로 자동 산출.
children[React.ReactNode, React.ReactNode]필수정확히 2개. [0]=첫 pane(크기 제어 대상), [1]=둘째 pane(남는 공간).
...restOmit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange">className 은 병합, 나머지는 루트 div 로 전파.
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-splitterstable루트 flex 컨테이너(width/height 100%, min 0).
.axe-splitter--horizontalstableflex-direction:row(좌/우 분할).
.axe-splitter--verticalstableflex-direction:column(상/하 분할).
.axe-splitter__panestablepane 공통 — min 0 + overflow:auto.
.axe-splitter__pane--secondstable둘째 pane — flex:1 1 auto 로 남는 공간 차지(첫 pane 은 인라인 width/height 로 크기 고정).
.axe-splitter__handlestable드래그/포커스 핸들(role=separator). 시각 6px + ::before 26px 히트영역(WCAG 2.5.5). hover/focus 시 accent.
.axe-splitter__handle-barstable핸들 중앙 시각 바(2×36px, aria-hidden 장식).
비-React 소비 노트
리사이즈는 포인터/키보드 JS 로직에 의존 — 순수 CSS 로는 재현 불가(정적 2단 레이아웃만 가능). 첫 pane 크기는 컴포넌트가 인라인 style(width/height)로 주므로 CSS-only 소비 시 직접 지정해야 한다.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • ←/→(horizontal) 또는 ↑/↓(vertical) — 핸들 포커스 시 ±5px
  • Shift + 화살표 — ±20px
  • Home — 첫 pane 을 minSize 로
  • End — 첫 pane 을 maxSize(지정/자동)로
ARIA

핸들은 role="separator" + tabIndex 0. aria-orientation 은 핸들 바의 축 기준이라 orientation 과 반대(좌우 분할=vertical 바, 상하 분할=horizontal 바). aria-valuenow/valuemin/valuemax = 첫 pane px, aria-valuetext 는 사람이 읽는 "Left/Top pane Npx of Mpx (P%)", aria-label="Resize panels". 시각 바(__handle-bar)는 aria-hidden.

Notes

포인터 캡처 드래그는 rAF 로 프레임당 1회 첫 pane DOM 에 직접 쓰고, state/onSizeChange 커밋은 pointerup 1회(고주사율 기기 과렌더 방지). prefers-reduced-motion 에서 핸들 트랜지션 제거. 알려진 한계: controlled 소비자가 onSizeChange 를 무시(size prop 유지)하고 리렌더도 없으면 드래그 잔여 px 가 남을 수 있음.

06 · Judgment

권장 · 지양

권장
  • 리사이즈 대상(사이드바·에디터 등)을 첫 pane 에 두고 본문을 둘째 pane 에 둔다.
  • minSize 를 충분히 줘 pane 이 조작 불가능할 만큼 접히지 않게 한다.
지양
  • children 을 2개가 아닌 수로 넘기지 말 것(타입이 정확히 2-tuple).
  • controlled 로 쓰면서 onSizeChange 를 무시하지 말 것(드래그가 커밋되지 않음).
검색창을 열면 컴포넌트 인덱스를 불러옵니다.