Spinner

Feedback & Status

로딩 상태를 나타내는 스피너.

Usage

짧은 로딩 상태를 원형 인디케이터로 표시할 때 진행률을 알 수 없는 불확정(Indeterminate) 대기를 표시할 때 (알 수 있으면 Progress Bar)

import

import

import { Spinner } from '@mildang/design-system/Spinner';

API Reference

Spinner Props

Prop

Type

Default

color

"green" | "white" | "neutral" | "inverse" | "brand"

green

panda

SystemStyleObject

지정 안 함

shape

"inherit" | "square" | "round" | "butt"

butt

size

number | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "2xs"

xl

thickness

number

3.6

같은 패밀리

@mildang/design-system/Spinner 에서 같이 내보내는 컴포넌트다.

크기

2xs(18px)부터 2xl(48px)까지 7단계다. 트랙과 인디케이터 두 원이 같은 값을 공유하므로 지름 하나로 전체 크기가 정해진다.

sizepx주 용도
2xs18소형 버튼·컴팩트 레이아웃 내 inline, 테이블 셀·조밀 UI
xs20버튼 로딩(기본), 텍스트 옆 작은 inline
sm22테이블 행·폼 필드 단위 inline
md24일반 블록·툴바·텍스트 옆 inline (배경 분리된 영역의 기본 크기)
lg(기본값)28카드·리스트 블록 로딩, 썸네일·미디어 영역 대기 표시
xl32모달·대시보드 섹션 로딩, 카드·모듈 중앙
2xl48페이지·오버레이(스크림) 로딩, 대형 섹션·그래프 중앙 정렬

Sizes

2xs부터 2xl까지 7단계 크기 스케일을 한 줄로 비교합니다.

import { Spinner } from '@mildang/design-system/Spinner';
import { type ComponentProps } from 'react';

const STORY_DEFAULT_ARGS = { ...({}), ...({
    color: 'green',
    size: 'md',
  }) } as ComponentProps<typeof Spinner>;

const SpinnerDemoExampleRender = (args: ComponentProps<typeof Spinner>) => {
    return <Spinner {...args} />;
  };

export default function SpinnerDemoExample(props: Partial<ComponentProps<typeof Spinner>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Spinner>;
  return SpinnerDemoExampleRender(mergedProps);
}

색은 놓일 면의 명도를 전제로 고른다. white·inverse는 짙은 면 위(필터 버튼 등), green(기본값)·neutral·brand는 옅은 면 위를 기준으로 만들어졌다 — 반대로 쓰면 스피너가 배경에 묻혀 보이지 않는다.

inverse는 테마에 따라 자동으로 반전된다: mildang·school처럼 짙은 surface를 쓰는 테마에서는 흰 스피너, educore처럼 옅은 surface를 쓰는 테마에서는 진한 스피너가 된다. 테마 간 배경 명도가 뒤집히는 자리(예: 버튼 secondary variant)에 쓴다.

색상별 배경 매칭

각 색이 전제하는 배경 명도에 맞춰 카드를 나눠 보여줍니다.

import { Spinner } from '@mildang/design-system/Spinner';

const typeItemStyle = { display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' } as const;

const typeBoxStyle = { background: '#fff', padding: 16, borderRadius: 12 } as const;

const SpinnerTypeExample = () => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 32 }}>
      <section>
        <h4 style={{ marginBottom: 12 }}>기본 테마</h4>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, auto)', gap: 24, justifyContent: 'start' }}>
          <div style={typeItemStyle}>
            <strong>White</strong>
            <div style={{ ...typeBoxStyle, background: '#000' }}>
              <Spinner color="white" size="xl" />
            </div>
          </div>
          <div style={typeItemStyle}>
            <strong>Green</strong>
            <div style={typeBoxStyle}>
              <Spinner color="green" size="xl" />
            </div>
          </div>
          <div style={typeItemStyle}>
            <strong>Neutral</strong>
            <div style={typeBoxStyle}>
              <Spinner color="neutral" size="xl" />
            </div>
          </div>
          <div style={typeItemStyle}>
            <strong>Brand</strong>
            <div style={typeBoxStyle}>
              <Spinner color="brand" size="xl" />
            </div>
          </div>
        </div>
      </section>
      <section data-panda-theme="educore">
        <h4 style={{ marginBottom: 12 }}>Educore(경기도) 테마</h4>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, auto)', gap: 24, justifyContent: 'start' }}>
          <div style={typeItemStyle}>
            <strong>White</strong>
            <div style={{ ...typeBoxStyle, background: 'rgba(0,0,0,0.6)' }}>
              <Spinner color="white" size="xl" />
            </div>
          </div>
          <div style={typeItemStyle}>
            <strong>Neutral</strong>
            <div style={typeBoxStyle}>
              <Spinner color="neutral" size="xl" />
            </div>
          </div>
          <div style={typeItemStyle}>
            <strong>Brand</strong>
            <div style={typeBoxStyle}>
              <Spinner color="brand" size="xl" />
            </div>
          </div>
        </div>
      </section>
    </div>
  );

export default SpinnerTypeExample;