@olundot/ui · Feedback
Progress
업로드, 채점, 환경 설정 확인, 다단계 처리에 쓰는 결정 완료 인디케이터입니다.
- API
- value · max(기본 100) · status(active/success/error/paused) · width · height
- 접근성
- role=progressbar + aria-valuenow/min/max 자동 적용
- 상태 소유권
- status는 막대 색만 제어하고 원인·복구 문구는 wrapper가 설명합니다.
- 권장
- 실제 완료율이 없으면 Spinner 사용 (허위 진행 금지)
기본
결정 진행률을 단계별로 비교0%
50%
100%
코드 보기tsx
import { Progress } from "@olundot/ui";
// Progress는 role=progressbar + aria-valuenow/min/max를 자동 적용.
// max: 기본 100, width: 기본 120px, height: 기본 4px.
export function ProgressBasic() {
return (
<div style={{ display: "grid", gap: "16px" }}>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>0%</p>
<Progress value={0} width="100%" aria-label="0퍼센트 진행률" />
</div>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>50%</p>
<Progress value={50} width="100%" aria-label="50퍼센트 진행률" />
</div>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>100%</p>
<Progress value={100} width="100%" aria-label="100퍼센트 진행률" />
</div>
</div>
);
}조절 가능한 진행률
input range로 value 조정문항 가져오기35%
코드 보기tsx
import { useState } from "react";
import { Progress } from "@olundot/ui";
export function ProgressLive() {
const [value, setValue] = useState(35);
return (
<div style={{ display: "grid", gap: "12px" }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<span style={{ fontSize: "0.875rem", color: "var(--text-secondary)" }}>
문항 가져오기
</span>
<span style={{ fontSize: "0.875rem", fontVariantNumeric: "tabular-nums" }}>
{value}%
</span>
</div>
<Progress value={value} width="100%" height={6} aria-label="문항 가져오기 진행률" />
<input
type="range"
min={0}
max={100}
value={value}
onChange={(e) => setValue(Number(e.target.value))}
style={{ width: "100%" }}
aria-label="진행률 조절"
/>
</div>
);
}두께 비교
표면 밀도에 맞춰 진행 막대 두께 선택4px (기본)
6px
8px
코드 보기tsx
import { Progress } from "@olundot/ui";
export function ProgressSizes() {
return (
<div style={{ display: "grid", gap: "16px" }}>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>4px (기본)</p>
<Progress value={72} width="100%" height={4} />
</div>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>6px</p>
<Progress value={72} width="100%" height={6} />
</div>
<div>
<p style={{ marginBottom: "8px", fontSize: "0.875rem", color: "var(--text-secondary)" }}>8px</p>
<Progress value={72} width="100%" height={8} />
</div>
</div>
);
}중단·오류·사용 불가
status는 막대 색, 원인과 복구 문구는 wrapper가 소유문항 업로드일시 중지
네트워크 확인 후 이어서 진행합니다.
자동 채점오류
실패 원인을 확인하고 다시 실행합니다.
리포트 생성완료
모든 리포트가 생성되었습니다.
코드 보기tsx
import { Progress } from "@olundot/ui";
const PROGRESS_STATES = [
{
label: "문항 업로드",
status: "일시 중지",
progressStatus: "paused",
value: 64,
helper: "네트워크 확인 후 이어서 진행합니다.",
},
{
label: "자동 채점",
status: "오류",
progressStatus: "error",
value: 38,
helper: "실패 원인을 확인하고 다시 실행합니다.",
},
{
label: "리포트 생성",
status: "완료",
progressStatus: "success",
value: 100,
helper: "모든 리포트가 생성되었습니다.",
},
];
export function ProgressStates() {
return (
<div style={{ display: "grid", gap: "16px" }}>
{PROGRESS_STATES.map(({ label, status, progressStatus, value, helper }) => (
<div
key={label}
style={{ display: "grid", gap: "8px" }}
>
<div style={{ display: "flex", justifyContent: "space-between", gap: "12px" }}>
<span style={{ fontSize: "0.875rem", color: "var(--text-secondary)" }}>{label}</span>
<span style={{ fontSize: "0.875rem", color: "var(--text-secondary)" }}>{status}</span>
</div>
<Progress status={progressStatus} value={value} width="100%" height={6} aria-label={`${label} ${status}`} />
<span style={{ fontSize: "0.8125rem", color: "var(--text-tertiary)" }}>{helper}</span>
</div>
))}
</div>
);
}