진행
진행은 얼마나 남았는지를 말합니다. 기다림이 길어질수록 표현을 한 단계씩 올립니다.
1초 안 → 아무것도 보이지 않습니다. 1–3초 → 누른 버튼의 스피너(Button loading). 3–10초이고 알 수 있음 → 그 자리의 Progress. 10초 넘게 → 백그라운드 작업 + 진행 토스트. 페이지 이동이 200ms 넘게 → PageProgress. 막대는 파인 홈에 한 색으로 차고, 완료 · 실패 · 멈춤은 막대 색이 아니라 글리프와 글자가 말합니다.
- import
- import { Progress, ProgressRing } from "@uyoolabs/ui/ui"; import { PageProgress, UploadList, UploadPanel, StepProgress } from "@uyoolabs/ui/feedback";
- 고르는 법
- 끝나는 일 → Progress(막대), 폭이 좁으면 ProgressRing. 파일 올리기 → UploadList · UploadPanel. 서버에서 오래 도는 작업의 단계 → StepProgress. 페이지 이동 → PageProgress. 값의 크기(사용량 · 좌석 · 저장 공간) → Meter(차트 페이지).
- 쓰지 않는 경우
- 1초 안에 끝나는 일에 막대를 띄우지 않습니다. 화면 전체를 덮는 스피너를 쓰지 않습니다. 실패를 막대 색(빨강)으로만 말하지 않습니다. 사용량을 진행 막대로 그리지 않습니다. 마법사 이동(Stepper)에 StepProgress 를 쓰지 않습니다.
Progress · ProgressRing
막대 sm 4 · md 6 · lg 8, 원 16 · 24 · 40. role=progressbar 이고 이름(label)은 필수입니다.
끝났습니다실패
PageProgress
상단 바 아래 헤어라인 자리 2px. 200ms 지연 · 90% 앞에서 멈춤 · 끝나면 200ms 페이드. 막대는 읽지 않고 main 에 aria-busy 를 답니다.
결제 개편 › 작업 › PAY-142
UploadList · UploadPanel · StepProgress
파일마다 한 줄(이름 · 크기 · 막대 · 남은 시간 · 동작). 패널은 토스트 층(70)의 뜬 판이고 다 끝나면 5초 뒤 접힙니다.
- 결제 흐름도.png
- PG 연동 설계 v3.pdf
- 정산 원본.xlsx
워크스페이스 가져오기1 / 3 단계
- 파일 확인, 끝남0:04
- 메시지 가져오기, 진행 중62%12,400 / 20,000개 · 약 3분 남음
- 멤버 31명 초대, 기다림
| 키 | 동작 |
|---|---|
| Tab | 줄 순서대로 취소 · 다시 시도 · 빼기, 패널 머리의 접기 · 닫기 |
| Enter·Space | 단추 실행 |
| 막대 · 원 | 포커스를 받지 않는다. 진행 값은 알리지 않는다 |
| 라이브 영역 | 시작 · 끝은 polite, 실패는 assertive 로 한 번. 퍼센트마다 읽지 않는다 |
| 줄인 모션 | 불확정 조각 · 원이 멈추고 ‘처리 중’ 글자만 남는다 |
props
소스의 타입과 JSDoc 에서 생성한 표입니다. 컴포넌트를 고치면 pnpm gen 으로 다시 만듭니다.
Progress
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| value | number | — | 0–max. 넘거나 모자라면 [0, max] 로 자른다. 없으면 불확정(조각이 오간다) |
| max | number | 100 | 기본 100. 0 이하면 비율 0 |
| size | "sm" | "md" | "lg" | "md" | sm 4 · md 6 · lg 8 |
| label필수 | string | — | 무엇의 진행인가(접근성 이름). 곁에 같은 글자가 보여도 준다 |
| valueText | string | — | aria-valuetext(‘12,400 / 20,000개’). 없으면 불확정일 때 labels.processing |
| block | boolean | — | 폭 100%. 기본은 표 셀에 맞는 64 |
| decorative | boolean | — | 곁에 같은 값의 글자가 이미 있을 때(‘reported 3 / 5’) 막대를 장식으로 둔다(aria-hidden). 이름 · 값을 두 번 읽지 않게 한다 |
| lang | "ko" | "en" | "ja" | — | |
| labels | Partial<ProgressLabels> | — |
이 밖에 <span> props(children 제외)를 그대로 받습니다.
ProgressRing
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| value | number | — | 0–max. 넘거나 모자라면 [0, max] 로 자른다. 없으면 불확정(원이 천천히 돈다) |
| max | number | 100 | 기본 100. 0 이하면 비율 0 |
| size | 16 | 24 | 40 | 24 | 지름. 16 표 안 · 24 파일 줄 · 40 가운데 값 |
| label필수 | string | — | 접근성 이름(무엇의 진행). 필수 |
| showValue | boolean | true | 40 에서 가운데 글자를 보인다. 기본 true(16 · 24 는 자리가 없어 보이지 않는다) |
| valueText | string | — | aria-valuetext(‘2.8MB / 8.1MB’). 40 의 가운데 글자도 이 글자다 |
| status | "active" | "done" | "failed" | "paused" | "active" | done · failed · paused 는 원 자리에 글리프 + 곁에 글자. 채움 색은 바뀌지 않는다 |
| lang | "ko" | "en" | "ja" | "ko" | |
| labels | Partial<ProgressRingLabels> | — |
이 밖에 <span> props(children 제외)를 그대로 받습니다.
PageProgress
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| active필수 | boolean | — | 페이지 이동 · 큰 불러오기가 진행 중인가 |
| delay | number | 200 | 이 시간(ms) 안에 끝나면 아예 그리지 않는다. 기본 200 |
| progress | number | — | 앱이 진행률을 알 때(0–1). 없으면 90% 앞까지 스스로 늘어난다 |
| busy | boolean | true | 진행 중에 가장 가까운 main 에 aria-busy 를 단다. 기본 true — 막대는 읽지 않고 본문이 바쁘다고 말한다 |
| lang | "ko" | "en" | "ja" | — | |
| labels | Partial<ProgressLabels> | — | |
| className | string | — |
UploadList
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| items필수 | readonly UploadItem[] | — | |
| onCancel | (id: string) => void | — | |
| onRetry | (id: string) => void | — | |
| onRemove | (id: string) => void | — | |
| onOpen | (id: string) => void | — | |
| announce | "all" | "failures" | "none" | "all" | 라이브 영역: all = 시작 · 끝(polite) · 실패(assertive), failures = 실패만(UploadPanel 은 머리 문장이 나머지를 말한다), none = 알리지 않는다. 퍼센트마다 읽지 않는다 |
| lang | "ko" | "en" | "ja" | "ko" | |
| labels | Partial<ProgressLabels> | — | |
| className | string | — |
UploadPanel
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| items필수 | readonly UploadItem[] | — | |
| onCancel | (id: string) => void | — | |
| onRetry | (id: string) => void | — | |
| onRemove | (id: string) => void | — | |
| onOpen | (id: string) => void | — | |
| announce | "all" | "failures" | "none" | — | 라이브 영역: all = 시작 · 끝(polite) · 실패(assertive), failures = 실패만(UploadPanel 은 머리 문장이 나머지를 말한다), none = 알리지 않는다. 퍼센트마다 읽지 않는다 |
| lang | "ko" | "en" | "ja" | "ko" | |
| labels | Partial<ProgressLabels> | — | |
| className | string | — | |
| collapsed | boolean | — | 제어 — 머리 한 줄만 남긴다 |
| defaultCollapsed | boolean | false | 비제어 첫 값 |
| onCollapsedChange | (collapsed: boolean) => void | — | |
| onClose | () => void | — | 닫기. 진행 중인 파일이 있으면 단추 이름이 ‘모두 취소하고 닫기’ 다(취소는 앱이 한다) |
| autoCollapseMs | number | 5000 | 모두 끝나면 이 시간(ms) 뒤 접는다. 기본 5000, 0 이면 접지 않는다 |
StepProgress
| prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| title필수 | ReactNode | — | 작업 이름(‘워크스페이스 가져오기’) |
| steps필수 | readonly Step[] | — | |
| actions | ReactNode | — | 바닥 줄(멈추기 · 안내 문장) |
| lang | "ko" | "en" | "ja" | "ko" | |
| labels | Partial<ProgressLabels> | — | |
| className | string | — |