แสดงบทความที่มีป้ายกำกับ Frontend Development แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Frontend Development แสดงบทความทั้งหมด

วันเสาร์ที่ 29 มีนาคม พ.ศ. 2568

🚀 การใช้ Headless UI กับ Next.js: ยืดหยุ่นกว่า สวยกว่า ใช้งานง่าย!

อยากได้ UI สวยๆ แต่ไม่อยากติดดีไซน์เดิมๆ ใช่ไหม? 🤔
Headless UI คือทางออก! มันเป็นชุดคอมโพเนนต์ที่ ไม่มีสไตล์ตายตัว ให้คุณออกแบบเองได้เต็มที่

ในบทความนี้ เราจะมาดูว่า Headless UI คืออะไร ทำไมถึงเหมาะกับ Next.js และมีวิธีใช้งานยังไงบ้าง พร้อมตัวอย่างโค้ดที่ใช้ได้จริง! 🎯

🎭 Headless UI คืออะไร?

Headless UI เป็นชุดของ UI Components ที่พัฒนาโดยทีม Tailwind CSS ซึ่งเน้นให้ ความยืดหยุ่น และ ปรับแต่งสไตล์เองได้

🔹 ข้อแตกต่างจาก UI Library ทั่วไป

Headless UI UI Library ทั่วไป (เช่น MUI, Ant Design)
ดีไซน์ ไม่มีดีไซน์บังคับ ปรับแต่งเอง มีดีไซน์ตายตัว ต้องใช้ตามที่ Library กำหนด
ความยืดหยุ่น ใช้กับ Tailwind, CSS, Styled Components ได้หมด ต้องใช้ตามโครงสร้างที่ Library กำหนด
ประสิทธิภาพ เบา เร็ว ไม่โหลดสไตล์เกินจำเป็น อาจมี CSS หรือ JS ส่วนเกินที่ไม่ได้ใช้
การรองรับ Accessibility มีการจัดการโฟกัสและคีย์บอร์ดให้ บางตัวรองรับ แต่บางตัวอาจต้องทำเพิ่มเอง
เหมาะกับ คนที่ต้องการ Custom UI เอง คนที่ต้องการ UI พร้อมใช้

🛠 วิธีติดตั้ง Headless UI ใน Next.js

ติดตั้งผ่าน npm หรือ yarn ง่ายๆ

npm install @headlessui/react

หรือ

yarn add @headlessui/react


🎯 ตัวอย่างการใช้งาน Headless UI

🔥 1️⃣ ทำ Modal ที่ใช้จริงได้เลย

Modal หรือ Dialog เป็นสิ่งที่ใช้บ่อยในเว็บ เช่น แจ้งเตือน, ฟอร์มสมัครสมาชิก


🔹 ตัวอย่าง Modal แบบใช้ Headless UI

import { Dialog, Transition } from "@headlessui/react";
import { Fragment, useState } from "react";

export default function ExampleModal() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="text-center mt-10">
      <button
        onClick={() => setIsOpen(true)}
        className="px-4 py-2 bg-blue-500 text-white rounded"
      >
        เปิด Modal
      </button>

      <Transition appear show={isOpen} as={Fragment}>
        <Dialog as="div" className="fixed inset-0 z-50 flex items-center justify-center" onClose={() => setIsOpen(false)}>
          <div className="bg-white p-6 rounded-lg shadow-lg">
            <Dialog.Title className="text-lg font-bold">นี่คือ Modal!</Dialog.Title>
            <Dialog.Description className="mt-2 text-gray-600">
              กดปุ่มปิดเพื่อออกจาก Modal
            </Dialog.Description>
            <button
              onClick={() => setIsOpen(false)}
              className="mt-4 px-4 py-2 bg-red-500 text-white rounded"
            >
              ปิด
            </button>
          </div>
        </Dialog>
      </Transition>
    </div>
  );
}

✅ ทำไม Headless UI ถึงดีกว่า Modal ปกติ?

  • ใช้งานง่าย แค่ใส่ Dialog
  • รองรับ Keyboard Accessibility อัตโนมัติ
  • ไม่มีสไตล์เกินจำเป็น 👉 Customize ได้เต็มที่!


📜 2️⃣ ทำ Dropdown Menu แบบโปร

