การใช้ Tailwind CSS ร่วมกับ Headless UI
ในบทความก่อนหน้านี้ เราได้เรียนรู้เกี่ยวกับการใช้งาน Tailwind CSS ร่วมกับ JavaScript frameworks ต่างๆ เช่น React, Vue, และ Angular ในบทความนี้ เราจะมาสำรวจการใช้งาน Tailwind CSS ร่วมกับ Headless UI ซึ่งเป็นชุดของ unstyled, fully accessible UI components ที่ออกแบบมาเพื่อใช้งานกับ React, Vue, และอื่นๆ
Headless UI ช่วยให้เราสามารถสร้าง components ที่มี behavior ที่ซับซ้อนได้ง่ายขึ้น โดยที่เราสามารถควบคุม styling ได้อย่างเต็มที่ด้วย Tailwind CSS นี่คือการผสมผสานที่ลงตัวสำหรับนักพัฒนาที่ต้องการทั้งความยืดหยุ่นและความสามารถในการปรับแต่ง
Headless UI คืออะไร?
Headless UI คือชุดของ UI components ที่ไม่มี styling ติดมาด้วย Components เหล่านี้ให้ความสำคัญกับ accessibility และ behavior ที่ถูกต้องตามหลักการของ UI patterns ต่างๆ เช่น dropdowns, modals, switches, และอื่นๆ
ข้อดีของการใช้ Headless UI คือ:
- Accessibility: Components สร้างขึ้นโดยคำนึงถึง accessibility เป็นหลัก ทำให้มั่นใจได้ว่า application ของคุณสามารถใช้งานได้โดยผู้ใช้งานทุกคน
- Unstyled: ไม่มี styling ติดมาด้วย ทำให้คุณสามารถใช้ Tailwind CSS หรือ styling solution อื่นๆ ที่คุณต้องการได้อย่างอิสระ
- Composability: Components ถูกออกแบบมาให้สามารถนำมาประกอบรวมกันได้อย่างง่ายดาย ทำให้คุณสามารถสร้าง UI ที่ซับซ้อนได้
การติดตั้ง Headless UI
การติดตั้ง Headless UI นั้นง่ายมาก คุณสามารถติดตั้งผ่าน npm หรือ yarn ได้
npm install @headlessui/react
# หรือ
yarn add @headlessui/react
สำหรับ Vue.js:
npm install @headlessui/vue
# หรือ
yarn add @headlessui/vue
ในบทความนี้ เราจะเน้นที่การใช้งานกับ React เป็นหลัก แต่หลักการพื้นฐานสามารถนำไปประยุกต์ใช้กับ Vue.js ได้เช่นกัน
การใช้งาน Components
หลังจากติดตั้ง Headless UI แล้ว เราสามารถเริ่มใช้งาน components ได้เลย ลองมาดูตัวอย่างการใช้งาน Menu component กัน
ตัวอย่าง: การสร้าง Dropdown Menu ด้วย React และ Headless UI
เริ่มต้นด้วยการ import components ที่จำเป็นจาก @headlessui/react
import { Menu } from '@headlessui/react'
function MyDropdown() {
return (
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
Options
<svg className="-mr-1 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clipRule="evenodd" />
</svg>
</Menu.Button>
</div>
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div className="py-1">
<Menu.Item>
{({ active }) => (
<a
href="#"
className={`block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 ${active ? 'bg-gray-100' : ''}`}
>
Edit
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
href="#"
className={`block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 ${active ? 'bg-gray-100' : ''}`}
>
Duplicate
</a>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
href="#"
className={`block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 ${active ? 'bg-gray-100' : ''}`}
>
Archive
</a>
)}
</Menu.Item>
<form method="POST" action="#">
<Menu.Item>
{({ active }) => (
<button
type="submit"
className={`block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 ${active ? 'bg-gray-100' : ''}`}
>
Delete
</button>
)}
</Menu.Item>
</form>
</div>
</Menu.Items>
</Menu>
)
}
export default MyDropdown;
คำอธิบาย:
<Menu as="div">: ห่อ component ทั้งหมดไว้ใน Menu component กำหนดให้เป็นdivเพื่อให้ Tailwind CSS สามารถทำงานได้อย่างถูกต้อง<Menu.Button>: ปุ่มที่เปิด dropdown menu เราใช้ Tailwind CSS classes เพื่อ styling ปุ่มนี้<Menu.Items>: รายการเมนูที่แสดงเมื่อ dropdown เปิดขึ้น เราใช้ Tailwind CSS classes เพื่อ styling รายการเหล่านี้<Menu.Item>: แต่ละรายการใน dropdown menu เราใช้ render prop pattern ({ active }) => ... เพื่อกำหนด styling เมื่อ item นั้นถูก hover (active)
ในตัวอย่างนี้ เราใช้ Tailwind CSS classes เพื่อ styling ปุ่มและรายการเมนู คุณสามารถปรับแต่ง styling ได้ตามต้องการ
การปรับแต่ง Styles
Headless UI ให้ความยืดหยุ่นในการปรับแต่ง styles อย่างมาก คุณสามารถใช้ Tailwind CSS classes เพื่อ styling components ได้ตามต้องการ นอกจากนี้ คุณยังสามารถใช้ CSS-in-JS libraries หรือ CSS modules ได้อีกด้วย
ตัวอย่าง: การเปลี่ยนสีพื้นหลังของ Menu Items เมื่อ Hover
ในตัวอย่างข้างต้น เราใช้ hover:bg-gray-100 เพื่อเปลี่ยนสีพื้นหลังของ menu items เมื่อ hover คุณสามารถเปลี่ยนสีนี้เป็นสีที่คุณต้องการได้ เช่น hover:bg-blue-500 หรือ hover:bg-primary (ถ้าคุณกำหนดสี primary ไว้ใน Tailwind config)
<Menu.Item>
{({ active }) => (
<a
href="#"
className={`block px-4 py-2 text-sm text-gray-700 hover:bg-blue-500 ${active ? 'bg-blue-500' : ''}`}
>
Edit
</a>
)}
</Menu.Item>
การใช้ Variants กับ Headless UI
Tailwind CSS variants สามารถใช้ร่วมกับ Headless UI ได้อย่างมีประสิทธิภาพ ตัวอย่างเช่น คุณสามารถใช้ disabled: variant เพื่อ styling components เมื่อถูก disable
import { Switch } from '@headlessui/react'
function MySwitch() {
const [enabled, setEnabled] = React.useState(false)
return (
<Switch
checked={enabled}
onChange={setEnabled}
className={`${
enabled ? 'bg-blue-600' : 'bg-gray-200'
} relative inline-flex h-6 w-11 items-center rounded-full`}
>
<span className="sr-only">Enable notifications</span>
<span
className={`${
enabled ? 'translate-x-6' : 'translate-x-1'
} inline-block h-4 w-4 transform rounded-full bg-white transition`}
/>
</Switch>
)
}
export default MySwitch;
คำอธิบาย:
- เราใช้ conditional styling เพื่อเปลี่ยนสีพื้นหลังของ switch ขึ้นอยู่กับว่า enabled หรือไม่
- เราใช้
transitionclass เพื่อสร้าง animation เมื่อ switch เปลี่ยนสถานะ
ข้อควรระวัง
เมื่อใช้ Tailwind CSS ร่วมกับ Headless UI มีข้อควรระวังบางประการที่ควรทราบ:
- Ensure correct HTML structure: Headless UI components มักจะ require โครงสร้าง HTML ที่ถูกต้องเพื่อให้ทำงานได้อย่างถูกต้อง โปรดอ่าน documentation ของแต่ละ component อย่างละเอียด
- Accessibility: Headless UI ช่วยให้คุณสร้าง accessible components ได้ง่ายขึ้น แต่คุณยังคงต้องตรวจสอบให้แน่ใจว่า application ของคุณเป็นไปตาม WCAG guidelines
สรุป
การใช้ Tailwind CSS ร่วมกับ Headless UI เป็นวิธีที่มีประสิทธิภาพในการสร้าง UI ที่ยืดหยุ่น, accessible, และปรับแต่งได้ง่าย Headless UI ให้ components ที่มี behavior ที่ถูกต้อง ในขณะที่ Tailwind CSS ให้ styling ที่รวดเร็วและสะดวกสบาย
ในบทความถัดไป เราจะมาสำรวจการใช้งาน Tailwind CSS ร่วมกับ Next.js ซึ่งเป็น React framework ที่ได้รับความนิยมอย่างมาก