diff --git a/.gitignore b/.gitignore index 0c461061..46faa2ba 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ next-env.d.ts *storybook.log storybook-static + +# vscode +.vscode diff --git a/src/app/example/page.tsx b/src/app/example/page.tsx new file mode 100644 index 00000000..7788dd01 --- /dev/null +++ b/src/app/example/page.tsx @@ -0,0 +1,17 @@ +import Header from "@/components/header/Header"; +import React from "react"; + +const Page = () => { + return ( +
+
+
+ ); +}; + +export default Page; diff --git a/src/app/globals.css b/src/app/globals.css index dcd564b8..41aeb618 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -33,3 +33,13 @@ body { * { box-sizing: border-box; } + +@layer utilities { + .flex-center { + @apply flex items-center justify-center; + } + + .flex-col-center { + @apply flex flex-col items-center justify-center; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index dde9abb2..262abf1f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { sfPro } from "./fonts"; import "./globals.css"; +import { Gnb } from "@/components"; import QueryProvider from "@/providers/query-provider"; export const metadata: Metadata = { @@ -14,9 +15,12 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - - {children} + + + + + {children} + ); diff --git a/src/components/gnb/Gnb.stories.tsx b/src/components/gnb/Gnb.stories.tsx new file mode 100644 index 00000000..ddaa356c --- /dev/null +++ b/src/components/gnb/Gnb.stories.tsx @@ -0,0 +1,18 @@ +import { Meta, StoryObj } from "@storybook/nextjs"; +import Gnb from "./Gnb"; + +const meta = { + title: "Components/Gnb", + component: Gnb, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: () => , +}; diff --git a/src/components/gnb/Gnb.tsx b/src/components/gnb/Gnb.tsx new file mode 100644 index 00000000..e6caba51 --- /dev/null +++ b/src/components/gnb/Gnb.tsx @@ -0,0 +1,37 @@ +import { cn } from "@/lib/utils"; +import Link from "next/link"; + +const LinkMenu = [ + { name: "WHYNE", href: "/" }, + { + name: "로그인", + href: "/login", + style: "underline-offset-2 hover:underline", + }, +]; + +const Gnb = () => { + return ( +
+ {/* TODO(지권): 로고 아이콘 추가 및 로그인 상태 추가 */} + {LinkMenu.map((menu) => ( + + {menu.name} + + ))} +
+ ); +}; + +export default Gnb; diff --git a/src/components/header/Header.stories.tsx b/src/components/header/Header.stories.tsx new file mode 100644 index 00000000..07e39816 --- /dev/null +++ b/src/components/header/Header.stories.tsx @@ -0,0 +1,51 @@ +import type { Meta, StoryObj } from "@storybook/nextjs"; +import Header from "./Header"; + +const meta: Meta = { + title: "Components/Header", + component: Header, + parameters: { + layout: "centered", + }, + argTypes: { + review: { control: { type: "text" } }, + title: { control: { type: "text" } }, + description: { control: { type: "text" } }, + price: { control: { type: "text" } }, + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + review: "128", + title: "샤또 마고 2015", + description: "블랙커런트와 바이올렛 아로마, 벨벳 같은 타닌", + price: "64,990", + }, +}; + +export const ManyReviews: Story = { + name: "리뷰가 많은 경우", + args: { + review: "12,345", + title: "도멘 드 라 로마네 콩티", + description: "풍부한 베리 계열 향과 깊은 여운", + price: "1,200,000", + }, +}; + +export const LongText: Story = { + name: "제목/설명이 긴 경우", + args: { + review: "87", + title: + "긴 이름의 와인이 들어갔을 때 줄바꿈과 레이아웃이 자연스러운지 확인합니다", + description: + "설명도 길어질 때 두 줄 이상이 되었을 때 라인하이트와 간격이 의도대로 나오는지 테스트합니다", + price: "199,000", + }, +}; diff --git a/src/components/header/Header.tsx b/src/components/header/Header.tsx new file mode 100644 index 00000000..22bdbd83 --- /dev/null +++ b/src/components/header/Header.tsx @@ -0,0 +1,54 @@ +import { cn } from "@/lib/utils"; + +interface HeaderProps { + review: string; + title: string; + description: string; + price: string; +} + +const Header = ({ review, title, description, price }: HeaderProps) => { + return ( +
+
+
+ {/* TODO(지권): 별 아이콘 추가 필요 */} +
⭐️⭐️⭐️⭐️
+

+ {review}개의 후기 +

+
+
+

+ {title} +

+ + {description} + +
+
+
+ {price}원 +
+
+ ); +}; + +export default Header; diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 00000000..eff89347 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,2 @@ +export { default as Gnb } from "./gnb/Gnb"; +export { default as Header } from "./header/Header"; diff --git a/tailwind.config.ts b/tailwind.config.ts index 2035a651..93070bc2 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -11,12 +11,19 @@ export default { colors: { black: "#111111", white: "#FFFFFF", + default: "#31302F", + secondary: "#A3A3A3", gray100: "#FAFAFA", gray300: "#D1D1D1", gray600: "#8C8C8B", gray800: "#484746", primary: "#1A1918", }, + screens: { + mobile: { max: "743px" }, + tablet: { min: "744px", max: "1279px" }, + pc: { min: "1280px" }, + }, fontSize: { "title-hero": ["32px", { lineHeight: "46px", fontWeight: "700" }], "title-page-md": ["40px", { lineHeight: "52px", fontWeight: "700" }],