๊ฐœ๋ฐœ/Next.js

nextjs shadcn/ui ์—์„œ ๋ฏธ๋””์–ด์ฟผ๋ฆฌ ์ž‘์—…ํ•˜๊ธฐ

๋ฐ(Ming) ๐Ÿˆ‍โฌ› 2024. 6. 10. 23:21
728x90
๋ฐ˜์‘ํ˜•

 

๋ฐ˜์‘ํ˜• ์›น์‚ฌ์ดํŠธ ์ œ์ž‘์€ ์ด์ œ ๊ทธ๋ƒฅ ํ•„์ˆ˜์ด๋‹ค. ๋ฏธ๋””์–ด์ฟผ๋ฆฌ ์ž‘์—…์„ ํ•  ๋•Œ ํ•ญ์ƒ ๋ธŒ๋ ˆ์ดํฌ ํฌ์ธํŠธ๋ฅผ ์žก๋Š” ๊ฒƒ์ด ์• ๋งคํ•˜๋‹ค๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ

์šฐ์„ ์€ 768px ์ตœ์†Œ๋กœ ํ–ˆ์„ ๊ฒฝ์šฐ๋ฅผ ๋‘๊ณ  ์ž‘์—…์— ๋“ค์–ด๊ฐ”๋‹ค. 

 

shadcn/ui ์ด๋ž€?

Radix UI ๋ฐ Tailwind CSS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์ถ•๋œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ. ์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹Œ ์•ฑ์— copy and paste ํ•˜์—ฌ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์„ฑ์š”์†Œ ๋ชจ์Œ์ด๋‹ค. npm install ์„ ํ•˜์—ฌ ์ข…์†์„ฑ ์„ค์น˜๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ด์•ผ๊ธฐ๋‹ค. tailwind css๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ๋‹ค. ์ปค์Šคํ…€์„ ํ•  ๋• tailwind css ๋ฒ•์น™์„ ๋”ฐ๋ฅด๋ฉด ๋œ๋‹ค. 

 

์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Nextjs , tailwind css ๊ฐ€ ์„ค์น˜๋˜์–ด์žˆ์–ด์•ผํ•œ๋‹ค. 

๋‹ค ๊ฐ์„คํ•˜๊ณ  shadcn/ui๋ฅผ ์“ฐ๋ฉด์„œ ๋ฏธ๋””์–ด์ฟผ๋ฆฌ ์ž‘์—…์„ ํ•˜๋ ค๋ฉด ์ผ์ผํžˆ css๋ฅผ ๊ฑด๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์กฐ๊ธˆ ๊ฐ„ํŽธํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค

 

 

 

1. shadcn/ui์—์„œ ์ œ๊ณตํ•˜๋Š” hook ์‚ฌ์šฉํ•˜๊ธฐ

 

์•„๋ž˜๋Š” shadcn/ui๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊นƒํ—™์ด๋‹ค. ์ด๊ณณ์—์„œ ๊ฐ์ข… ui ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

use-media-query ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ ์ž์‹ ์ด ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋กœ ๋ถ™์—ฌ๋„ฃ๋Š”๋‹ค. 

 

https://github.com/shadcn-ui/ui/blob/main/apps/www/hooks/use-media-query.tsx

 

ui/apps/www/hooks/use-media-query.tsx at main · shadcn-ui/ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source. - shadcn-ui/ui

github.com

 

 

2. ๋ฐ˜์‘ํ˜• ๋ฉ”๋‰ด๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

"use client";

import { useMediaQuery } from "@/hooks/use-media-query";

// ๋ชจ๋ฐ”์ผ ๋ฒ„์ ผ์ผ ๋•Œ ๋‚˜์™€์•ผํ•  drawer 
import { Drawer, DrawerContent, DrawerTrigger } from "./ui/drawer";

// ๊ธฐ์กด์˜ ๋ฉ”๋‰ด
import {
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
} from "@/components/ui/navigation-menu";
import { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu";
import Link from "next/link";
import { Menu } from "lucide-react";

const MainMenu = () => {
  const isDesktop = useMediaQuery("(min-width: 768px)");

  const menuList: { title: string; href: string }[] = [
.....
  ];

  const menuDisplay = (menuList: any[]) => {
    return (
 .......
    );
  };

  return (
    <div className="flex h-50 justify-between">
..................
    </div>
  );
};

export default MainMenu;

 

๋ณต๋ถ™ํ–ˆ๋˜ useMediaQuery๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ทธ ์•ˆ์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์›ํ•˜๋Š” ์ˆ˜์น˜๋ฅผ ๋„ฃ์–ด์ค€๋‹ค

 

 

const isDesktop = useMediaQuery("(min-width: 768px)");

 

 

 

 

3. ์ •ํ•ด์ง„ ๋ฒ”์œ„๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์— ๋„ฃ์–ด์„œ ์ ์šฉํ•˜์ž

  return (
    <div className="flex h-50 justify-between">
      <div className="flex items-center p-5">
        <Link href="/" className="flex z-40 font-semibold">
          Logo
        </Link>
      </div>
      ////////////// ์—ฌ๊ธฐ์š”์˜ค์˜ค์˜ค์˜ค 
      {isDesktop ? (
        <div className="flex gap-6">
          <NavigationMenu>
            <NavigationMenuList>{menuDisplay(menuList)}</NavigationMenuList>
          </NavigationMenu>
        </div>
      ) : (
        <div className="flex p-1">
          <Drawer direction="right">
            <DrawerTrigger>
              <Menu />
            </DrawerTrigger>
            <DrawerContent>
              <NavigationMenu orientation="vertical" className="items-start">
                <NavigationMenuList className="h-full flex-col items-start space-x-0">
                  {menuDisplay(menuList)}
                </NavigationMenuList>
              </NavigationMenu>
            </DrawerContent>
          </Drawer>
        </div>
      )}
    </div>
  );

 

 

drawer์€  ํด๋ฆญ์‹œ์— ์˜†์ด๋‚˜ ์•„๋ž˜์—์„œ ์“ฐ์œฝ - ํ•˜๊ณ  ๋‚˜ํƒ€๋‚˜๋Š” ํŒ์—…์ฐฝ๊ฐ™์€ ๊ฑธ ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ ์„œ๋ž์—ด๋“ฏ์ด~ ์•„๋ž˜์™€ ๊ฐ™์€ ui์ด๋‹ค.

 

 

isDesktop์ด๋ฉด ์ผ๋ฐ˜ header์— ๋ถ™๋Š” ๋ฉ”๋‰ด๊ฐ€ ๋‚˜์˜ค๊ณ , ์•„๋‹ˆ๋ฉด drawer์ด ๋‚˜์˜ค๊ฒŒ ํ–ˆ๋‹ค. 

๊ฐ„๋‹จํ•˜์ง€์šฅ? 

๋‹ค์Œ์—๋Š” drawer ๋ฐฉํ–ฅ์„ ์ „ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณต์œ ํ•˜๊ฒ ์Œ!

 

 

 

 

 

 

728x90