UIを作成する時フレームワークを使ったことはありますか?
私はCSSフレームワークのtailwindを多用していて、そのtailwindからUIコンポーネントが出ていたので使ってみました。
HeadlessUIとは
Headless Componentと言われ、tailwindから出ているUIの制御や動作だけを行ってくれるものです。なのでデザイン等は自身でしていく必要があるので、CSSやtailwind等のフレームワーク自由に組みわせてUIを作っていきます。
使用感
ReactとVueでの使い方が公式に乗っているのでVueの方を参考にしつつ、私なりの独断と偏見で使用感を書きたいと思います。
インストールの手順については省略しております。
皆様のほうでお調べください
コンポーネントについて
Vueの方では10個のコンポーネントが用意されていて、特に便利だと感じた3つを紹介したいと思います。
Tabs
tabs.vue
<script setup>
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from "@headlessui/vue";
import Chat from "@/components/Chat.vue";
import Todo from "@/components/Todo.vue";
import Blog from "@/components/Blog.vue";
import User from "@/components/User.vue";
import Janken from "@/components/Janken.vue";
import Test from "@/components/Test.vue";
const menus = [
{ icon: "/src/assets/chat.svg", component: Chat, title: "Chat" },
{ icon: "/src/assets/todo.svg", component: Todo, title: "Todo" },
{ icon: "/src/assets/book.svg", component: Blog, title: "Blog" },
{ icon: "/src/assets/user.svg", component: User, title: "User" },
{ icon: "/src/assets/janken.svg", component: Janken, title: "Janken" },
{ icon: "/src/assets/test.svg", component: Test, title: "Test" },
]
</script>
<template>
<TabGroup>
<TabList class="w-full sticky flex gap-5 top-10">
<Tab v-for="menu in menus">
<img :src="menu.icon" alt="" width="25" height="25">
</Tab>
</TabList>
<TabPanels class="w-full h-full">
<TabPanel v-for="menu in menus" class="w-full h-full">
<p class="text-3xl text-center">{{ menu.title }}</p>
<component :is="menu.component" />
</TabPanel>
</TabPanels>
</TabGroup>
</template>
タブを縦にしたり、選択されているタブのスタイルを変更することもできます。
Switch(Toggle)
公式からの引用です
switch.vue
<template>
<Switch
v-model="enabled"
:class="enabled ? 'bg-blue-600' : 'bg-gray-200'"
class="relative inline-flex h-6 w-11 items-center rounded-full"
>
<span class="sr-only">Enable notifications</span>
<span
:class="enabled ? 'translate-x-6' : 'translate-x-1'"
class="inline-block h-4 w-4 transform rounded-full bg-white transition"
/>
</Switch>
</template>
<script setup>
import { ref } from 'vue'
import { Switch } from '@headlessui/vue'
const enabled = ref(false)
</script>
こういうのがサクッと作れるのは良いですね
Dialog(Modal)
dialog.vue
<TransitionRoot appear :show="isOpen" as="template">
<Dialog as="div" @close="closeModal" class="relative z-10">
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0"
enter-to="opacity-100"
leave="duration-200 ease-in"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div class="fixed inset-0 bg-black/25" />
</TransitionChild>
<div class="fixed inset-0 overflow-y-auto">
<div
class="flex min-h-full items-center justify-center p-4 text-center"
>
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100"
leave="duration-200 ease-in"
leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"
>
<DialogPanel
class="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all"
>
<DialogTitle
as="h3"
class="text-lg font-medium leading-6 text-gray-900"
>
投稿
</DialogTitle>
<div class="mt-2">
<input type="text" v-model="title" class="w-full h-8" placeholder="タイトル">
</div>
<div class="mt-2">
<textarea placeholder="本文" v-model="body" class="w-full h-32 resize-none"></textarea>
</div>
<div class="mt-4 flex gap-20 justify-center">
<button
type="button"
class="inline-flex justify-center rounded-md border border-transparent bg-red-100 px-4 py-2 text-sm font-medium text-red-900 hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2"
@click="closeModal"
>
キャンセル
</button>
<button
type="button"
class="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
@click="post"
>
投稿
</button>
</div>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
背景の色やダイヤログを開いた時、閉じた時にイベントを発生させることも可能です。
まとめ
HeadlessUIを使うことでUIの制御や動作を任せる事ができるので、デザインの方に時間を割くことができ、よりクリエイティブなデザインにすることができると感じました。