ウェブエンジニア問題集

コンポーネントパターン — よく使うUIの作り方

この章では実務でよく使うUIパターンをTailwindで実装する方法をまとめます。コピペで使えるボタン・カード・フォームなどの実装例を集めました。

学習者学習者

同じボタンを何度も書いていると、クラスの羅列をコピペするのが大変…。これって毎回書くものなの?

先生先生

よく使うUIはReactコンポーネントに切り出して、クラスを中に閉じ込めるのが基本だよ。まずこの章で「型」を覚えて、次の章でコンポーネント化を学ぼう。

Tailwindでコンポーネントを組んでいるイメージ

ボタン

<!-- プライマリボタン -->
<button class="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-semibold rounded-lg transition-colors focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:outline-none disabled:opacity-50 disabled:cursor-not-allowed">
  送信
</button>
 
<!-- アウトラインボタン -->
<button class="inline-flex items-center gap-2 px-4 py-2 border border-blue-600 text-blue-600 hover:bg-blue-50 text-sm font-semibold rounded-lg transition-colors">
  キャンセル
</button>
 
<!-- ゴーストボタン(背景なし) -->
<button class="inline-flex items-center gap-2 px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 text-sm font-medium rounded-lg transition-colors">
  詳細
</button>

バッジ

<!-- ステータスバッジ -->
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
  完了
</span>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
  処理中
</span>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
  エラー
</span>

カード

<div class="bg-white rounded-2xl border border-gray-200 shadow-sm overflow-hidden hover:shadow-md transition-shadow">
  <img src="..." alt="..." class="w-full h-48 object-cover" />
  <div class="p-5">
    <span class="text-xs font-medium text-blue-600 uppercase tracking-wide">カテゴリ</span>
    <h3 class="mt-1 text-lg font-semibold text-gray-900 line-clamp-2">
      カードタイトル
    </h3>
    <p class="mt-2 text-sm text-gray-500 line-clamp-3">
      説明テキストが入ります。長い場合は3行で省略されます。
    </p>
    <div class="mt-4 flex items-center justify-between">
      <span class="text-xs text-gray-400">2024/01/01</span>
      <button class="text-sm text-blue-600 hover:underline">続きを読む</button>
    </div>
  </div>
</div>

フォーム

<form class="space-y-5">
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1.5">
      メールアドレス
      <span class="text-red-500 ml-0.5">*</span>
    </label>
    <input
      type="email"
      class="block w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm
             focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
             placeholder:text-gray-400"
      placeholder="example@email.com"
    />
  </div>
 
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1.5">メッセージ</label>
    <textarea
      rows="4"
      class="block w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm
             focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
             resize-none"
    ></textarea>
  </div>
 
  <button type="submit" class="w-full py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg transition-colors">
    送信する
  </button>
</form>

アラート

<!-- 情報 -->
<div class="flex gap-3 p-4 bg-blue-50 border border-blue-200 rounded-lg text-blue-800">
  <svg class="w-5 h-5 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
    <!-- info icon -->
  </svg>
  <p class="text-sm">情報メッセージです。</p>
</div>
 
<!-- エラー -->
<div class="flex gap-3 p-4 bg-red-50 border border-red-200 rounded-lg text-red-800">
  <p class="text-sm">エラーが発生しました。</p>
</div>

ちゃんと使うためのポイント

  • Reactコンポーネントにまとめてクラスを閉じ込めるとHTMLの長さ問題が解消される
  • 繰り返し使うパターンはコンポーネント化して cn() (clsx) でクラスを管理する
  • バリアントはpropsで切り替えると再利用性が高まる

次の章では、テーマカスタマイズの方法を学びます。