エンプティステート
:LiTarget: 用途
データが空のときの「最初のアクションへ誘導」パターン。
:LiSparkle: 特徴
- イラスト/アイコン
- 行動誘導CTA
- カスタムメッセージ
:LiCode: コード(コピペ用)
import { ReactNode } from 'react';
export function EmptyState({
icon, title, description, cta,
}: {
icon: ReactNode; // <Icon /> 等
title: string;
description?: string;
cta?: { label: string; onClick?: () => void; href?: string };
}) {
const ctaEl = cta && (cta.href ? (
<a href={cta.href} className="inline-flex items-center gap-2 px-4 py-2 rounded-xl bg-indigo-500 text-white text-sm font-semibold hover:bg-indigo-400 transition-colors">
{cta.label}
</a>
) : (
<button onClick={cta.onClick} className="inline-flex items-center gap-2 px-4 py-2 rounded-xl bg-indigo-500 text-white text-sm font-semibold hover:bg-indigo-400 transition-colors">
{cta.label}
</button>
));
return (
<div className="text-center py-12 px-4">
<div className="w-16 h-16 mx-auto mb-4 rounded-2xl bg-zinc-800/50 flex items-center justify-center text-zinc-500">
{icon}
</div>
<h3 className="text-base font-semibold text-zinc-200 mb-2">{title}</h3>
{description && <p className="text-sm text-zinc-500 mb-5 max-w-md mx-auto">{description}</p>}
{ctaEl}
</div>
);
}
// 使い方:
// <EmptyState
// icon={<Icon name="lucide:inbox" />}
// title="まだタスクがありません"
// description="最初のタスクを追加して始めましょう"
// cta={{ label: '+ 新規タスク', onClick: openNewTaskModal }}
// />
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加