ページネーション部品
:LiTarget: 用途
前/次 + ページ番号表示。1…5 6 7 …100 形式の省略表示対応。
:LiSparkle: 特徴
- 前/次ボタン
- ページ番号
- 省略表示(…)
- モバイル対応
:LiCode: コード(コピペ用)
export function Pagination({
page, totalPages, onChange,
}: {
page: number; totalPages: number; onChange: (p: number) => void;
}) {
if (totalPages <= 1) return null;
// 表示ページ計算: 1, 2, ..., current-1, current, current+1, ..., last-1, last
const pages = new Set<number>();
pages.add(1); pages.add(totalPages);
for (let i = page - 1; i <= page + 1; i++) {
if (i >= 1 && i <= totalPages) pages.add(i);
}
const sorted = [...pages].sort((a, b) => a - b);
const items: (number | '...')[] = [];
for (let i = 0; i < sorted.length; i++) {
items.push(sorted[i]);
if (i < sorted.length - 1 && sorted[i + 1] - sorted[i] > 1) items.push('...');
}
return (
<div style={{ display: 'flex', gap: '.35rem', alignItems: 'center' }}>
<button onClick={() => onChange(Math.max(1, page - 1))} disabled={page === 1}>←</button>
{items.map((it, i) => it === '...' ? (
<span key={'el-' + i} style={{ padding: '0 .5rem', color: '#71717a' }}>…</span>
) : (
<button key={it} onClick={() => onChange(it)}
style={{ fontWeight: it === page ? 700 : 400, color: it === page ? '#a5b4fc' : 'inherit' }}>
{it}
</button>
))}
<button onClick={() => onChange(Math.min(totalPages, page + 1))} disabled={page === totalPages}>→</button>
</div>
);
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加