SCALE — Build Lab
開発パターン · REACT PATTERN

エンプティステート

CATEGORY開発パターン TYPEReact Pattern EFFORT30〜60分 DIFFICULTY
PRIMARY CODE
tsx
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 }}
// />
前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 新規ユーザー
  • 検索結果0件

エンプティステート

: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: 注意事項

  • 依存パッケージを忘れず追加