From ec4ee78fcb278402a22f767b6b041c5c016aff12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AF=BC=ED=97=8C?= Date: Tue, 16 Jun 2026 13:26:18 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20front:=20=EA=B3=B5=ED=86=B5=20UI=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8(Button/Input)=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 네이티브 element props 상속 + className 병합(무의존 cn 헬퍼) - Button: variant(primary/secondary/outline/ghost/destructive)/size, hover 톤다운(brand-700) - React 19 기준 forwardRef 없이 ref 전달 Co-Authored-By: Claude Opus 4.8 (1M context) --- front/src/component/Button.tsx | 53 ++++++++++++++++++++++++++++++++++ front/src/component/Input.tsx | 18 ++++++++++++ front/src/component/cn.ts | 11 +++++++ front/src/component/index.ts | 4 +++ 4 files changed, 86 insertions(+) create mode 100644 front/src/component/Button.tsx create mode 100644 front/src/component/Input.tsx create mode 100644 front/src/component/cn.ts create mode 100644 front/src/component/index.ts diff --git a/front/src/component/Button.tsx b/front/src/component/Button.tsx new file mode 100644 index 0000000..fce5fe4 --- /dev/null +++ b/front/src/component/Button.tsx @@ -0,0 +1,53 @@ +import { type ComponentProps } from 'react' +import { cn } from './cn' + +export type ButtonVariant = + | 'primary' + | 'secondary' + | 'outline' + | 'ghost' + | 'destructive' +export type ButtonSize = 'sm' | 'md' | 'lg' + +const base = + 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium ' + + 'transition-colors cursor-pointer select-none ' + + 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ' + + 'disabled:pointer-events-none disabled:opacity-50' + +// hover 는 한 단계 톤다운(brand-700) — 디자인 선호 +const variantClass: Record = { + primary: 'bg-primary text-primary-foreground hover:bg-brand-700', + secondary: 'bg-secondary text-secondary-foreground hover:bg-accent', + outline: + 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + ghost: 'hover:bg-accent hover:text-accent-foreground', + destructive: 'bg-destructive text-white hover:opacity-90', +} + +const sizeClass: Record = { + sm: 'h-8 px-3 text-sm', + md: 'h-10 px-4 text-sm', + lg: 'h-11 px-6 text-base', +} + +export interface ButtonProps extends ComponentProps<'button'> { + variant?: ButtonVariant + size?: ButtonSize +} + +export function Button({ + variant = 'primary', + size = 'md', + type = 'button', + className, + ...props +}: ButtonProps) { + return ( +