一括操作パターン
:LiTarget: 用途
複数選択→一括削除/編集/エクスポートのUIパターン。
:LiSparkle: 特徴
- 複数選択
- チェックボックス
- 一括アクションメニュー
:LiCode: コード(コピペ用)
import { useState } from 'react';
// 一括選択 + アクションフック
export function useBulkSelection<T extends { id: string }>(items: T[]) {
const [selected, setSelected] = useState<Set<string>>(new Set());
const toggle = (id: string) => setSelected((s) => {
const n = new Set(s);
n.has(id) ? n.delete(id) : n.add(id);
return n;
});
const toggleAll = () => setSelected((s) =>
s.size === items.length ? new Set() : new Set(items.map((i) => i.id))
);
const clear = () => setSelected(new Set());
return {
selected, toggle, toggleAll, clear,
count: selected.size,
selectedItems: items.filter((i) => selected.has(i.id)),
allChecked: selected.size === items.length && items.length > 0,
};
}
// 一括アクションバー(選択数に応じて表示)
export function BulkActionBar({ count, onClear, children }: { count: number; onClear: () => void; children: React.ReactNode }) {
if (count === 0) return null;
return (
<div className="sticky top-0 z-30 bg-indigo-500/10 border-b border-indigo-500/30 px-4 py-3 flex items-center gap-3">
<span className="text-sm text-indigo-200">{count}件 選択中</span>
<button onClick={onClear} className="text-xs text-zinc-400 hover:text-zinc-200">解除</button>
<div className="ml-auto flex gap-2">{children}</div>
</div>
);
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加