개요
Next.js 프로젝트에서 shadcn/ui
를 사용해서, 반응형 사이드바를 쉽게 구현할 수 있다.
구현 방법
dashboard-02
의 코드를 베이스로 구현하려고 한다.
※ 해당 컴포넌트에 대한 전체 코드: dashboard-02
-
패키지 설치
- 먼저,
shadcn/ui
를 설치한다.
install shadcn/ui npx shadcn-ui@latest init
- 먼저,
-
코드 복사
copy code
버튼을 클릭해서,dashboard-02
의 코드를 가져와서app/page.tsx
에 붙여넣어 준다.
-
컴포넌트 추가
- 아직 컴포넌트가 없으므로 오류가 생길 것이다. 아래 명령어로 컴포넌트를 추가한다.
add components npx shadcn-ui@latest add badge button card dropdown-menu input sheet
-
컴포넌트 분리
mobile navigation
에 해당하는 부분을components/ui
에mobile-nav.tsx
파일을 생성해서 옮겨준다.
mobile-nav.tsx import Link from 'next/link'; import { Menu, Package2, Home, ShoppingCart, Package, Users, LineChart, } from 'lucide-react'; import { Button } from './button'; import { Card, CardHeader, CardTitle, CardDescription, CardContent, } from './card'; import { Sheet, SheetTrigger, SheetContent } from './sheet'; import { Badge } from './badge'; export default function MobileNav() { return ( <Sheet> <SheetTrigger asChild> <Button variant="outline" size="icon" className="shrink-0 md:hidden"> <Menu className="h-5 w-5" /> <span className="sr-only">Toggle navigation menu</span> </Button> </SheetTrigger> <SheetContent side="left" className="flex flex-col"> <nav className="grid gap-2 text-lg font-medium"> <Link href="#" className="flex items-center gap-2 text-lg font-semibold" > <Package2 className="h-6 w-6" /> <span className="sr-only">Acme Inc</span> </Link> <Link href="#" className="text-muted-foreground hover:text-foreground mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2" > <Home className="h-5 w-5" /> Dashboard </Link> <Link href="#" className="bg-muted text-foreground hover:text-foreground mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2" > <ShoppingCart className="h-5 w-5" /> Orders <Badge className="ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded-full"> 6 </Badge> </Link> <Link href="#" className="text-muted-foreground hover:text-foreground mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2" > <Package className="h-5 w-5" /> Products </Link> <Link href="#" className="text-muted-foreground hover:text-foreground mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2" > <Users className="h-5 w-5" /> Customers </Link> <Link href="#" className="text-muted-foreground hover:text-foreground mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2" > <LineChart className="h-5 w-5" /> Analytics </Link> </nav> <div className="mt-auto"> <Card> <CardHeader> <CardTitle>Upgrade to Pro</CardTitle> <CardDescription> Unlock all features and get unlimited access to our support team. </CardDescription> </CardHeader> <CardContent> <Button size="sm" className="w-full"> Upgrade </Button> </CardContent> </Card> </div> </SheetContent> </Sheet> ); }
-
sidebar
에 해당하는 부분을components/ui
에sidebar.tsx
파일을 생성해서 옮겨준다.sidebar.tsx import Link from 'next/link'; import { Bell, Home, ShoppingCart, Package, Users, LineChart, Package2, } from 'lucide-react'; import { Button } from './button'; import { Badge } from './badge'; import { Card, CardHeader, CardTitle, CardDescription, CardContent, } from './card'; export default function Sidebar() { return ( <aside className="bg-muted/40 hidden border-r md:block"> <div className="flex h-full max-h-screen flex-col gap-2"> <div className="flex h-14 items-center border-b px-4 lg:h-[60px] lg:px-6"> <Link href="/" className="flex items-center gap-2 font-semibold"> <Package2 className="h-6 w-6" /> <span className="">Acme Inc</span> </Link> <Button variant="outline" size="icon" className="ml-auto h-8 w-8"> <Bell className="h-4 w-4" /> <span className="sr-only">Toggle notifications</span> </Button> </div> <div className="flex-1"> <nav className="grid items-start px-2 text-sm font-medium lg:px-4"> <Link href="#" className="text-muted-foreground flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary" > <Home className="h-4 w-4" /> Dashboard </Link> <Link href="#" className="text-muted-foreground flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary" > <ShoppingCart className="h-4 w-4" /> Orders <Badge className="ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded-full"> 6 </Badge> </Link> <Link href="#" className="bg-muted flex items-center gap-3 rounded-lg px-3 py-2 text-primary transition-all hover:text-primary" > <Package className="h-4 w-4" /> Products{' '} </Link> <Link href="#" className="text-muted-foreground flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary" > <Users className="h-4 w-4" /> Customers </Link> <Link href="#" className="text-muted-foreground flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary" > <LineChart className="h-4 w-4" /> Analytics </Link> </nav> </div> <div className="mt-auto p-4"> <Card x-chunk="dashboard-02-chunk-0"> <CardHeader className="p-2 pt-0 md:p-4"> <CardTitle>Upgrade to Pro</CardTitle> <CardDescription> Unlock all features and get unlimited access to our support team. </CardDescription> </CardHeader> <CardContent className="p-2 pt-0 md:p-4 md:pt-0"> <Button size="sm" className="w-full"> Upgrade </Button> </CardContent> </Card> </div> </div> </aside> ); }
- 코드 정리
- 사용하지 않는 부분에 대한 코드를 제거해준다. 예를 들어, 사이드바 하단의 Card 부분을 제거해준다.
- 중복되는 코드에 대해 컴포넌트를 생성해서 분리해준다. 네비게이션에 들어갈 목록은 화면 사이즈에 상관없이 동일하므로 이를 새로운 컴포넌트로 분리해준다.
구현 결과
아래 링크를 통해 정리된 소스 코드의 완성본을 확인할 수 있다.
완성된 소스 코드
참고: Youtube Link