headlessui
nuxt-headlessui

Nuxt向けのHeadless UI統合。完全にスタイルなしで、完全にアクセス可能なUIコンポーネントで、Tailwind CSSと美しく統合できるように設計されています。

Nuxt Headless UI CircleCI

npm versionnpm downloadsLicenseNuxt

Headless UIのNuxt向け統合。完全にスタイルなしで、完全にアクセス可能なUIコンポーネントで、Tailwind CSSと美しく統合できるように設計されています。

Vue向けHeadless UIのドキュメント: https://headlessui.dokyumento.jp/vue/menu

機能

  • 自動動的インポート(グローバルコンポーネントなし)
  • 完全に型安全
  • 設定可能なコンポーネントプレフィックス(デフォルトはHeadless

クイックセットアップ

  1. プロジェクトにnuxt-headlessuiの依存関係を追加します
npx nuxi@latest module add headlessui
  1. nuxt-headlessuinuxt.config.tsmodulesセクションに追加します
{
    modules: [
        'nuxt-headlessui'
    ],

    // Optionally change the default prefix.
    headlessui: {
        prefix: 'Headless'
    }
}
  1. app.vueファイル内の<script setup>に以下の行を追加します

!注
これは[email protected]または@headlessui/[email protected]以前のバージョンを使用している場合にのみ必要です。より新しいバージョンでは、Vueが提供するネイティブのuseIdコンポーザブルを使用します。

// Use SSR-safe IDs for Headless UI
provideHeadlessUseId(() => useId())

これはIDの不一致によるハイドレーションの問題を回避するために必要です。どちらのコンポーザブルもNuxtによって自動インポートされます。provideHeadlessUseIdコンポーザブルは@headlessui/vueからのprovideUseIdコンポーザブルのエイリアスです。import { provideUseId } from '@headlessui/vue'を直接使用してもそのままでは動作しません

以上です!これでNuxtアプリでHeadless UIを使用できます✨

使用方法

セットアップが完了したら、コンポーネントやページでヘッドレスコンポーネントを使用し、お気に入りのCSSフレームワークでスタイルを設定するだけです。コンポーネントをインポートする必要はありません。以下は、heroiconsとTailwind CSSを使用したListbox(Select)の例です

<template>
  <div class="container mx-auto">
    <div class="w-72">
      <HeadlessListbox v-model="selectedPerson">
        <div class="relative mt-1">
          <HeadlessListboxButton
            class="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm"
          >
            <span class="block truncate">{{ selectedPerson.name }}</span>
            <span
              class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
            >
              <ChevronUpDownIcon
                class="h-5 w-5 text-gray-400"
                aria-hidden="true"
              />
            </span>
          </HeadlessListboxButton>

          <transition
            leave-active-class="transition duration-100 ease-in"
            leave-from-class="opacity-100"
            leave-to-class="opacity-0"
          >
            <HeadlessListboxOptions
              class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
            >
              <HeadlessListboxOption
                v-for="person in people"
                v-slot="{ active, selected }"
                :key="person.name"
                :value="person"
                as="template"
              >
                <li
                  :class="[
                    active ? 'bg-amber-100 text-amber-900' : 'text-gray-900',
                    'relative cursor-default select-none py-2 pl-10 pr-4',
                  ]"
                >
                  <span
                    :class="[
                      selected ? 'font-medium' : 'font-normal',
                      'block truncate',
                    ]"
                  >{{ person.name }}</span>
                  <span
                    v-if="selected"
                    class="absolute inset-y-0 left-0 flex items-center pl-3 text-amber-600"
                  >
                    <CheckIcon class="h-5 w-5" aria-hidden="true" />
                  </span>
                </li>
              </HeadlessListboxOption>
            </HeadlessListboxOptions>
          </transition>
        </div>
      </HeadlessListbox>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/vue/20/solid'

const people = [
  { name: 'Wade Cooper' },
  { name: 'Arlene Mccoy' },
  { name: 'Devon Webb' },
  { name: 'Tom Cook' },
  { name: 'Tanya Fox' },
  { name: 'Hellen Schmidt' }
]
const selectedPerson = ref(people[0])
</script>

Tailwind CSSを使用している場合、@headlessui/tailwindcssプラグインを使用して、ui-open:*ui-active:*のようなモディファイアを取得できます。UnoCSSを使用している場合は、unocss primitives presethttps://github.com/zirbest/unocss-preset-primitives/tree/main)がこれを行います。

開発

# Install dependencies
pnpm install

# Generate type stubs
pnpm run dev:prepare

# Develop with the playground
pnpm run dev

# Build the playground
pnpm run dev:build

# Run ESLint
pnpm run lint