Loader and Skeleton
아직 불러오는 중인 내용을 위한 컴포넌트 두 개입니다. Loader.Root는 값이 없는 네이티브 <progress>이고, Skeleton.Root는 자리를 채우는 div입니다. Server Components는 @tounsoo/todae/loader과 @tounsoo/todae/skeleton에서 가져올 수 있습니다.
이 페이지의 내용
Loader
Loader.Root는 progressbar 역할이 그대로 남으므로 스크린 리더는 진행 막대로 알려 주고, 다른 progress처럼 이름이 필요합니다. 텍스트와 함께 <label>로 감싸거나 aria-label을 주세요. 기본값인 variant="spinner"에서는 채움 호 하나가 도는 고리로 그려지고, 사용자가 동작 줄이기를 요청하면 멈춥니다. value는 받지 않습니다. 끝을 아는 기다림에는 Progress 막대를 쓰세요.
<label>
<Loader.Root /> Loading invoices
</label>
<Loader.Root aria-label="Saving" />
Dots
variant="dots"는 타이핑 표시처럼 점 세 개가 차례로 올라가며, 텍스트가 시작하는 쪽부터 움직입니다. 채팅의 어시스턴트처럼 누군가 답을 쓰고 있을 때 쓰세요. 같은 <progress>이고 역할도 같으므로 역시 이름이 필요하며, 동작 줄이기에서는 점이 멈춥니다.
<Loader.Root variant="dots" aria-label="Assistant is typing" />
두 변형 모두 텍스트 색으로 그리므로 기본 버튼을 포함해 어떤 표면에서도 보입니다. 색을 바꾸려면 color를 정하세요. loader.size(점은 너비가 1.5배입니다), loader.thickness, loader.track-tint(트랙이 텍스트 색을 얼마나 쓰는지), loader.motion.duration(점의 물결 한 번)으로 바꾸세요. loader.thickness와 loader.track-tint는 스피너에만 적용됩니다.
Skeleton
Skeleton.Root는 내용이 오기 전에 그 자리를 대신합니다. 높이는 최소 한 줄이고, 안에 든 요소는 크기만 정할 뿐 숨겨집니다. 깜빡이며, 동작 줄이기에서는 멈춥니다.
<div>
<VisuallyHidden.Root>Loading profile</VisuallyHidden.Root>
<Stack.Root direction="row" aria-hidden="true">
<Skeleton.Root style={{ inlineSize: '2.5rem', blockSize: '2.5rem', borderRadius: '50%' }} />
<Stack.Root style={{ flex: 1 }}>
<Skeleton.Root style={{ inlineSize: '40%' }} />
<Skeleton.Root style={{ inlineSize: '70%' }} />
</Stack.Root>
</Stack.Root>
</div>
Skeleton은 스크린 리더에게 아무 뜻이 없으니 aria-hidden으로 숨기고, 무엇을 불러오는지 텍스트로 알리세요. skeleton.bg, skeleton.radius, skeleton.motion.duration, skeleton.motion.easing, 그리고 펄스가 옅어지는 불투명도인 skeleton.pulse.opacity로 바꾸세요.
접근성을 지키는 조합
Todae가 맡는 것: 스타일만 맡습니다. Loader.Root는 progressbar role을 가진 네이티브 <progress> 그대로이며, value를 받지 않으므로 늘 바쁜 상태로 알려집니다. 동작 줄이기 설정에서는 멈춥니다. Skeleton.Root는 안의 요소를 visibility: hidden으로 숨기므로 보조 기술에서도 숨겨지지만, 바로 안에 있는 맨 텍스트는 투명해질 뿐이라 여전히 읽힙니다.
직접 제공할 것: 무엇을 불러오는지 말해 주는 각 로딩 표시의 이름. <label>이나 aria-label로 붙이세요. 각 Skeleton의 aria-hidden, 그리고 위처럼 VisuallyHidden 등으로 그 옆에 적은 로딩 문구. 내용이 도착하면 둘 다 그 내용으로 바꾸세요.
주의할 점: 다른 텍스트 없이 aria-hidden만 있는 로딩 표시. 그 영역이 바쁘다고 알려 주는 것이 없습니다. 목록의 모든 행에 넣은 로딩 표시. 각각 진행 막대로 읽힙니다. 영역 전체에 하나가 더 잘 읽힙니다.
언제 쓰나요
쓸 때: Spinner → 저장이나 검색처럼 동작 하나나 작은 영역을 잠깐 기다릴 때. Dots → 답을 쓰고 있을 때. Skeleton → 내용이 오기 전에 페이지나 구역의 배치를 이미 알 때.
쓰지 않을 때: 끝을 아는 기다림 → value가 있는 Progress. 길거나 실패할 수 있는 기다림 → 텍스트로 알리고 취소나 다시 시도할 방법을 주세요.
Props
| 이름 | 타입 | 설명 |
|---|---|---|
variant | "spinner" | "dots" | spinner는 고리의 호 하나를 돌리고, dots는 타이핑 표시처럼 점 세 개에 물결을 보냅니다. data-variant를 설정합니다. 기본값: "spinner" |
aria-label | string | 텍스트가 있는 label 안에 있지 않을 때 표시에 이름을 붙입니다. progressbar role을 유지하므로 이름이 필요합니다. |
| 이름 | 타입 | 설명 |
|---|---|---|
children | React.ReactNode | 크기만 정하는 요소. 숨겨집니다. |