📖

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

に公開

概要

ポップアップメニュー項目のサイズ感を統一する。

プロンプト35

- ポップアップメニューのuiをアプリ内で統一したいです。
  `frontend\prototype_frontend\app\pages\custom_training\index.vue`の358行目の設定がアプリ内のすべてのポップアップメニューに適用されるように修正して。

追加命令

  • UDropdownMenucomponents配下に共通コンポーネントとして作成して。
  • app.config.tsでグローバル設定化できない設定を共通化して、その他の設定は使う側から動的に指定できるようにできますか?今のUDropdownMenuのすべての実装を確認して共通化できるかチェックした上で可能であれば共通コンポーネントに修正してください。コンポーネント名はお任せします。

対応内容

  • 一部、:ui={...}で設定していたポップアップメニューの幅、フォントサイズ、アイコンサイズをグローバル設定(app.config.ts)に移動してポップアップメニューの見た目を統一させる。
    • → 幅(content)設定は効くがその他(item,itemLeadingIcon)はグローバル設定に入れても効かない。(´・ω・`)
    • claude codeにNuxtUIのソースを解析してもらったがグローバル設定は効くはずの構成になっているといわれたが、効かないのでとりあえずNuxtUIのバグと結論づける。
    • 公式ページも確かにcontentしか例が書いてない。
app.config.ts
export default defineAppConfig({
  ui: {
    /* ... 中略 */    
    dropdownMenu: {
      slots: {
        content: '!min-w-0 w-auto',
        /* 以下2つは効いてないが後学のため残す */
        item: 'text-[9px]',
        itemLeadingIcon: 'w-[10px] h-[10px]'
      }
    }
  }
})

  • UDropdownMenucomponentscomposables化して共通利用できるようにした。

    • composables内に件のitem,itemLeadingIcon設定を定義し、アプリ内で共通利用するようにした。
  • 以下のように、defaultUi,mergeUiとして共通設定を提供。

composables/useDropdownMenuConfig.ts
/**
 * ドロップダウンメニューの共通設定を返すcomposable
 */
export const useDropdownMenuConfig = () => {
  // 共通のUI設定
  const defaultUi = {
    item: 'text-[9px]',
    itemLeadingIcon: 'w-[11px] h-[11px]'
  }
  /**
   * UI設定をマージする関数
   */
  const mergeUi = (customUi: Record<string, any> = {}) => ({
    ...defaultUi,
    ...customUi
  })
  /* ...中略 */
  return {
    defaultUi,
    mergeUi,
    // 以下略
  }
}
  • mergeUiの利用側
components/AppDropdownMenu.vue
<template>
  <UDropdownMenu
    :items="items"
    :popper="popper"
    :size="size"
    :open="open"
    :ui="mergedUi"
    v-bind="$attrs"
    @update:open="$emit('update:open', $event)"
  >
    <slot />
  </UDropdownMenu>
</template>

<script setup lang="ts">
import type { DropdownMenuProps } from '@nuxt/ui'

interface Props {
  items: any[]
  popper?: Record<string, any>
  size?: DropdownMenuProps['size']
  open?: boolean
  ui?: Record<string, any>
}

const props = withDefaults(defineProps<Props>(), {
  popper: () => ({ placement: 'bottom-end' }),
  size: undefined,
  open: undefined,
  ui: () => ({})
})

const emits = defineEmits<{
  'update:open': [value: boolean]
}>()

// ★ useDropdownMenuConfigから共通UI設定を取得 ★
const { mergeUi } = useDropdownMenuConfig()

// ★ デフォルトUI設定と渡されたUI設定をマージ ★
const mergedUi = computed(() => mergeUi(props.ui))
</script>

画面

  • ポップアップメニューの幅、項目名、アイコンを小さくした。

ソース差分

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


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

Discussion