🔹 ตัวอย่าง Dropdown Menu

import { Menu, Transition } from "@headlessui/react";
import { Fragment } from "react";

export default function Dropdown() {
  return (
    <Menu as="div" className="relative inline-block text-left">
      <Menu.Button className="px-4 py-2 bg-blue-500 text-white rounded">เมนู</Menu.Button>

      <Transition
        as={Fragment}
        enter="transition ease-out duration-100"
        enterFrom="opacity-0 scale-95"
        enterTo="opacity-100 scale-100"
        leave="transition ease-in duration-75"
        leaveFrom="opacity-100 scale-100"
        leaveTo="opacity-0 scale-95"
      >
        <Menu.Items className="absolute mt-2 w-48 bg-white border rounded shadow-lg">
          <Menu.Item>
            {({ active }) => (
              <a className={`block px-4 py-2 ${active ? "bg-gray-200" : ""}`} href="#">
                โปรไฟล์
              </a>
            )}
          </Menu.Item>
          <Menu.Item>
            {({ active }) => (
              <a className={`block px-4 py-2 ${active ? "bg-gray-200" : ""}`} href="#">
                ตั้งค่า
              </a>
            )}
          </Menu.Item>
        </Menu.Items>
      </Transition>
    </Menu>
  );
}

✅ Dropdown ของ Headless UI ดียังไง?

  • ปรับแต่งได้ง่าย ไม่มีสไตล์บังคับ
  • รองรับ Keyboard Navigation
  • Animate ได้ Smooth (แค่ใช้ Transition)


🏁 สรุป

หัวข้อ รายละเอียด
Headless UI คืออะไร? ชุดคอมโพเนนต์ที่ไม่มีสไตล์บังคับ ให้เราปรับแต่งได้เอง
ข้อดี ยืดหยุ่น, ใช้กับ Tailwind CSS ได้ดี, เร็วและเบากว่า UI Library อื่นๆ
การติดตั้ง npm install @headlessui/react
คอมโพเนนต์ที่ใช้งานบ่อย Modal (Dialog), Dropdown (Menu), Tabs, Popover
เหมาะกับใคร? คนที่ต้องการ UI ที่ Custom ได้เต็มที่ โดยไม่อยากติดดีไซน์เดิมๆ

🎯 สรุปง่ายๆ

ถ้าคุณอยากให้เว็บมี UI ที่ยืดหยุ่น ไม่ถูกบังคับด้วยดีไซน์เดิมๆ และรองรับ Accessibility ดีเยี่ยม 👉 ใช้ Headless UI เถอะ!

ลองไปใช้กับ Tailwind CSS แล้วคุณจะหลงรัก 💙

วันศุกร์ที่ 28 มีนาคม พ.ศ. 2568

🌙 การทำ Dark Mode ใน Next.js: ให้เว็บของคุณเท่ขึ้นแบบมืออาชีพ!

เบื่อไหม? กับเว็บที่สว่างจ้าจนตาล้า 😵‍💫 ถ้าคุณอยากให้ผู้ใช้เลือกได้ว่าอยากใช้ โหมดสว่าง (Light Mode) หรือ โหมดมืด (Dark Mode) ใน Next.js เรามีวิธีง่ายๆ ให้คุณลองทำ!

ในบทความนี้ เราจะมาเจาะลึก การทำ Dark Mode ใน Next.js แบบครบทุกวิธี ทั้งใช้ CSS Variables, useState, localStorage และไลบรารีเสริม เช่น Next Themes กับ Tailwind CSS พร้อมตัวอย่างโค้ดที่เอาไปใช้ได้เลย! 🚀


🔥 ทำไมต้องมี Dark Mode?

✅ ข้อดีของ Dark Mode

  • ช่วยลดอาการล้าสายตา 👀 (สำหรับคนที่ใช้เว็บตอนกลางคืน)
  • ประหยัดแบตเตอรี่ 🔋 (โดยเฉพาะจอ OLED)
  • ดูเท่! 😎 หลายเว็บใหญ่ๆ ก็ใช้ เช่น YouTube, Twitter


🛠 วิธีทำ Dark Mode ใน Next.js

🚀 1. ใช้ CSS Variables + useState

วิธีนี้เหมาะกับ:
✅ เว็บที่ไม่ซับซ้อนมาก
✅ ไม่ต้องใช้ไลบรารีเสริม


