@olundot/ui · Indicators
Spinner
진행률을 알 수 없는 짧은 대기에 쓰는 비결정 로딩 인디케이터입니다.
- 크기
- sm (16px) · md (24px, 기본) · lg (32px) — 숫자 값 deprecated
- 접근성
- role=status + aria-label 필수 (기본: '로딩 중')
- 배치
- 인라인(size=sm) · 블록(size=md) · 오버레이
- Button 통합
- Button loading prop 사용 시 Loader2 자동 표시 — 별도 Spinner 불필요
- 애니메이션
- spin (prefers-reduced-motion → pulse로 대체)
기본
라이브 (크기 3종 · role=status · aria-label)코드 보기tsx
import { Spinner } from "@olundot/ui";
// Spinner는 <span role="status" aria-label="로딩 중" />을 기본으로 렌더링.
// label prop으로 접근성 텍스트를 맥락에 맞게 변경.
// size: "sm" (16px) · "md" (24px, 기본) · "lg" (32px)
export function SpinnerBasic() {
return (
<div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Spinner size="sm" label="소형 로딩 중" />
<Spinner size="md" label="기본 로딩 중" />
<Spinner size="lg" label="대형 로딩 중" />
</div>
);
}인라인
정적 (버튼·텍스트 옆 인라인 배치)제출 처리 중...
자동 저장 중
코드 보기tsx
import { Spinner } from "@olundot/ui";
export function SpinnerInline() {
return (
<div style={{ display: "grid", gap: "12px" }}>
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
<Spinner size="sm" label="제출 중" />
<span>제출 처리 중...</span>
</div>
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
<Spinner size="sm" label="저장 중" />
<span style={{ fontSize: "0.875rem", color: "var(--text-secondary)" }}>
자동 저장 중
</span>
</div>
</div>
);
}Button loading 통합
라이브 (Button loading prop — Loader2 자동 표시)코드 보기tsx
import { useState } from "react";
import { Button } from "@olundot/ui";
// Button의 loading prop을 사용하면 Loader2 아이콘이 자동으로 표시됨.
// 별도 Spinner를 Button 옆에 두는 패턴 대신 이 방식을 권장.
export function SpinnerToggle() {
const [loading, setLoading] = useState(false);
return (
<div style={{ display: "flex", gap: "12px", alignItems: "center" }}>
<Button
loading={loading}
onClick={() => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
}}
>
{loading ? "처리 중..." : "작업 시작"}
</Button>
</div>
);
}