npm install
npm run dev
๊ธฐ์กด์ airbnb์๋ ๋ค๋ฅด๊ฒ, app ๋๋ ํ ๋ฆฌ ํ์์ ๋ฐ๋ก page.tsx๋ฅผ ์์น ์ํจ๊ฒ ์๋, (site)
๋ผ๋ ๋๋ ํ ๋ฆฌ ํ์์ page.tsx๋ฅผ ์์น ์์ผฐ๋ค.
์ ์ฒด์ ์ธ Layout์ Layout.tsx์ ์์ฑ์ ํ์๋ค.
// app/layout.tsx
import './globals.css';
import type { Metadata } from 'next';
import { Figtree } from 'next/font/google';
import SideBar from '@/components/SideBar';
const font = Figtree({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'Spotify Clone',
description: 'Listen to music!',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang='en'>
<body className={font.className}>
<SideBar>{children}</SideBar>
</body>
</html>
);
}
SideBar.tsx์ ์ ์ฒด์ ์ธ ๋ ์ด์์์ด ์กํ์๋ค. ์ถ๊ฐ๋ก tailwind-merge๋ฅผ ์ฌ์ฉํด์ ๊ธฐ๋ณธ์ ์ธ ์คํ์ผ ์์ฑ์ ๋ฏธ๋ฆฌ ์ ์ธํด๋๊ณ , ์ถ๊ฐ๋ก ํ์ํ CSS ์์ฑ์ props์ className
๋ก ๋๊ฒจ ๊ธฐ์กด ์คํ์ผ์ ํ์ฅ์ํค๊ฑฐ๋, ์ค๋ฒ๋ผ์ด๋ฉ์ ํ ์ ์๋ค.
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, children, disabled, type = 'button', ...props }, ref) => {
return (
<button
type={type}
className={twMerge(
`
w-full
rounded-full
bg-green-500
border
border-transparent
px-3
py-3
disabled:cursor-not-allowed
disabled:opacity-50
text-black
font-bold
hover:opacity-75
transition
`,
className
)}
disabled={disabled}
ref={ref}
{...props}
>
{children}
</button>
);
}
);
Button.displayName = 'Button';
export default Button;
๋ณด๋ ๊ฒ์ฒ๋ผ twMerge()
ํจ์ ๋ด๋ถ์ ๋ฏธ๋ฆฌ ์ง์ ํด ๋์ CSS์์ฑ์ ์
๋ ฅํด ๋๋๋ค.