👨‍💻 ขั้นตอนการทำ

1️⃣ สร้าง globals.css และกำหนด Theme

แก้ไขไฟล์ styles/globals.css

:root {
  --bg-color: #ffffff;
  --text-color: #000000;
}

.dark-mode {
  --bg-color: #121212;
  --text-color: #ffffff;
}

body {
  background-color: var(--bg-color);
  color: var(--text-color);
  transition: background 0.3s, color 0.3s;
}

2️⃣ เพิ่มปุ่มสลับโหมดใน index.js

เปิดไฟล์ pages/index.js แล้วเพิ่มโค้ดนี้

import { useState } from "react";

export default function Home() {
  const [darkMode, setDarkMode] = useState(false);

  const toggleDarkMode = () => {
    setDarkMode(!darkMode);
    document.body.classList.toggle("dark-mode");
  };

  return (
    <div style={{ textAlign: "center", marginTop: "50px" }}>
      <h1>Dark Mode in Next.js 🌙</h1>
      <button
        onClick={toggleDarkMode}
        style={{
          padding: "10px 20px",
          fontSize: "18px",
          cursor: "pointer",
          background: darkMode ? "#fff" : "#333",
          color: darkMode ? "#000" : "#fff",
          border: "none",
          borderRadius: "5px",
        }}
      >
        {darkMode ? "Switch to Light Mode ☀️" : "Switch to Dark Mode 🌙"}
      </button>
    </div>
  );
}

🛠 2. ใช้ localStorage จำค่าโหมด

ปัญหา: ถ้ารีเฟรชหน้าเว็บ ค่าโหมดที่เลือกไว้จะหายไป
ทางแก้: ใช้ localStorage จำค่าการตั้งค่าของผู้ใช้

อัปเดตโค้ด index.js

import { useState, useEffect } from "react";

export default function Home() {
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    const savedTheme = localStorage.getItem("theme");
    if (savedTheme === "dark") {
      setDarkMode(true);
      document.body.classList.add("dark-mode");
    }
  }, []);

  const toggleDarkMode = () => {
    setDarkMode(!darkMode);
    if (!darkMode) {
      document.body.classList.add("dark-mode");
      localStorage.setItem("theme", "dark");
    } else {
      document.body.classList.remove("dark-mode");
      localStorage.setItem("theme", "light");
    }
  };

  return (
    <div style={{ textAlign: "center", marginTop: "50px" }}>
      <h1>Dark Mode in Next.js 🌙</h1>
      <button
        onClick={toggleDarkMode}
        style={{
          padding: "10px 20px",
          fontSize: "18px",
          cursor: "pointer",
          background: darkMode ? "#fff" : "#333",
          color: darkMode ? "#000" : "#fff",
          border: "none",
          borderRadius: "5px",
        }}
      >
        {darkMode ? "Switch to Light Mode ☀️" : "Switch to Dark Mode 🌙"}
      </button>
    </div>
  );
}

✅ ข้อดี:

  • จำค่าธีมได้หลังจากรีเฟรช


🎨 3. ใช้ next-themes (แนะนำ!)

✅ ข้อดีของ next-themes

  • ใช้ง่ายมาก (ไม่ต้องเขียนโค้ดเยอะ)
  • รองรับ ระบบ Dark Mode อัตโนมัติจาก OS



🛠 ติดตั้ง next-themes

npm install next-themes


👨‍💻 ใช้งาน next-themes

1️⃣ แก้ไข _app.js

import { ThemeProvider } from "next-themes";

export default function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

2️⃣ แก้ไข index.js

import { useTheme } from "next-themes";
import { useEffect, useState } from "react";

export default function Home() {
  const { theme, setTheme } = useTheme();
  const [mounted, setMounted] = useState(false);

  useEffect(() => setMounted(true), []);

  if (!mounted) return null; // ป้องกัน Hydration Error

  return (
    <div className="p-5 text-center">
      <h1 className="text-2xl">Dark Mode with next-themes 🌙</h1>
      <button
        onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
        className="mt-3 px-4 py-2 text-white bg-black rounded"
      >
        {theme === "dark" ? "Switch to Light Mode ☀️" : "Switch to Dark Mode 🌙"}
      </button>
    </div>
  );
}

