Skip to content

UI Design: 投票券購入フロー

機能は requirements.md、技術は design.md 参照。デザイントークンは home/ui-design.md 参照。


モーダル1: PurchaseCreditsModal

レイアウト

┌─────────────────────────────────────────────┐
│                                        [✕]  │
│         🛒 投票券を購入                      │
│      {候補者名}への投票券を選択              │
├─────────────────────────────────────────────┤
│ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐    │
│ │ 10票  │ │ 35票  │ │ 60票  │ │ 150票 │    │
│ │¥1,000 │ │¥3,000 │ │¥5,000 │ │¥10,000│    │
│ │       │ │ 人気  │ │       │ │       │    │
│ │[購入] │ │[購入] │ │[購入] │ │[購入] │    │
│ └───────┘ └───────┘ └───────┘ └───────┘    │
└─────────────────────────────────────────────┘

コンテナ

  • Overlay: fixed inset-0 bg-black/50 backdrop-blur-sm
  • Body: bg-white rounded-3xl p-8 max-w-2xl w-full shadow-2xl
  • z-index: 90 (login modal より下、stripe modal より下)

ヘッダー

  • ShoppingCart アイコン (gold) + 「投票券を購入」
  • 候補者名: display フォント、gold-dark
  • サブテキスト: 「{候補者名}への投票券を選択してください」

<CreditPackageCard>

  • グリッド grid-cols-2 md:grid-cols-4 gap-4
  • 個別カード:
    • rounded-2xl p-6 border-2
    • 通常時: 白背景、border-gold/30
    • hover: border-gold + shadow-lg
    • 「人気」バッジ付き (popular: true): 上部に gold→rose-gold グラデバッジ
  • 内容(縦並び):
    • 票数(display 2.5rem、gold-dark
    • 「票」ラベル(小、opacity 0.6)
    • 価格(1.25rem、weight 600)
    • 「購入する」ボタン(gold背景、白文字、rounded-fullmt-4

モーダル2: StripePaymentModal

レイアウト

┌────────────────────────────────────────────┐
│ [← 戻る]                              [✕]  │
│                                            │
│      🔒 セキュア決済 (Stripe)               │
│                                            │
│  購入内容: 35票パッケージ                    │
│  金額:    ¥3,000                          │
├────────────────────────────────────────────┤
│ カード番号                                   │
│ [0000 0000 0000 0000]                     │
│                                            │
│ 有効期限         CVC                        │
│ [MM/YY]         [XXX]                     │
│                                            │
│ カード名義                                   │
│ [TARO YAMADA]                              │
│                                            │
│ ┌────────────────────────────────────────┐ │
│ │ ¥3,000を支払う                         │ │
│ └────────────────────────────────────────┘ │
│                                            │
│ 🔒 Stripeによるセキュア決済                  │
└────────────────────────────────────────────┘

コンテナ

  • Body: bg-white rounded-3xl p-8 max-w-md w-full shadow-2xl
  • z-index: 110 (login modal より上)

ヘッダー

  • 戻るボタン: 左上、ArrowLeft + 「戻る」
  • 鍵アイコン (Lock) + 「セキュア決済」
  • 購入内容ボックス:
    • 背景: rgba(212, 175, 55, 0.05)
    • 枠: 1px solid rgba(212, 175, 55, 0.2)
    • rounded-xl p-4
    • 「購入内容」「金額」を縦並びで表示

フォームフィールド

フィールドプレースホルダ最大幅
カード番号0000 0000 0000 0000full
有効期限MM/YYhalf
CVC123half
カード名義TARO YAMADAfull

各フィールド:

  • ラベル: 0.85rem、weight 500、charcoal opacity 0.7
  • input: rounded-xl border-2 border-gold/20 px-4 py-3
  • focus: border-gold + outline-none
  • 入力中の整形: useStripePayment が制御

「支払う」ボタン

状態スタイル
通常gold背景、白文字、rounded-full py-4、weight 600
disabled (!isValid)opacity 0.4、cursor not-allowed
processingスピナー + 「処理中...」

状態別の表示

step: 'processing'

  • フォーム全体を半透明の overlay で覆う
  • 中央に Loader2 (回転)
  • 下に「決済処理中...」テキスト

step: 'success'

  • フォームを Check アイコン + 「決済完了」表示に置き換え
  • 1.5秒後に自動でモーダルを閉じる
  • Confetti 用に親に通知

step: 'error'

  • フォーム下に赤背景のエラーボックス
  • 「もう一度試す」ボタンで step: 'payment' に戻す

フッター

  • 鍵アイコン + 「Stripeによるセキュア決済」
  • 0.75rem、opacity 0.6、中央揃え

アニメーション

要素プロパティtiming
Modal 開閉scale (0.9→1), opacityspring damping: 20
パッケージカード hovertranslateY(-4) + shadow200ms
「人気」バッジ軽い脈動 (scale 1→1.05→1)2s loop
Loading スピナー360deg 回転1s linear infinite
Success Checkscale (0→1)spring

レスポンシブ

モバイル

  • パッケージカード: 2列グリッド
  • StripePaymentModal: 横幅 max-w-sm
  • フォームフィールドは全て full 幅

タブレット以上

  • パッケージカード: 4列グリッド
  • StripePaymentModal: max-w-md

アクセシビリティ

  • フォームには <label> を関連付け(htmlFor
  • カード番号入力に inputmode="numeric"autocomplete="cc-number"
  • 有効期限に autocomplete="cc-exp"
  • CVC に autocomplete="cc-csc"
  • エラー時に aria-invalid="true" + aria-describedby="error-message"
  • 処理中はフォーム全体を aria-busy="true"

関連

  • requirements.md / design.md
  • ../home/ui-design.md — デザイントークン
  • ../social-login/ui-design.md — モーダル共通スタイル