Resizable#
드래그 핸들을 사용하여 패널 간 크기를 조절할 수 있는 분할 레이아웃 컴포넌트입니다.
Live Preview#
Web
Flutter
Loading Flutter...
class ResizableDefaultExample extends StatelessComponent {
const ResizableDefaultExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return div(
[
CoResizable(
panes: [
CoreResizablePaneData<Component>(
content: div(
[Component.text('Panel A')],
classes: 'flex items-center justify-center bg-${cs.surfaceContainer} text-${cs.onSurface} h-full',
),
initialSize: 0.4,
),
CoreResizablePaneData<Component>(
content: div(
[Component.text('Panel B')],
classes: 'flex items-center justify-center bg-${cs.surfaceContainerHigh} text-${cs.onSurface} h-full',
),
initialSize: 0.6,
),
],
),
],
styles: Styles(raw: {'width': '100%', 'height': '200px'}),
);
}
}
class ResizableDefaultExample extends StatelessWidget {
const ResizableDefaultExample({super.key});
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
final onSurface = scheme.onSurface!;
return SizedBox(
height: 200,
child: CoResizable(
panes: [
CoreResizablePaneData(
content: Container(
color: scheme.surfaceContainer!,
alignment: Alignment.center,
child: Text('Panel A', style: TextStyle(color: onSurface)),
),
initialSize: 0.4,
),
CoreResizablePaneData(
content: Container(
color: scheme.surfaceContainerHigh!,
alignment: Alignment.center,
child: Text('Panel B', style: TextStyle(color: onSurface)),
),
initialSize: 0.6,
),
],
),
);
}
}
수직 분할#
Web
Flutter
Loading Flutter...
class ResizableVerticalExample extends StatelessComponent {
const ResizableVerticalExample({super.key});
@override
Component build(BuildContext context) {
final cs = context.colorScheme;
return div(
[
CoResizable(
direction: CoreResizableDirection.vertical,
panes: [
CoreResizablePaneData<Component>(
content: div(
[Component.text('Top')],
classes: 'flex items-center justify-center bg-${cs.surfaceContainer} text-${cs.onSurface} h-full',
),
initialSize: 0.5,
),
CoreResizablePaneData<Component>(
content: div(
[Component.text('Bottom')],
classes: 'flex items-center justify-center bg-${cs.surfaceContainerHigh} text-${cs.onSurface} h-full',
),
initialSize: 0.5,
),
],
),
],
styles: Styles(raw: {'width': '100%', 'height': '260px'}),
);
}
}
class ResizableVerticalExample extends StatelessWidget {
const ResizableVerticalExample({super.key});
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
final onSurface = scheme.onSurface!;
return SizedBox(
height: 260,
child: CoResizable(
direction: CoreResizableDirection.vertical,
panes: [
CoreResizablePaneData(
content: Container(
color: scheme.surfaceContainer!,
alignment: Alignment.center,
child: Text('Top', style: TextStyle(color: onSurface)),
),
initialSize: 0.5,
),
CoreResizablePaneData(
content: Container(
color: scheme.surfaceContainerHigh!,
alignment: Alignment.center,
child: Text('Bottom', style: TextStyle(color: onSurface)),
),
initialSize: 0.5,
),
],
),
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- IDE, 코드 에디터, 대시보드처럼 사용자가 패널 크기를 직접 조정해야 할 때
- 좌우 또는 상하로 분할된 레이아웃에서 각 패널의 비율을 사용자가 선택하게 할 때
- 세 개 이상의 패널을 유연하게 분할 배치할 때
대신 다른 컴포넌트를 사용하세요:
Separator: 크기 조절 없이 시각적 구분선만 필요할 때Row/Column: 고정된 비율의 레이아웃에는 일반 레이아웃 위젯 사용
기본 사용법 (Basic Usage)#
// 수평 분할 패널
CoResizable(
panes: [
CoreResizablePaneData(
content: SidebarPanel(),
initialSize: 0.3,
),
CoreResizablePaneData(
content: MainContentPanel(),
initialSize: 0.7,
),
],
)
// 수직 분할 (min/max 제한 포함)
CoResizable(
direction: CoreResizableDirection.vertical,
onResize: (sizes) => saveLayout(sizes),
panes: [
CoreResizablePaneData(
content: EditorPanel(),
initialSize: 0.6,
minSize: 0.2,
),
CoreResizablePaneData(
content: TerminalPanel(),
initialSize: 0.4,
minSize: 0.1,
maxSize: 0.6,
),
],
)
// 수평 분할 패널
CoResizable(
panes: [
CoreResizablePaneData<Component>(
content: div(
[Component.text('사이드바')],
classes: 'flex items-center justify-center h-full',
),
initialSize: 0.3,
),
CoreResizablePaneData<Component>(
content: div(
[Component.text('메인 콘텐츠')],
classes: 'flex items-center justify-center h-full',
),
initialSize: 0.7,
),
],
)
// 수직 분할
CoResizable(
direction: CoreResizableDirection.vertical,
panes: [
CoreResizablePaneData<Component>(
content: div([Component.text('에디터')]),
initialSize: 0.6,
),
CoreResizablePaneData<Component>(
content: div([Component.text('터미널')]),
initialSize: 0.4,
),
],
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
panes |
List<CoreResizablePaneData<W>> |
필수 | 분할할 패널 목록 |
direction |
CoreResizableDirection |
horizontal |
분할 방향 (horizontal, vertical) |
onResize |
void Function(List<double>)? |
null |
크기 변경 콜백 (ratio 배열) |
dividerThickness |
double? |
CoreBorderWidth.thick |
디바이더 두께 (px) |
CoreResizablePaneData<W>#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
content |
W (Widget / Component) |
필수 | 패널 내부 콘텐츠 |
initialSize |
double |
0.5 |
초기 크기 비율 (0.0~1.0) |
minSize |
double? |
null |
최소 크기 비율 |
maxSize |
double? |
null |
최대 크기 비율 |
동작 스펙 (Behavior)#
인터랙션#
- 드래그: 디바이더를 드래그하여 인접 패널 크기 실시간 조정
- 커서 변경: 수평은
col-resize, 수직은row-resize - min/max 제한: 드래그가 제한 범위를 벗어나면 무시됨
상태 전환#
idle→dragging: 디바이더 드래그 시작dragging→idle: 드래그 종료 (마우스 업)- 드래그 중 문서 전역에서 마우스 이동을 추적 (요소 밖으로 벗어나도 유지)
애니메이션#
- 드래그 중 즉시 반응 (애니메이션 없음)
- 디바이더 색상은 hover 시
CoreDuration.short(150ms) 전환
사용 가이드라인 (Usage Guidelines)#
✅ Do#
minSize로 패널이 너무 좁아지지 않도록 제한
CoResizable(
panes: [
CoreResizablePaneData(
content: SidebarPanel(),
initialSize: 0.3,
minSize: 0.2,
),
CoreResizablePaneData(
content: ContentPanel(),
initialSize: 0.7,
),
],
)
최소 크기 제한이 없으면 사용자가 패널을 완전히 닫아 콘텐츠에 접근하지 못할 수 있습니다.
❌ Don't#
너무 많은 패널을 한 번에 분할하지 않기
패널이 4개를 초과하면 각 패널이 너무 좁아져 콘텐츠를 표시하기 어렵습니다.
✅ Do#
onResize 콜백으로 사용자 설정 저장
CoResizable(
onResize: (sizes) => preferences.saveSizes(sizes),
panes: panes,
)
사용자가 설정한 패널 크기를 저장하면 다음 방문 시 동일한 레이아웃이 유지됩니다.
접근성 (Accessibility)#
포커스 & 커서#
- 디바이더 hover 시 리사이즈 커서 표시
- 터치 타겟을 위해 디바이더 hit-test 영역은
CoreSpace.space8(8px)
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CoResizable | CoResizable |
| 패널 타입 | CoreResizablePaneData<Widget> |
CoreResizablePaneData<Component> |
| 드래그 감지 | GestureDetector |
mousedown + document listeners |
| 레이아웃 | LayoutBuilder + Row/Column + Expanded |
CSS flex + ratio 기반 flex-grow |