🔥 ง่ายสุดๆ แค่เรียก setTheme() แล้วปล่อยให้ next-themes จัดการให้!

🏁 สรุป

วิธี ข้อดี ข้อเสีย
CSS Variables + useState ง่าย, ไม่ต้องใช้ไลบรารี รีเฟรชแล้วค่าหาย
localStorage จำค่าธีมได้หลังรีเฟรช ต้องใช้ useEffect
next-themes (แนะนำ) รองรับ Dark Mode อัตโนมัติ ต้องติดตั้งไลบรารี

🎯 ถ้าคุณอยากทำ Dark Mode แบบง่ายสุด 👉 ใช้ next-themes
🎯 ถ้าอยากควบคุมเองทั้งหมด 👉 ใช้ CSS Variables + localStorage

🚀 ลองทำเลย แล้วเว็บของคุณจะดูโปรขึ้น 300%!! 😆

วันพฤหัสบดีที่ 27 มีนาคม พ.ศ. 2568

การใช้ Framer Motion กับ Next.js: เพิ่ม Animation ให้เว็บดูโปรแบบมืออาชีพ 🚀

อย่าปล่อยให้เว็บนิ่งเหมือน PowerPoint สไลด์แรก 😆 ถ้าอยากให้เว็บของคุณดู Smooth และมีชีวิตชีวา Framer Motion คือทางออก!

ในบทความนี้ เราจะมาดูกันว่า Framer Motion ทำงานยังไง และเราจะใช้มันเพิ่ม Animation ให้กับ Next.js ได้แบบไหนบ้าง พร้อมตัวอย่างโค้ดที่เอาไปใช้ได้เลย!


🎭 Framer Motion คืออะไร?

Framer Motion เป็นไลบรารีสำหรับทำ Animation บน React และ Next.js มันใช้ง่ายมาก และทำให้เว็บดู Smooth & Interactive โดยไม่ต้องเขียน CSS Animation เอง

✅ ข้อดีของ Framer Motion

  • ใช้ Props-based Animation 👉 ไม่ต้องเขียน @keyframes
  • รองรับ Server-side Rendering (SSR) 👉 ใช้กับ Next.js ได้ดี
  • มี Gesture & Scroll Animation 👉 รองรับการลาก, สัมผัส และเลื่อน
  • ทำ Animation Complex ได้ง่ายมาก


🚀 ติดตั้ง Framer Motion ใน Next.js

เริ่มต้นง่ายๆ แค่ติดตั้งไลบรารีก่อน

npm install framer-motion

จากนั้นก็พร้อมใช้งานได้เลย! 🎉


🔥 เริ่มต้นกับ Motion Components

🎬 1️⃣ สร้าง Animation ง่ายๆ

เปิดไฟล์ pages/index.js แล้วลองใช้ Motion Component

import { motion } from "framer-motion";

export default function Home() {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 1 }}
      style={{ fontSize: "24px", textAlign: "center", marginTop: "50px" }}
    >
      Hello Framer Motion! 👋
    </motion.div>
  );
}

🔹 อธิบายโค้ด:

  • initial={{ opacity: 0 }} 👉 เริ่มต้นที่โปร่งใส (มองไม่เห็น)
  • animate={{ opacity: 1 }} 👉 ค่อยๆ เผยตัวออกมา
  • transition={{ duration: 1 }} 👉 ใช้เวลา 1 วินาที

🎉 ได้ Animation Fade-in แบบง่ายๆ แล้ว!



🏃 เพิ่ม Motion ให้ปุ่ม

🎬 2️⃣ ปุ่มที่เด้งตอนกด

import { motion } from "framer-motion";

export default function Button() {
  return (
    <motion.button
      whileTap={{ scale: 0.9 }}
      whileHover={{ scale: 1.1 }}
      style={{
        padding: "10px 20px",
        fontSize: "18px",
        borderRadius: "5px",
        border: "none",
        background: "blue",
        color: "white",
        cursor: "pointer",
      }}
    >
      Click Me 🚀
    </motion.button>
  );
}

🔹 อธิบายโค้ด:

  • whileTap={{ scale: 0.9 }} 👉 ปุ่มย่อเล็กลงนิดนึงตอนกด
  • whileHover={{ scale: 1.1 }} 👉 ปุ่มขยายขึ้นตอนเอาเมาส์ไปชี้

