Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Blur from "@/components/common/Blur";

Check warning on line 1 in app/page.tsx

View workflow job for this annotation

GitHub Actions / lint

'Blur' is defined but never used
import Button from "@/components/ui/Button";

export default function Home() {
return (
<main>
<Blur />
<Button fixed={true}>안녕하세요</Button>
</main>
);
}
56 changes: 28 additions & 28 deletions app/tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
99 changes: 99 additions & 0 deletions components/ui/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react";
import { cn } from "@/lib/utils";

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
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<HTMLButtonElement>;
}

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 (
<button
ref={ref}
type={type}
disabled={disabled}
className={cn(
// 기본 스타일
"flex items-center justify-center rounded-[12px] transition-colors duration-100",
finalBackgroundColor,
height,
finalTextColor,
fontSize,
// fixed 속성에 따른 분기
fixed ? "fixed z-50 mx-auto" : width,
// disabled 상태에 따른 커서
disabled ? "cursor-not-allowed" : "cursor-pointer",
className,
)}
style={{
...(fixed
? {
bottom: getBottomValue(),
left: `${sideGap}px`,
right: `${sideGap}px`,
maxWidth: `${maxWidth}px`,
}
: undefined),
...(isPrimaryButton
? {
border: "0.8px solid rgba(255, 255, 255, 0.3)",
boxShadow:
"0px 4px 8px rgba(0, 0, 0, 0.08), 0px 0px 16px rgba(0, 0, 0, 0.16)",
}
: undefined),
}}
{...props}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

웹 표준(스타일 가이드 규칙 80)을 준수하고 예기치 않은 동작을 방지하기 위해 버튼의 type을 명시적으로 지정하는 것이 좋습니다. type의 기본값을 'button'으로 설정하면, 이 컴포넌트가 <form> 안에서 사용될 때 의도치 않은 폼 제출을 막을 수 있습니다. 이 제안은 propstype이 전달될 경우 해당 값을 우선적으로 사용합니다.

Suggested change
{...props}
{...{ type: "button", ...props }}
References
  1. 폼 제출 버튼은 type="submit"을 명시하는 등, 버튼의 역할을 명확히 하여 웹 표준을 준수해야 합니다. 일반 버튼의 경우 type="button"을 명시하여 의도치 않은 동작을 방지하는 것이 좋습니다. (link)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type의 기본값을 button으로 설정완료

>
{children}
</button>
);
}
4 changes: 2 additions & 2 deletions scripts/generate-tokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
const tokenName = sanitizeKey(lastPart);

// tokenMap에서 찾기
for (const [key, token] of tokenMap.entries()) {

Check warning on line 106 in scripts/generate-tokens.js

View workflow job for this annotation

GitHub Actions / lint

'key' is assigned a value but never used
if (token.name === tokenName) {
return `var(--${token.name})`;
}
Expand Down Expand Up @@ -176,14 +176,14 @@
});
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;
Expand Down
Loading