📚

Nuxt.jsでWebアプリケーション開発メモ31

に公開

概要

topページ見た目改善、統計・グラフのカスタムボタンのポップアップメニュー実装。(ポップアップメニューだけで、メニュー内のアイテムクリックによる実処理は未実装)

プロンプト31

31-1

# 命令31
# 命令31-1
- Topページ内の要素を全体的に縮小して。ブラウザで75%表示相当で。
- ヘッダの領域を今の3分の2くらいに狭くして。

31-2

# 命令31-2
- 統計・グラフの`カスタム`ボタンの機能を実装したいのですが、どのようなUIが良いか検討・提示してください。

Claude Codeからの回答

回答
統計・グラフの「カスタム」ボタンのUIを検討しました。以下の案を提示します:

  推奨案:インライン展開型

  メリット:
  - 操作がシンプルで直感的
  - 他のボタンと同じエリアに統合
  - モーダルを開く必要がない

  実装イメージ:
  [今週] [今月] [今年] [過去7日] [過去30日] [カスタム▼]
  ↓ カスタムクリック時
  [今週] [今月] [今年] [過去7日] [過去30日] [カスタム▲]
  [開始日: 2025-01-01] [終了日: 2025-03-31] [適用]

  代替案:ドロップダウンメニュー型

  メリット:
  - スペースを取らない
  - よく使う期間のプリセットも併用可能

  実装イメージ:
  [カスタム▼] クリック時
  ┌─────────────────┐
  │ □ 過去1年         │
  │ □ 過去6ヶ月       │
  │ ─────────────── │
  │ カスタム期間指定    │
  │ 開始: [____]      │
  │ 終了: [____]      │
  │ [適用]           │
  └─────────────────┘

  どちらがお好みでしょうか?

  個人的にはインライン展開型が使いやすく、既存UIとの親和性も高いと思います。いかがでしょうか?

31-3

回答への再質問
- nuxtjs,nuxtuiの勉強という観点でいうとどちらが学びが多いと思う?
Claude Codeからの再回答
● ドロップダウンメニュー型の方が学びが多いと思います。

  ドロップダウンメニュー型で学べること

  Nuxt UI コンポーネント:
  - UDropdownMenu の詳細な使い方(プリセット + カスタム期間の組み合わせ)
  - UInput の日付入力バリデーション
  - UButton のメニュー内配置

  Vue.js パターン:
  - v-model での複雑なフォーム管理
  - computed でのプリセット・カスタム期間の状態切り替え
  - watch での日付変更時のバリデーション
  - カスタムコンポジション関数の作成

  状態管理:
  const customPeriod = reactive({
    type: 'preset', // 'preset' | 'custom'
    preset: 'past_6_months',
    startDate: '',
    endDate: ''
  })

  インライン展開型で学べること

  - 基本的な v-show の条件表示
  - シンプルな日付入力

  学習観点では圧倒的にドロップダウンメニュー型が、Nuxt UI の高度な使い方や Vue.js のリアクティブシステムを深く理解できる良い題材だと思います。

31-4

# 命令31-4
- 統計・グラフの`カスタム`ボタンの機能をポップアップメニュー型で実装してください。
    - `カスタム`ボタンをクリックするとポップアップメニューが表示され、上から、`過去3ヶ月`、`過去6ヶ月`、`過去1年`は固定表示、一番下に任意の`過去N期間`がラジオボタンでトグル選択できるようにしてください。
    - `過去N期間`は`過去`のとなりに正数が入力できる数値入力Input要素、となりに期間を選択できるドロップダウン要素を表示し、選択できる期間は上から`週`、`月`、`年`にしてください。
        - `過去N期間`のデフォルトは`過去1ヶ月`にしてください。
        - 入力した内容はlocalstorage等に保存し、次回画面表示した際に復元されるようにしてください。
    - ポップアップメニュー内のいずれかの期間を選択すると、日付のfrom~toがポップアップのフッター部分(セパレータで区切られて表示されるように。)に`yyyy/MM/dd~yyyy/MM/dd`のように表示されるようにしてください。
        - この日付部分は読み取り専用でユーザー入力には使用しません。あくまで期間を選択した際の日付範囲を表すだけに使用します。
    - まずは`カスタム`ボタンのポップアップダウンメニューだけを実装してください。期間の選択によって実際のグラフ表示が変化する処理は後でよいです。

対応内容

  • top画面のダッシュボード全体を75%相当のスケールに縮小。
    • cssのtransform: scale(0.75);やら、classのscale-75やらで縮小。
    • → cssが一部効かないので、scale-75などを使ったがはっきり言って失敗な感じ。
      • ドロップダウンのポップアップメニューだけはでかいままなので、適宜scale-75を設定する必要がありメンドイ。
    • そのうちスケールじゃなく別の方法で全体をコンパクトにしたい。
  • カスタムボタンにポップアップメニューを実装。

画面

  • カスタム期間の期間選定ドロップダウンのメニューの大きさがおかしい。

ソース差分

https://github.com/tkure/prototype-frontend/commit/d646ba94e5b2ca0072e038e44a23e50ff031dc01

UDropdownMenuのカスタムコンテンツの書き方

  • ★ポイント:自作のスロット名#custom-contentを指定する。
pages/top.vue
                <!-- ★:items="customPeriodMenuItems"でカスタムコンテンツにするスロット名を指定する -->
                <UDropdownMenu 
                  :items="customPeriodMenuItems"
                  :popper="{ placement: 'bottom-end' }"
                  v-model:open="showCustomPeriodMenu"
                  size="xs"
                  :ui = "{
                    content: 'scale-75'
                  }"
                >
                  <UButton 
                    size="xs" 
                    :variant="selectedPeriod === 'custom' ? 'solid' : 'outline'"
                    :label="customButtonLabel" 
                    icon="i-heroicons-chevron-down"
                  />

                  <!-- ★ #custom-content はcustomPeriodMenuItems内で指定されている -->   
                  <template #custom-content>
                    <div class="p-2 w-64 ">
                      <!-- プリセット期間 -->
                      <div class="space-y-1 mb-2">
                        <label class="flex items-center">
                          <input 
                            type="radio" 
                            name="customPeriod" 
                            value="past_3_months"
                            v-model="customPeriodSettings.selectedType"
                            @change="saveCustomPeriodSettings"
                            @click.stop
                            class="mr-1.5"
                          />
                          過去3ヶ月
                        </label>
<!-- ...中略 -->
pages/top.vue
<script setup lang="ts">
// カスタム期間メニューのアイテム(カスタムスロットを使用するため、1つのアイテムが必要)
const customPeriodMenuItems = computed(() => [
  {
    label: 'カスタム期間設定',
    slot: 'custom-content', // ★ここでスロット名を指定★
    onSelect: (e: Event) => {
      e.preventDefault() // メニューが閉じるのを防ぐ
    }
  }
])


[Nuxt.jsでWebアプリケーション開発メモ32]

Discussion