Badge

Badge (배지)

Badge는 보통 알림이나 사용자 아바타 근처에 눈에 띄게 표시되며, 주로 읽지 않은 메시지 개수를 나타내는 컴포넌트예요.

출처: 문서

본문

언제 사용하나요

Badge는 보통 알림이나 사용자 아바타 근처에 눈에 띄게 나타나며, 주로 읽지 않은 메시지 개수를 표시해요.

예제 (Examples)

기본 (Basic)

가장 단순한 사용법이에요. count가 0이면 Badge는 숨겨지지만, showZero를 사용해 표시할 수 있어요.

import React from 'react';
import { ClockCircleOutlined } from '@ant-design/icons';
import { Avatar, Badge, Space } from 'antd';

const App: React.FC = () => (
  <Space size="medium">
    <Badge count={5}>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge count={0} showZero>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}>
      <Avatar shape="square" size="large" />
    </Badge>
  </Space>
);

export default App;

단독 사용 (Standalone)

children이 비어 있을 때 단독으로 사용돼요.

import React, { useState } from 'react';
import { ClockCircleOutlined } from '@ant-design/icons';
import { Badge, Space, Switch } from 'antd';

const App: React.FC = () => {
  const [show, setShow] = useState(true);

  return (
    <Space>
      <Switch aria-label="Show badge counts" checked={show} onChange={() => setShow(!show)} />
      <Badge count={show ? 11 : 0} showZero color="#faad14" />
      <Badge count={show ? 25 : 0} />
      <Badge count={show ? <ClockCircleOutlined style={{ color: '#f5222d' }} /> : 0} />
      <Badge
        className="site-badge-count-109"
        count={show ? 109 : 0}
        style={{ backgroundColor: '#52c41a' }}
      />
    </Space>
  );
};

export default App;

오버플로 개수 (Overflow Count)

count가 overflowCount보다 크면 ${overflowCount}+가 표시돼요. overflowCount의 기본값은 99예요.

import React from 'react';
import { Avatar, Badge, Space } from 'antd';

const App: React.FC = () => (
  <Space size="large">
    <Badge count={99}>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge count={100}>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge count={99} overflowCount={10}>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge count={1000} overflowCount={999}>
      <Avatar shape="square" size="large" />
    </Badge>
  </Space>
);

export default App;

빨간 점 (Red badge)

구체적인 개수 없이 빨간 점만 표시해요. count가 0이면 점을 표시하지 않아요.

import React from 'react';
import { NotificationOutlined } from '@ant-design/icons';
import { Badge, Space } from 'antd';

const App: React.FC = () => (
  <Space>
    <Badge dot>
      <NotificationOutlined style={{ fontSize: 16 }} />
    </Badge>
    <Badge dot>
      <a href="#">Link something</a>
    </Badge>
  </Space>
);

export default App;

동적 (Dynamic)

count가 변할 때 애니메이션 효과가 적용돼요.

import React, { useState } from 'react';
import { MinusOutlined, PlusOutlined, QuestionOutlined } from '@ant-design/icons';
import { Avatar, Badge, Button, Space, Switch } from 'antd';

const App: React.FC = () => {
  const [count, setCount] = useState(5);
  const [show, setShow] = useState(true);

  const increase = () => {
    setCount(count + 1);
  };

  const decline = () => {
    let newCount = count - 1;
    if (newCount < 0) {
      newCount = 0;
    }
    setCount(newCount);
  };

  const random = () => {
    const newCount = Math.floor(Math.random() * 100);
    setCount(newCount);
  };

  const onChange = (checked: boolean) => {
    setShow(checked);
  };

  return (
    <Space vertical>
      <Space size="large">
        <Badge count={count}>
          <Avatar shape="square" size="large" />
        </Badge>
        <Space.Compact>
          <Button onClick={decline} icon={<MinusOutlined />} />
          <Button onClick={increase} icon={<PlusOutlined />} />
          <Button onClick={random} icon={<QuestionOutlined />} />
        </Space.Compact>
      </Space>
      <Space size="large">
        <Badge dot={show}>
          <Avatar shape="square" size="large" />
        </Badge>
        <Switch aria-label="Show badge dot" onChange={onChange} checked={show} />
      </Space>
    </Space>
  );
};

export default App;

클릭 가능 (Clickable)

Badge를 a 태그로 감싸 링크로 만들 수 있어요.

import React from 'react';
import { Avatar, Badge } from 'antd';

const App: React.FC = () => (
  <a href="#">
    <Badge count={5}>
      <Avatar shape="square" size="large" />
    </Badge>
  </a>
);

export default App;

오프셋 (Offset)

배지 점의 오프셋을 설정해요. 형식은 [left, top]으로, 상태 점이 기본 위치의 왼쪽과 위에서 얼마나 떨어지는지를 나타내요.

import React from 'react';
import { Avatar, Badge } from 'antd';

const App: React.FC = () => (
  <Badge count={5} offset={[10, 10]}>
    <Avatar shape="square" size="large" />
  </Badge>
);

