diff --git a/app/page.tsx b/app/page.tsx
index 718c073..19f56fb 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,9 +1,10 @@
import Blur from "@/components/common/Blur";
+import Button from "@/components/ui/Button";
export default function Home() {
return (
-
+
);
}
diff --git a/app/tokens.css b/app/tokens.css
index 02dc7fb..753c63a 100644
--- a/app/tokens.css
+++ b/app/tokens.css
@@ -135,169 +135,169 @@
@layer utilities {
/* Font utilities */
- .text-16-400 {
+ .typo-16-400 {
font-size: 16px;
font-weight: 400;
line-height: 1.5;
}
- .text-16-500 {
+ .typo-16-500 {
font-size: 16px;
font-weight: 500;
line-height: 1.5;
}
- .text-16-600 {
+ .typo-16-600 {
font-size: 16px;
font-weight: 600;
line-height: 1.5;
}
- .text-16-700 {
+ .typo-16-700 {
font-size: 16px;
font-weight: 700;
line-height: 1.5;
}
- .text-20-400 {
+ .typo-20-400 {
font-size: 20px;
font-weight: 400;
line-height: 1.5;
}
- .text-20-500 {
+ .typo-20-500 {
font-size: 20px;
font-weight: 500;
line-height: 1.5;
}
- .text-20-600 {
+ .typo-20-600 {
font-size: 20px;
font-weight: 600;
line-height: 1.5;
}
- .text-20-700 {
+ .typo-20-700 {
font-size: 20px;
font-weight: 700;
line-height: 1.5;
}
- .text-24-400 {
+ .typo-24-400 {
font-size: 24px;
font-weight: 400;
line-height: 1.5;
}
- .text-24-500 {
+ .typo-24-500 {
font-size: 24px;
font-weight: 500;
line-height: 1.5;
}
- .text-24-600 {
+ .typo-24-600 {
font-size: 24px;
font-weight: 600;
line-height: 1.5;
}
- .text-24-700 {
+ .typo-24-700 {
font-size: 24px;
font-weight: 700;
line-height: 1.5;
}
- .text-12-400 {
+ .typo-12-400 {
font-size: 12px;
font-weight: 400;
line-height: 1.5;
}
- .text-12-500 {
+ .typo-12-500 {
font-size: 12px;
font-weight: 500;
line-height: 1.5;
}
- .text-12-600 {
+ .typo-12-600 {
font-size: 12px;
font-weight: 600;
line-height: 1.5;
}
- .text-12-700 {
+ .typo-12-700 {
font-size: 12px;
font-weight: 700;
line-height: 1.5;
}
- .text-14-400 {
+ .typo-14-400 {
font-size: 14px;
font-weight: 400;
line-height: 1.5;
}
- .text-14-500 {
+ .typo-14-500 {
font-size: 14px;
font-weight: 500;
line-height: 1.5;
}
- .text-14-600 {
+ .typo-14-600 {
font-size: 14px;
font-weight: 600;
line-height: 1.5;
}
- .text-14-700 {
+ .typo-14-700 {
font-size: 14px;
font-weight: 700;
line-height: 1.5;
}
- .text-10-400 {
+ .typo-10-400 {
font-size: 10px;
font-weight: 400;
line-height: 1.5;
}
- .text-10-500 {
+ .typo-10-500 {
font-size: 10px;
font-weight: 500;
line-height: 1.5;
}
- .text-10-600 {
+ .typo-10-600 {
font-size: 10px;
font-weight: 600;
line-height: 1.5;
}
- .text-10-700 {
+ .typo-10-700 {
font-size: 10px;
font-weight: 700;
line-height: 1.5;
}
- .text-18-400 {
+ .typo-18-400 {
font-size: 18px;
font-weight: 400;
line-height: 1.5;
}
- .text-18-500 {
+ .typo-18-500 {
font-size: 18px;
font-weight: 500;
line-height: 1.5;
}
- .text-18-600 {
+ .typo-18-600 {
font-size: 18px;
font-weight: 600;
line-height: 1.5;
}
- .text-18-700 {
+ .typo-18-700 {
font-size: 18px;
font-weight: 700;
line-height: 1.5;
diff --git a/components/ui/Button.tsx b/components/ui/Button.tsx
new file mode 100644
index 0000000..d3740d1
--- /dev/null
+++ b/components/ui/Button.tsx
@@ -0,0 +1,99 @@
+import React from "react";
+import { cn } from "@/lib/utils";
+
+interface ButtonProps extends React.ButtonHTMLAttributes {
+ children: React.ReactNode;
+ backgroundColor?: string;
+ width?: string;
+ height?: string;
+ fixed?: boolean;
+ bottom?: number; // 하단 여백 (px)
+ sideGap?: number; // 좌우 여백 (px)
+ maxWidth?: number; // fixed일 때 최대 너비 (px)
+ textColor?: string;
+ fontSize?: string;
+ safeArea?: boolean; // safe-area-inset-bottom 적용 여부
+ ref?: React.Ref;
+}
+
+export default function Button({
+ children,
+ backgroundColor = "bg-button-primary",
+ width = "w-full",
+ height = "h-12",
+ fixed = false,
+ bottom = 0,
+ sideGap = 16,
+ maxWidth = 430,
+ textColor = "text-button-primary-text-default",
+ fontSize = "typo-20-600",
+ safeArea = true,
+ disabled = false,
+ className,
+ ref,
+ type = "button",
+ ...props
+}: ButtonProps) {
+ // disabled 상태에 따른 배경색/텍스트색 결정
+ const finalBackgroundColor = disabled
+ ? "bg-button-background-disabled"
+ : backgroundColor;
+ const finalTextColor = disabled
+ ? "text-button-primary-text-disabled"
+ : textColor;
+
+ // bg-button-primary일 때 border와 shadow 추가
+ const isPrimaryButton = finalBackgroundColor === "bg-button-primary";
+
+ // fixed일 때 bottom 계산 (safeArea 적용)
+ const getBottomValue = () => {
+ if (!fixed) return undefined;
+
+ if (safeArea) {
+ return `calc(${bottom}px + env(safe-area-inset-bottom))`;
+ }
+
+ return `${bottom}px`;
+ };
+
+ return (
+
+ );
+}
diff --git a/scripts/generate-tokens.js b/scripts/generate-tokens.js
index c047395..3e34833 100644
--- a/scripts/generate-tokens.js
+++ b/scripts/generate-tokens.js
@@ -176,14 +176,14 @@ colorTokens
});
const textColorUtilities = Array.from(textColorUtilitiesSet).sort().join("\n");
-// 폰트 사이즈 유틸리티 (text-{size}-{weight})
+// 폰트 사이즈 유틸리티 (typo-{size}-{weight})
const weights = ["400", "500", "600", "700"];
const fontUtilitiesSet = new Set();
fontTokens.forEach((t) => {
const size = t.value;
if (typeof size === "number") {
weights.forEach((weight) => {
- fontUtilitiesSet.add(` .text-${size}-${weight} {
+ fontUtilitiesSet.add(` .typo-${size}-${weight} {
font-size: ${size}px;
font-weight: ${weight};
line-height: 1.5;