From a7bcbeda723b695460bcade3171a32b9fe34f54a Mon Sep 17 00:00:00 2001 From: "jihoon87.lee" Date: Wed, 4 Feb 2026 09:35:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A1=9C=EB=94=A9=20=EC=8A=A4=ED=94=BC?= =?UTF-8?q?=EB=84=88=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=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 - LoadingSpinner: 전체 화면 로딩 스피너 - InlineSpinner: 인라인 로딩 스피너 (버튼 내부용) --- components/ui/loading-spinner.tsx | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 components/ui/loading-spinner.tsx diff --git a/components/ui/loading-spinner.tsx b/components/ui/loading-spinner.tsx new file mode 100644 index 0000000..d7a95e3 --- /dev/null +++ b/components/ui/loading-spinner.tsx @@ -0,0 +1,109 @@ +"use client"; + +import { cn } from "@/lib/utils"; + +/** + * [로딩 스피너 컴포넌트] + * + * 전역적으로 사용 가능한 로딩 스피너입니다. + * - 크기 조절 가능 (sm, md, lg) + * - 색상 커스터마이징 가능 + * - 텍스트와 함께 사용 가능 + * + * @example + * // 기본 사용 + * + * + * @example + * // 크기 및 텍스트 지정 + * + * + * @example + * // 버튼 내부에서 사용 + * + */ + +interface LoadingSpinnerProps { + /** 스피너 크기 */ + size?: "sm" | "md" | "lg"; + /** 스피너와 함께 표시할 텍스트 */ + text?: string; + /** 추가 CSS 클래스 */ + className?: string; + /** 스피너 색상 (Tailwind 클래스) */ + color?: string; +} + +export function LoadingSpinner({ + size = "md", + text, + className, + color = "border-gray-900 dark:border-white", +}: LoadingSpinnerProps) { + // 크기별 스타일 매핑 + const sizeClasses = { + sm: "h-4 w-4 border-2", + md: "h-8 w-8 border-3", + lg: "h-12 w-12 border-4", + }; + + return ( +
+ {/* ========== 회전 스피너 ========== */} +
+ {/* ========== 로딩 텍스트 (선택적) ========== */} + {text && ( + + {text} + + )} +
+ ); +} + +/** + * [인라인 스피너 컴포넌트] + * + * 버튼 내부나 작은 공간에서 사용하기 적합한 미니 스피너입니다. + * + * @example + * + */ +export function InlineSpinner({ className }: { className?: string }) { + return ( + + + + + ); +}