export default App;

크기 (Size)

숫자 Badge의 크기를 설정해요.

import React from 'react';
import { Avatar, Badge, Space } from 'antd';

const App: React.FC = () => (
  <Space size="medium">
    <Badge size="medium" count={5}>
      <Avatar shape="square" size="large" />
    </Badge>
    <Badge size="small" count={5}>
      <Avatar shape="square" size="large" />
    </Badge>
  </Space>
);

export default App;

상태 (Status)

상태가 있는 단독 배지예요.

import React from 'react';
import { Badge, Space } from 'antd';

const App: React.FC = () => (
  <>
    <Space>
      <Badge status="success" />
      <Badge status="error" />
      <Badge status="default" />
      <Badge status="processing" />
      <Badge status="warning" />
    </Space>
    <br />
    <Space vertical>
      <Badge status="success" text="Success" />
      <Badge status="error" text="Error" />
      <Badge status="default" text="Default" />
      <Badge status="processing" text="Processing" />
      <Badge status="warning" text="Warning" />
    </Space>
  </>
);

export default App;

컬러풀 Badge

다양한 상황에 쓰기 위한 일련의 컬러풀한 Badge 스타일을 미리 정의해 뒀어요. 커스텀 색을 위해 hex 색 문자열로도 설정할 수 있어요.

import React from 'react';
import { Badge, Divider, Space } from 'antd';

const colors = [
  'pink',
  'red',
  'yellow',
  'orange',
  'cyan',
  'green',
  'blue',
  'purple',
  'geekblue',
  'magenta',
  'volcano',
  'gold',
  'lime',
];

const App: React.FC = () => (
  <>
    <Divider titlePlacement="start">Presets</Divider>
    <Space vertical>
      {colors.map((color) => (
        <Badge key={color} color={color} text={color} />
      ))}
    </Space>
    <Divider titlePlacement="start">Custom</Divider>
    <Space vertical>
      <Badge color="#f50" text="#f50" />
      <Badge color="rgb(45, 183, 245)" text="rgb(45, 183, 245)" />
      <Badge color="hsl(102, 53%, 61%)" text="hsl(102, 53%, 61%)" />
      <Badge color="hwb(205 6% 9%)" text="hwb(205 6% 9%)" />
    </Space>
  </>
);

export default App;

리본 (Ribbon)

리본 배지를 사용해요.

import React from 'react';
import { Badge, Card, Space } from 'antd';

const App: React.FC = () => (
  <Space vertical size="medium" style={{ width: '100%' }}>
    <Badge.Ribbon text="Hippies">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="pink">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="red">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="cyan">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="green">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="purple">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="volcano">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
    <Badge.Ribbon text="Hippies" color="magenta">
      <Card title="Pushes open the window" size="small">
        and raises the spyglass.
      </Card>
    </Badge.Ribbon>
  </Space>
);

export default App;

커스텀 시맨틱 DOM 스타일링

classNames와 styles에 객체/함수를 전달해 Badge의 시맨틱 DOM 스타일을 커스터마이즈할 수 있어요.

import React from 'react';
import { Avatar, Badge, Card, Flex, Space } from 'antd';
import type { BadgeProps, GetProp } from 'antd';
import { createStaticStyles } from 'antd-style';
import type { RibbonProps } from 'antd/es/badge/Ribbon';

const badgeClassNames = createStaticStyles(({ css }) => ({
  indicator: css`
    font-size: 10px;
  `,
}));

const ribbonClassNames = createStaticStyles(({ css }) => ({
  root: css`
    width: 400px;
    border: 1px solid #d9d9d9;
    border-radius: 10px;
  `,
}));

const badgeStyles: BadgeProps['styles'] = {
  root: {
    borderRadius: 8,
  },
};

const ribbonStyles: RibbonProps['styles'] = {
  indicator: {
    boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
  },
};

const badgeStylesFn: BadgeProps['styles'] = (info): GetProp<RibbonProps, 'styles', 'Return'> => {
  if (info.props.size === 'medium') {
    return {
      indicator: {
        fontSize: 14,
        backgroundColor: '#696FC7',
      },
    };
  }
  return {};
};

const ribbonStylesFn: RibbonProps['styles'] = (info): GetProp<RibbonProps, 'styles', 'Return'> => {
  if (info.props.color === '#696FC7') {
    return {
      content: {
        fontWeight: 'bold',
      },
      indicator: {
        boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
      },
    };
  }
  return {};
};

