File name
Commit message
Commit date
File name
Commit message
Commit date
type SpinnerSize = "sm" | "md" | "lg";
type SpinnerTone = "primary" | "inverse" | "muted";
const SIZE_CLASSES: Record<SpinnerSize, string> = {
sm: "size-4 border-2",
md: "size-6 border-2",
lg: "size-8 border-4",
};
const TONE_CLASSES: Record<SpinnerTone, string> = {
primary: "text-primary",
inverse: "text-on-primary",
muted: "text-foreground-subtle",
};
interface SpinnerProps {
size?: SpinnerSize;
tone?: SpinnerTone;
/** 스크린리더 전용 안내 문구. 기본 '불러오는 중'. */
label?: string;
}
/** 로딩 인디케이터. 상태 없는 프레젠테이션 컴포넌트 — 표시 여부는 호출부 책임. */
export function Spinner({
size = "md",
tone = "primary",
label = "불러오는 중",
}: SpinnerProps) {
return (
<span role="status" className="inline-flex items-center">
<span
aria-hidden="true"
className={`inline-block animate-spin rounded-full border-current border-t-transparent ${SIZE_CLASSES[size]} ${TONE_CLASSES[tone]}`}
/>
<span className="sr-only">{label}</span>
</span>
);
}