Splitter

Splitter

크기 조절 가능한 분할 창 레이아웃 컴포넌트예요. use-splitter 훅 위에 구축되어 선언형 API와 Styles API 통합을 제공해요.

출처: 문서

본문

사용법 (Usage)

Splitter 컴포넌트는 크기 조절 가능한 분할 창 레이아웃을 제공해요. use-splitter 훅 위에 구축되어 선언형 API와 Styles API 통합을 제공해요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter>
      <Splitter.Pane defaultSize="50%">First pane</Splitter.Pane>
      <Splitter.Pane defaultSize="50%">Second pane</Splitter.Pane>
    </Splitter>
  );
}

orientation prop으로 분할 방향을 설정할 수 있어요.

CSS 단위 (CSS units)

Splitter.Pane의 defaultSize, min, max prop은 일반 숫자 외에 CSS 단위를 받아요.

  • 일반 number 또는 % 문자열('30%')은 유연한 크기예요. 패널이 다른 유연한 패널과 남은 공간을 나눠 가져요.
  • px 또는 rem 문자열('240px', '15rem')은 고정 크기예요. 컨테이너가 리사이즈되어도 패널은 픽셀 크기를 유지하고, 자기 핸들을 드래그할 때만 변경돼요.

이로써 고정 너비 사이드바와 나머지 공간을 흡수하는 유동 콘텐츠 패널을 섞을 수 있어요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter>
      <Splitter.Pane defaultSize="240px">Fixed 240px sidebar</Splitter.Pane>
      <Splitter.Pane>Flexible content</Splitter.Pane>
    </Splitter>
  );
}

크기는 선언된 단위 그대로 보고돼요. '240px' 패널은 sizes/onSizeChange에서 계속 '240px'로 유지되고, 유연한 패널은 해석된 백분율을 보고해요. 컨테이너가 고정 패널 합보다 작아지면 고정 패널은 비례적으로 줄어들어요.

세로 방향 (Vertical orientation)

orientation="vertical"로 설정하면 패널을 세로로 분할해요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter orientation="vertical">
      <Splitter.Pane defaultSize="50%">Top pane</Splitter.Pane>
      <Splitter.Pane defaultSize="50%">Bottom pane</Splitter.Pane>
    </Splitter>
  );
}

접을 수 있는 패널 (Collapsible panes)

Splitter.Pane에 collapsible prop을 설정하면 패널을 최소 크기 너머로 드래그해 접을 수 있어요. splitterRef로 프로그램 방식의 접기/펼치기를 위한 명령형 API에 접근할 수 있어요.

import { useRef } from 'react';
import { Button, Group, Splitter } from '@mantine/core';
import { UseSplitterReturnValue } from '@mantine/hooks';

function Demo() {
  const splitterRef = useRef<UseSplitterReturnValue>(null);

  return (
    <>
      <Splitter size="md">
        <Splitter.Pane collapsible defaultSize="30%">Collapsible sidebar</Splitter.Pane>
        <Splitter.Pane defaultSize="70%">Main content</Splitter.Pane>
      </Splitter>
      <Group mt="md">
        <Button onClick={() => splitterRef.current?.toggleCollapse(0)}>Toggle sidebar</Button>
      </Group>
    </>
  );
}

제어 방식 (Controlled)

패널 크기를 제어하려면 sizes와 onSizeChange prop을 사용해요.

import { useState } from 'react';
import { Button, Group, Splitter, Text } from '@mantine/core';

function Demo() {
  const [sizes, setSizes] = useState([50, 50]);

  return (
    <>
      <Splitter
        sizes={sizes}
        onSizeChange={setSizes}
      >
        <Splitter.Pane>Panel A ({Math.round(sizes[0])}%)</Splitter.Pane>
        <Splitter.Pane>Panel B ({Math.round(sizes[1])}%)</Splitter.Pane>
      </Splitter>
      <Text>Current sizes: [{sizes.map((s) => Math.round(s)).join(', ')}]</Text>
      <Group mt="md">
        <Button onClick={() => setSizes([30, 70])}>30 / 70</Button>
        <Button onClick={() => setSizes([50, 50])}>50 / 50</Button>
        <Button onClick={() => setSizes([70, 30])}>70 / 30</Button>
      </Group>
    </>
  );
}

