nuxt-headlessui

nuxt-headlessui
Nuxt用のHeadless UI連携機能。完全にスタイルが適用されておらず、完全にアクセス可能なUIコンポーネントで、Tailwind CSSと美しく統合できるように設計されています。
Nuxt Headless UI 
Headless UI と Nuxt の連携機能。完全にスタイルが適用されておらず、完全にアクセス可能なUIコンポーネントで、Tailwind CSSと美しく統合できるように設計されています。
Vue用Headless UIドキュメント:https://headlessui.dokyumento.jp/vue/menu
機能
- 自動動的インポート(グローバルコンポーネントなし)
- 完全にタイプセーフ
- 設定可能なコンポーネントプレフィックス(デフォルトは
Headless
)
クイックセットアップ
nuxt-headlessui
依存関係をプロジェクトに追加します。
# Using pnpm
pnpm add -D nuxt-headlessui
# Using yarn
yarn add --dev nuxt-headlessui
# Using npm
npm install --save-dev nuxt-headlessui
nuxt-headlessui
をnuxt.config.ts
のmodules
セクションに追加します。
{
modules: [
'nuxt-headlessui'
],
// Optionally change the default prefix.
headlessui: {
prefix: 'Headless'
}
}
app.vue
ファイルの<script setup>
内に以下の行を追加します。
// Use SSR-safe IDs for Headless UI
provideHeadlessUseId(() => useId())
これは、IDの不一致によるハイドレーションの問題を回避するために必要です。両方のcomposableはnuxtによって自動的にインポートされます。provideHeadlessUseId
composableは、@headlessui/vue
のprovideUseId
composableのエイリアスです。import { provideUseId } from '@headlessui/vue'
を直接使用しても、すぐに機能しません。
以上です!これでNuxtアプリでHeadless UIを使用できます✨
使用方法
セットアップ完了後、コンポーネントやページでHeadlessコンポーネントを使用し、お好みの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:*
のような修飾子を取得できます。
開発
# 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