RingProgress

RingProgress

원형 다이어그램으로 작업 상태 피드백을 제공하는 컴포넌트예요. 링 모양의 진행률 링을 만들어요.

출처: 문서

본문

사용법 (Usage)

sections prop은 다음 속성을 가진 객체 배열을 받아요.

  • value – 링을 채울 비율을 나타내는 0~100 사이의 숫자
  • color – theme.colors의 세그먼트 색상 또는 어떤 CSS 색상 값
  • tooltip (선택) – 섹션 위에 마우스를 올렸을 때 표시할 React 노드
  • 유효한 SVG <circle> 요소 prop (onClick, onMouseEnter, style 등)

참고: 예상대로 동작하려면 섹션 값의 합이 100% 이하여야 해요. 100%를 초과하면 섹션이 겹치게 돼요.

import { RingProgress, Text } from '@mantine/core';

function Demo() {
  return (
    <RingProgress
      label={<Text size="xs">Application data usage</Text>}
      sections={[
        { value: 40, color: 'cyan' },
        { value: 15, color: 'orange' },
        { value: 15, color: 'grape' },
      ]}
    />
  );
}

크기, 두께와 둥근 모서리 (Size, thickness & rounded caps)

size, thickness, roundCaps prop으로 RingProgress의 크기와 두께를 설정해요.

import { RingProgress } from '@mantine/core';

function Demo() {
  return (
    <RingProgress
      size={160}
      thickness={12}
      roundCaps
      sections={[
        { value: 40, color: 'cyan' },
        { value: 15, color: 'orange' },
        { value: 15, color: 'grape' },
      ]}
    />
  );
}

섹션 툴팁 (Sections tooltips)

섹션에 tooltip 속성을 추가하면 사용자가 섹션 위에 마우스를 올렸을 때 떠다니는 Tooltip이 표시돼요.

import { RingProgress, Text } from '@mantine/core';

function Demo() {
  return (
    <RingProgress
      label={<Text size="xs">Hover sections to see tooltips</Text>}
      sections={[
        { value: 40, color: 'cyan', tooltip: 'Documents – 40 Gb' },
        { value: 25, color: 'orange', tooltip: 'Apps – 25 Gb' },
        { value: 15, color: 'grape', tooltip: 'Other – 15 Gb' },
      ]}
    />
  );
}

섹션 간격 (Section gaps)

sectionGap prop으로 섹션 사이에 시각적 구분을 추가할 수 있어요. 간격은 도(degrees) 단위로 지정해요.

import { RingProgress, Stack, Text } from '@mantine/core';

function Demo() {
  const sections = [
    { value: 40, color: 'cyan' },
    { value: 25, color: 'orange' },
    { value: 15, color: 'grape' },
  ];

  return (
    <Stack>
      <Text>No gap (default)</Text>
      <RingProgress sections={sections} sectionGap={0} />
      <Text>5° gap</Text>
      <RingProgress sections={sections} sectionGap={5} />
      <Text>10° gap</Text>
      <RingProgress sections={sections} sectionGap={10} />
    </Stack>
  );
}

시작 각도 (Start angle)

startAngle prop으로 진행률이 시작되는 위치를 제어해요. 각도는 도 단위로 지정하며, 0 = 오른쪽, 90 = 아래, 180 = 왼쪽, 270 = 위(기본값)를 나타내요.

import { Group, RingProgress, Stack, Text } from '@mantine/core';

function Demo() {
  const sections = [{ value: 40, color: 'cyan' }];

  return (
    <Group>
      <Stack><Text>0° (right)</Text><RingProgress sections={sections} startAngle={0} /></Stack>
      <Stack><Text>90° (bottom)</Text><RingProgress sections={sections} startAngle={90} /></Stack>
      <Stack><Text>180° (left)</Text><RingProgress sections={sections} startAngle={180} /></Stack>
      <Stack><Text>270° (top)</Text><RingProgress sections={sections} startAngle={270} /></Stack>
    </Group>
  );
}

배경 색상 (Background color)

rootColor prop으로 링에서 채워지지 않은 부분(배경)의 색상을 커스터마이즈할 수 있어요.

import { RingProgress } from '@mantine/core';

function Demo() {
  return (
    <RingProgress
      sections={[{ value: 40, color: 'cyan' }]}
      rootColor="var(--mantine-color-gray-4)"
    />
  );
}

섹션 이벤트 (Section events)

각 섹션은 유효한 SVG <circle> 요소 prop을 받을 수 있어요. onClick, onMouseEnter, onMouseLeave 같은 이벤트 핸들러도 포함해요.

import { useState } from 'react';
import { RingProgress, Text } from '@mantine/core';

function Demo() {
  const [hovered, setHovered] = useState(-1);
  const reset = () => setHovered(-1);

  return (
    <>
      <RingProgress
        onMouseLeave={() => setHovered(-1)}
        size={140}
        sections={[
          { value: 40, color: 'cyan', onMouseEnter: () => setHovered(0), onMouseLeave: reset },
          { value: 20, color: 'blue', onMouseEnter: () => setHovered(1), onMouseLeave: reset },
          { value: 15, color: 'indigo', onMouseEnter: () => setHovered(2), onMouseLeave: reset },
        ]}
      />
      <Text>Hovered section: {hovered === -1 ? 'none' : hovered}</Text>
    </>
  );
}

라벨 커스터마이즈 (Customize label)

라벨로 어떤 React 노드든 추가할 수 있어요. 예를 들어 커스텀 스타일의 Text 컴포넌트나 ActionIcon을 넣을 수 있어요.

import { ActionIcon, RingProgress, Text, Center } from '@mantine/core';
import { CheckIcon } from '@phosphor-icons/react';

function Demo() {
  return (
    <>
      <RingProgress
        label={
          <Text c="blue" fw={700} ta="center" size="xl">
            40%
          </Text>
        }
        sections={[{ value: 40, color: 'cyan' }]}
      />
      <RingProgress
        sections={[{ value: 100, color: 'teal' }]}
        label={
          <Center>
            <ActionIcon color="teal" variant="light" radius="xl" size={44}>
              <CheckIcon size={22} />
            </ActionIcon>
          </Center>
        }
      />
    </>
  );
}

채워진 세그먼트 전환 (Filled segment transition)

기본적으로 전환은 비활성화돼 있어요. 활성화하려면 transitionDuration prop을 밀리초 단위 숫자로 설정해요.

import { useState } from 'react';
import { Button, RingProgress, Stack, Text } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState(30);

  return (
    <>
      <RingProgress
        sections={[{ value, color: 'cyan' }]}
        transitionDuration={300}
        label={<Text>{value}%</Text>}
      />
      <Button onClick={() => setValue(Math.floor(Math.random() * 100))}>Set random value</Button>
    </>
  );
}

더 알아보기 (Learn more)