🛠 ปรับแต่งปุ่มให้ดูโปรได้ง่ายๆ แบบนี้เลย!


🔄 Animate หลายองค์ประกอบพร้อมกัน

🎬 3️⃣ ทำ List ที่มี Animation ตอนโหลด

import { motion } from "framer-motion";

const items = ["🍎 Apple", "🍌 Banana", "🍒 Cherry", "🍇 Grape"];

export default function List() {
  return (
    <div style={{ padding: "20px" }}>
      {items.map((item, index) => (
        <motion.div
          key={item}
          initial={{ opacity: 0, x: -50 }}
          animate={{ opacity: 1, x: 0 }}
          transition={{ duration: 0.5, delay: index * 0.2 }}
          style={{ fontSize: "20px", marginBottom: "10px" }}
        >
          {item}
        </motion.div>
      ))}
    </div>
  );
}

🔹 อธิบายโค้ด:

  • x: -50 👉 แต่ละไอเทมเริ่มจากซ้ายมือแล้วเลื่อนเข้ามา
  • delay: index * 0.2 👉 ไอเทมจะเลื่อนเข้ามาทีละตัว (ไม่มาพร้อมกัน)

📜 ได้ List ที่มี Animation นุ่มๆ แล้ว!



🎡 ใช้ Variants ให้ Animation ดูเป็นธรรมชาติ

ถ้าต้องการทำ Animation ที่มีหลายสถานะ ใช้ Variants จะช่วยให้โค้ดดูสะอาดขึ้น

🎬 4️⃣ ทำ Animation ตอนเปลี่ยนหน้าใน Next.js

import { motion } from "framer-motion";

const pageVariants = {
  hidden: { opacity: 0, y: 50 },
  visible: { opacity: 1, y: 0, transition: { duration: 0.5 } },
};

export default function Page() {
  return (
    <motion.div
      initial="hidden"
      animate="visible"
      variants={pageVariants}
      style={{ fontSize: "24px", textAlign: "center", marginTop: "50px" }}
    >
      Welcome to the new page! 🎉
    </motion.div>
  );
}

🔹 อธิบายโค้ด:

  • hidden 👉 เริ่มต้นจากด้านล่างและโปร่งใส
  • visible 👉 ขึ้นมาที่ตำแหน่งปกติ และค่อยๆ แสดงผล



📜 ทำ Scroll Animation

อยากให้ Element ขยับตอนเลื่อนหน้าจอไหม?

🎬 5️⃣ ทำให้ Element โผล่มาตอน Scroll

import { motion, useScroll } from "framer-motion";

export default function ScrollEffect() {
  const { scrollYProgress } = useScroll();

  return (
    <motion.div
      style={{
        scale: scrollYProgress,
        width: "100px",
        height: "100px",
        background: "red",
        margin: "50px auto",
      }}
    />
  );
}

🔹 อธิบายโค้ด:

  • useScroll() 👉 ใช้ตรวจจับการเลื่อน
  • scale: scrollYProgress 👉 ยิ่งเลื่อนลง Element ยิ่งขยายใหญ่

🔥 ลองเลื่อนหน้าจอดู แล้วจะเห็นความเปลี่ยนแปลง!


🏁 สรุป

  • Framer Motion ทำให้ Animation ใน Next.js ง่ายและดู Smooth
  • ใช้ motion.div เพื่อทำ Animation ได้ทันที
  • whileHover & whileTap ทำให้ปุ่ม Interactive
  • Variants ช่วยจัดการหลายสถานะของ Animation
  • useScroll ใช้ทำ Scroll Animation ได้ง่าย

🎨 ลองเล่นดู แล้วเว็บของคุณจะดูแพงขึ้น 300%!! 😆

การใช้ Image Optimization ใน Next.js: โหลดไว SEO ดี ประหยัดแบนด์วิธ!

เคยเจอปัญหาเว็บโหลดช้าเพราะรูปภาพขนาดใหญ่หรือเปล่า? 📷 ถ้าใช่ Next.js มีฟีเจอร์ Image Optimization ที่ช่วยให้รูปภาพโหลดเร็วขึ้น อัตโนมัติ ไม...