const App: React.FC = () => {
  return (
    <Space size="large" vertical>
      <Flex gap="medium">
        <Badge size="small" count={5} classNames={badgeClassNames} styles={badgeStyles}>
          <Avatar shape="square" size="large" />
        </Badge>
        <Badge count={5} classNames={badgeClassNames} styles={badgeStylesFn}>
          <Avatar shape="square" size="large" />
        </Badge>
      </Flex>
      <Flex vertical gap="medium">
        <Badge.Ribbon text="Custom Ribbon" classNames={ribbonClassNames} styles={ribbonStyles}>
          <Card title="Card with custom ribbon" size="small">
            This card has a customized ribbon with semantic classNames and styles.
          </Card>
        </Badge.Ribbon>
        <Badge.Ribbon
          text="Custom Ribbon"
          color="#696FC7"
          classNames={ribbonClassNames}
          styles={ribbonStylesFn}
        >
          <Card title="Card with custom ribbon" size="small">
            This card has a customized ribbon with semantic classNames and styles.
          </Card>
        </Badge.Ribbon>
      </Flex>
    </Space>
  );
};

export default App;

API

공통 props 참고: Common props

Badge

속성 설명 타입 기본값 버전 전역 설정
color Badge 점 색 커스터마이즈 string - ×
count 배지에 표시할 숫자 ReactNode - ×
classNames 컴포넌트 내부 각 시맨틱 구조의 클래스 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> - 5.7.0
dot count 대신 빨간 점 표시 여부 boolean false ×
offset 배지 점의 오프셋 설정 [number, number] - ×
overflowCount 표시할 최대 개수 number 99 ×
showZero count가 0일 때 배지 표시 여부 boolean false ×
size count가 설정되면 size가 배지 크기를 결정 medium | small - - ×
status Badge를 상태 점으로 설정 success | processing | default | error | warning - ×
styles 컴포넌트 내부 각 시맨틱 구조의 인라인 스타일 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> - 5.7.0
text status가 설정되면 text가 상태 dot의 표시 텍스트를 결정 ReactNode - ×
title 배지에 마우스를 올렸을 때 표시할 텍스트. 네이티브 툴팁을 제거하려면 null 또는 false로 설정 string | null | false - 6.5.0 ×

Badge.Ribbon

속성 설명 타입 기본값 버전 전역 설정
classNames 컴포넌트 내부 각 시맨틱 구조의 클래스 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> - 6.0.0
color Ribbon 색 커스터마이즈 string - ×
placement Ribbon의 위치, start와 end는 텍스트 방향(RTL 또는 LTR)을 따름 start | end end ×
styles 컴포넌트 내부 각 시맨틱 구조의 인라인 스타일 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> - 6.0.0
text Ribbon 내부 콘텐츠 ReactNode - ×

시맨틱 DOM (Semantic DOM)

Badge

https://ant.design/components/badge/semantic.md

Badge.Ribbon

https://ant.design/components/badge/semantic_ribbon.md

디자인 토큰 (Design Token)

컴포넌트 토큰 (Badge)

토큰 이름 설명 타입 기본값
dotSize 점 배지 크기 number 6
indicatorHeight 배지 높이 string | number 20
indicatorHeightSM 작은 배지 높이 string | number 14
indicatorZIndex 배지의 z-index string | number auto
paddingInline 여러 단어 배지의 인라인 패딩 string | number 8
statusSize 상태 배지 크기 number 6
textFontSize 배지 텍스트의 폰트 크기 number 12
textFontSizeSM 작은 배지 텍스트의 폰트 크기 number 12
textFontWeight 배지 텍스트의 폰트 두께 string | number normal

전역 토큰 (Global Token)

토큰 이름 설명 타입 기본값
colorBorderBg 요소의 배경 테두리 색 제어. string
colorError 작업 실패의 시각 요소를 나타내는 데 사용. 예: 오류 Button, 오류 Result 컴포넌트 등 string
colorErrorHover 오류 색의 호버 상태. string
colorInfo 정보 토큰 시퀀스. Alert, Tag, Progress 등 컴포넌트가 이 map 토큰 사용 string
colorInfoTextHover 정보 색의 텍스트 색 호버 상태. string
colorSuccess 작업 성공의 토큰 시퀀스. Result, Progress 등 컴포넌트가 이 map 토큰 사용 string
colorText W3C 표준을 준수하는 기본 텍스트 색. 가장 어두운 중성색이기도 함. string
colorTextLightSolid 배경색이 있는 텍스트의 하이라이트 색 제어. 예: Primary Button의 텍스트 string
colorTextPlaceholder placeholder 텍스트 색 제어. string
colorWarning 경고 map 토큰. Notification, Alert 등이 사용. Alert 또는 Control 컴포넌트(Input)도 사용 string
fontFamily 시스템 기본 인터페이스 폰트와 화면 표시에 적합한 대체 폰트 라이브러리 세트 제공 string
fontSize 디자인 시스템에서 가장 널리 사용되는 폰트 크기. number
lineHeight 텍스트의 줄 높이. number
lineWidth 기본 컴포넌트의 테두리 너비 number
marginXS 요소의 여백 제어, 작은 크기. number
motionDurationMid 모션 속도, 중간 속도. 중간 요소 애니메이션 상호작용에 사용. string
motionDurationSlow 모션 속도, 느린 속도. 대형 요소 애니메이션 상호작용에 사용. string
motionEaseOutBack 프리셋 모션 곡선. string

더 알아보기 (Learn more)