Pagination
Pagination
활성 페이지를 표시하고 여러 페이지 사이를 탐색하는 컴포넌트예요.
출처: 문서
본문
사용법 (Usage)
Pagination으로 활성 페이지를 표시하고 여러 페이지 사이를 탐색할 수 있어요. total, color, size, radius, withControls, withEdges, disabled 등의 prop을 지원해요.
import { Pagination } from '@mantine/core';
function Demo() {
return <Pagination total={10} />;
}
청크 콘텐츠 예시 (Example with chunked content)
데이터를 페이지 크기로 나눠 Pagination과 함께 사용하는 예시예요.
import { useState } from 'react';
import { randomId } from '@mantine/hooks';
import { Pagination, Text } from '@mantine/core';
function chunk<T>(array: T[], size: number): T[][] {
if (!array.length) {
return [];
}
const head = array.slice(0, size);
const tail = array.slice(size);
return [head, ...chunk(tail, size)];
}
const data = chunk(
Array(30)
.fill(0)
.map((_, index) => ({ id: index, name: randomId() })),
5
);
function Demo() {
const [activePage, setPage] = useState(1);
const items = data[activePage - 1].map((item) => (
<Text key={item.id}>id: {item.id}, name: {item.name}</Text>
));
return (
<>
{items}
<Pagination total={data.length} value={activePage} onChange={setPage} mt="sm" />
</>
);
}
제어 방식 (Controlled)
컴포넌트 상태를 제어하려면 value와 onChange prop을 제공해요.
import { useState } from 'react';
import { Pagination } from '@mantine/core';
function Demo() {
const [activePage, setPage] = useState(1);
return <Pagination value={activePage} onChange={setPage} total={10} />;
}
형제 수 (Siblings)
siblings prop으로 활성 항목 형제의 수를 제어해요.
import { Text, Pagination } from '@mantine/core';
function Demo() {
return (
<>
<Text>1 sibling (default)</Text>
<Pagination total={20} siblings={1} />
<Text>2 siblings</Text>
<Pagination total={20} siblings={2} />
<Text>3 siblings</Text>
<Pagination total={20} siblings={3} />
</>
);
}
경계 수 (Boundaries)
boundaries prop으로 이전 버튼 뒤와 다음 버튼 앞에 표시할 항목 수를 제어해요.
import { Text, Pagination } from '@mantine/core';
function Demo() {
return (
<>
<Text>1 boundary (default)</Text>
<Pagination total={20} boundaries={1} />
<Text>2 boundaries</Text>
<Pagination total={20} boundaries={2} />
<Text>3 boundaries</Text>
<Pagination total={20} boundaries={3} />
</>
);
}
반응형 레이아웃 (Responsive layout)
layout="responsive"로 설정하면 CSS 컨테이너 쿼리를 사용해 컨테이너가 좁을 때 컴팩트한 "Page X of Y" 라벨을 표시할 수 있어요. formatLabel prop으로 라벨 텍스트를 커스터마이즈해요.
import { Box, Pagination } from '@mantine/core';
function Demo() {
return (
<Box w={200}>
<Pagination total={20} layout="responsive" />
</Box>
);
}
페이지 컨트롤 숨기기 (Hide pages controls)
withPages={false}로 설정하면 페이지 컨트롤을 숨길 수 있어요.
import { useState } from 'react';
import { Group, Pagination, Text } from '@mantine/core';
const limit = 10;
const total = 145;
const totalPages = Math.ceil(total / limit);
function Demo() {
const [page, setPage] = useState(1);
const message = `Showing ${limit * (page - 1) + 1} – ${Math.min(total, limit * page)} of ${total}`;
return (
<Group justify="space-between">
<Text>{message}</Text>
<Pagination total={totalPages} value={page} onChange={setPage} withPages={false} />
</Group>
);
}
Styles API
Pagination은 Styles API를 지원해요. classNames prop으로 컴포넌트의 내부 요소에 스타일을 추가할 수 있어요.
Styles API 셀렉터:
root– 루트 요소control– 컨트롤 요소: 항목, 다음/이전, 처음/마지막 버튼dots– 점 아이콘 래퍼items– 페이지 번호 컨트롤 주변 래퍼,layout="responsive"와 함께 사용label–layout="responsive"에서 좁은 컨테이너에 표시되는 컴팩트 라벨 요소
복합 컴포넌트 (Compound components)
Pagination 렌더링을 완전히 제어하려면 다음 복합 컴포넌트를 사용할 수 있어요.
Pagination.Root– 컨텍스트 제공자Pagination.Items– 항목 목록Pagination.Next– 다음 컨트롤Pagination.Previous– 이전 컨트롤Pagination.First– 처음 컨트롤Pagination.Last– 마지막 컨트롤Pagination.Label– 반응형 레이아웃용 컴팩트 라벨
import { Group, Pagination } from '@mantine/core';
function Demo() {
return (
<Pagination.Root total={10}>
<Group gap={7}>
<Pagination.First />
<Pagination.Previous />
<Pagination.Items />
<Pagination.Next />
<Pagination.Last />
</Group>
</Pagination.Root>
);
}
컨트롤을 링크로 (Controls as links)
getItemProps와 getControlProps로 컨트롤을 링크로 렌더링할 수 있어요.
import { Group, Pagination } from '@mantine/core';
function Demo() {
return (
<>
{/* Regular pagination */}
<Pagination
total={10}
getItemProps={(page) => ({ component: 'a', href: `#page-${page}` })}
getControlProps={(control) => {
if (control === 'first') return { component: 'a', href: '#page-0' };
if (control === 'last') return { component: 'a', href: '#page-10' };
if (control === 'next') return { component: 'a', href: '#page-2' };
if (control === 'previous') return { component: 'a', href: '#page-1' };
return {};
}}
/>
</>
);
}
아이콘 변경 (Change icons)
icons prop으로 이전/다음/처음/마지막/점 아이콘을 변경할 수 있어요.
import { Group, Pagination } from '@mantine/core';
import { ArrowLineRightIcon, ArrowLineLeftIcon, ArrowLeftIcon, ArrowRightIcon, DotsSixIcon } from '@phosphor-icons/react';
function Demo() {
return (
<Pagination
total={10}
icons={{
first: <ArrowLineLeftIcon size={16} />,
last: <ArrowLineRightIcon size={16} />,
next: <ArrowRightIcon size={16} />,
previous: <ArrowLeftIcon size={16} />,
dots: <DotsSixIcon size={16} />,
}}
/>
);
}
autoContrast
Pagination은 autoContrast prop과 theme.autoContrast를 지원해요. Pagination 또는 테마에 autoContrast가 설정되면 color prop에 지정된 값과 충분한 대비가 있도록 콘텐츠 색상이 조정돼요.
autoContrast 기능은 color prop으로 배경색을 변경할 때만 동작해요.
import { Pagination, Stack, Text } from '@mantine/core';
function Demo() {
return (
<Stack>
<Text>autoContrast: off</Text>
<Pagination total={10} color="red" />
<Text>autoContrast: on</Text>
<Pagination total={10} color="red" autoContrast />
</Stack>
);
}
컨트롤 크기 (Controls size)
기본적으로 페이지네이션 컨트롤은 인풋과 버튼보다 작은 크기를 가져요. 컨트롤을 인풋·버튼과 같은 크기로 만들려면 size prop에 input- 접두사를 사용할 수 있어요.
import { Button, Group, Pagination, TextInput } from '@mantine/core';
function Demo() {
return (
<Group>
<TextInput size="sm" placeholder="sm input" />
<Button size="sm">sm button</Button>
<Pagination total={10} size="input-sm" />
</Group>
);
}
시작 값 (Start value)
startValue로 시작 페이지 번호를 정의할 수 있어요. 예를 들어 startValue={5}와 total={15}를 사용하면 페이지네이션 범위는 5부터 15까지예요.
import { Text, Pagination } from '@mantine/core';
function Demo() {
return (
<>
<Text>Pages 5–15 (startValue=5, total=15)</Text>
<Pagination startValue={5} total={15} />
</>
);
}
URL 동기화 (URL synchronization)
페이지네이션 상태를 URL 쿼리 매개변수와 동기화할 수 있어요. 이 패턴은 특정 페이지가 선택된 URL을 공유하고 싶은 목록 뷰에서 흔히 사용돼요.
Next.js
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { Pagination } from '@mantine/core';
function Demo() {
const router = useRouter();
const searchParams = useSearchParams();
const pathname = usePathname();
const page = Number(searchParams.get('page')) || 1;
const handlePageChange = (p: number) => {
const params = new URLSearchParams(searchParams);
params.set('page', p.toString());
router.push(`${pathname}?${params.toString()}`);
};
return <Pagination total={10} value={page} onChange={handlePageChange} />;
}
react-router-dom
import { useSearchParams } from 'react-router-dom';
import { Pagination } from '@mantine/core';
function Demo() {
const [searchParams, setSearchParams] = useSearchParams();
const page = Number(searchParams.get('page')) || 1;
const handlePageChange = (p: number) => {
setSearchParams({ page: p.toString() });
};
return <Pagination total={10} value={page} onChange={handlePageChange} />;
}
nuqs
nuqs를 사용하는 예시:
import { useQueryState, parseAsInteger } from 'nuqs';
import { Pagination } from '@mantine/core';
function Demo() {
const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1));
return <Pagination total={10} value={page} onChange={setPage} />;
}
use-pagination 훅
더 많은 유연성이 필요하다면 @mantine/hooks 패키지가 use-pagination 훅을 내보내요. 커스텀 페이지네이션 컴포넌트를 만드는 데 사용할 수 있어요.