여러 패널 (Multiple panes)

Splitter은 어떤 수의 패널이든 지원해요. 핸들은 패널 사이에 자동으로 렌더링돼요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter>
      <Splitter.Pane>First</Splitter.Pane>
      <Splitter.Pane>Second</Splitter.Pane>
      <Splitter.Pane>Third</Splitter.Pane>
    </Splitter>
  );
}

중첩 스플리터 (Nested splitters)

복잡한 레이아웃을 만들기 위해 Splitter 컴포넌트를 중첩할 수 있어요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter>
      <Splitter.Pane>Sidebar</Splitter.Pane>
      <Splitter.Pane>
        <Splitter orientation="vertical">
          <Splitter.Pane>Editor</Splitter.Pane>
          <Splitter.Pane>Terminal</Splitter.Pane>
        </Splitter>
      </Splitter.Pane>
    </Splitter>
  );
}

재분배 (Redistribute)

여러 패널을 사용할 때 redistribute prop을 설정하면 인접 패널이 min/max에 도달했을 때 비인접 패널에서 공간을 어떻게 빌려올지 제어할 수 있어요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter redistribute>
      <Splitter.Pane>Panel A</Splitter.Pane>
      <Splitter.Pane>Panel B</Splitter.Pane>
      <Splitter.Pane>Panel C</Splitter.Pane>
      <Splitter.Pane>Panel D</Splitter.Pane>
    </Splitter>
  );
}

선 크기 (Line size)

lineSize prop으로 패널 사이의 구분선 두께를 제어할 수 있어요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter lineSize={4}>
      <Splitter.Pane>First pane</Splitter.Pane>
      <Splitter.Pane>Second pane</Splitter.Pane>
    </Splitter>
  );
}

핸들 없이 (Without handle)

withHandle={false}로 설정하면 그립 아이콘이 있는 썸을 숨길 수 있어요. 패널 사이의 구분선은 여전히 보이고 드래그할 수 있어요.

import { Splitter } from '@mantine/core';

function Demo() {
  return (
    <Splitter withHandle={false}>
      <Splitter.Pane>First pane</Splitter.Pane>
      <Splitter.Pane>Second pane</Splitter.Pane>
    </Splitter>
  );
}

명령형 API (Imperative API)

splitterRef prop으로 명령형 스플리터 API에 접근할 수 있어요.

import { useRef } from 'react';
import { Splitter } from '@mantine/core';
import { UseSplitterReturnValue } from '@mantine/hooks';

function Demo() {
  const splitterRef = useRef<UseSplitterReturnValue>(null);

  return (
    <>
      <Button onClick={() => splitterRef.current?.collapse(0)}>Collapse first pane</Button>
      <Splitter splitterRef={splitterRef}>
        <Splitter.Pane>First pane</Splitter.Pane>
        <Splitter.Pane>Second pane</Splitter.Pane>
      </Splitter>
    </>
  );
}

Splitter.Pane 감싸기 (Wrap Splitter.Pane)

Splitter 컴포넌트는 Splitter.Pane의 순서에 의존해요. Splitter.Pane을 감싸는 것은 지원되지 않아요. Splitter.Pane은 반드시 Splitter의 직접 자식이어야 해요.

import { Splitter } from '@mantine/core';

// This will not work – wrapped pane will not be recognized
function WillNotWork() {
  return (
    <Splitter>
      <PaneWrapper>This part will not render correctly</PaneWrapper>
    </Splitter>
  );
}

// Create a separate component for pane content instead
function PaneContent() {
  return <div>This will work as expected!</div>;
}

function Demo() {
  return (
    <Splitter>
      <Splitter.Pane>
        {/* Do not wrap Splitter.Pane in another component */}
        <PaneContent />
      </Splitter.Pane>
      <Splitter.Pane>First pane</Splitter.Pane>
    </Splitter>
  );
}

use-splitter 훅

Splitter 컴포넌트는 use-splitter 훅 위에 구축돼요. 레이아웃과 스타일링을 더 제어해야 한다면 훅을 직접 사용할 수 있어요.

더 알아보기 (Learn more)