BarChart

Data Visualization

visx 기반 막대 차트.

Usage

카테고리별 수치를 막대 길이로 비교하거나 여러 시리즈를 그룹·누적으로 볼 때 사용한다.

import

import

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

예제를 복사해 쓸 때 필요한 준비

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

API Reference

BarChart Props

Prop

Type

Default

data
필수

TDatum[]

지정 안 함

xKey
필수

string

지정 안 함

yKeys
필수

(keyof TDatum & string)[]

지정 안 함

children

ReactNode

지정 안 함

className

string

지정 안 함

colors

string[]

지정 안 함

groupMode

"stacked" | "grouped"

grouped

labels

Partial<Record<keyof TDatum & string, string>>

지정 안 함

layout

"horizontal" | "vertical"

vertical

legendPosition

"bottom" | "left" | "right" | "top"

bottom

margin

Partial<ChartMargin>

지정 안 함

paints

ChartPaint[]

지정 안 함

showGrid

boolean

true

showLegend

boolean

false

showTooltip

boolean

false

showValueText

boolean

false

showXAxis

boolean

true

showYAxis

boolean

true

xAxisProps

BarChartAxisProps

지정 안 함

yAxisProps

BarChartAxisProps

지정 안 함

예제

나란히 비교 vs 누적 합계

groupMode 로 시리즈를 나란히 비교할지, 쌓아서 전체 규모를 함께 볼지 고른다.

코드

'use client';

import { BarChart } from '@mildang/design-system/Chart';
import { Text } from '@mildang/design-system/Text';
import { HStack, VStack } from '@mildang/styled-system/jsx';
import { css } from '@mildang/styled-system/css';

/**
 * yKeys 가 2개 이상일 때 `groupMode` 로 나란히 비교할지(grouped) 값을 누적해 전체 규모를
 * 함께 볼지(stacked) 고른다. 데이터는 그대로 두고 이 prop 하나만 바뀐다.
 */
const data = [
  { subject: '국어', male: 72, female: 78 },
  { subject: '수학', male: 64, female: 69 },
  { subject: '영어', male: 81, female: 75 },
];

const labels = { male: '남학생', female: '여학생' };
const frame = css({ width: '100%', height: '[220px]' });

export default function BarChartModesExample() {
  return (
    <HStack gap="6" alignItems="flex-start" flexWrap="wrap">
      <VStack gap="2" alignItems="stretch" flex="1" minWidth="[220px]">
        <Text variant="caption-md" color="neutral.text.low">
          grouped — 성별을 나란히 비교
        </Text>
        <div className={frame}>
          <BarChart
            data={data}
            xKey="subject"
            yKeys={['male', 'female']}
            labels={labels}
            groupMode="grouped"
            showLegend
          />
        </div>
      </VStack>
      <VStack gap="2" alignItems="stretch" flex="1" minWidth="[220px]">
        <Text variant="caption-md" color="neutral.text.low">
          stacked — 과목별 합계를 함께 확인
        </Text>
        <div className={frame}>
          <BarChart
            data={data}
            xKey="subject"
            yKeys={['male', 'female']}
            labels={labels}
            groupMode="stacked"
            showLegend
          />
        </div>
      </VStack>
    </HStack>
  );
}

단일 시리즈

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartSingleExample = () => <BarChart data={monthlyData} xKey="month" yKeys={['revenue']} showLegend />;

export default BarChartSingleExample;

Hover Tooltip

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartHoverTooltipExample = () => (
    <BarChart
      data={monthlyData}
      xKey="month"
      yKeys={['revenue']}
      labels={{ revenue: '매출' }}
      showTooltip
    />
  );

export default BarChartHoverTooltipExample;

그룹 막대

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartGroupedExample = () => (
    <BarChart
      data={monthlyData}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="grouped"
      labels={{ revenue: '매출', cost: '비용' }}
      showLegend
    />
  );

export default BarChartGroupedExample;

패턴 채우기

import { BarChart } from '@mildang/design-system/Chart';
import { token } from '@mildang/styled-system/tokens';
import { createElement } from 'react';

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartPatternFillExample = () => (
    <BarChart
      data={monthlyData}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="grouped"
      labels={{ revenue: '매출', cost: '비용' }}
      paints={[
        {
          type: 'pattern',
          patternId: 'bar-chart-revenue-lines',
          legendFill: token('colors.info.surface.base'),
          stroke: token('colors.info.border.highest'),
          definition: createElement(
            'pattern',
            {
              id: 'bar-chart-revenue-lines',
              width: 8,
              height: 8,
              patternUnits: 'userSpaceOnUse',
            },
            createElement('rect', {
              width: 8,
              height: 8,
              fill: token('colors.info.surface.base'),
            }),
            createElement('path', {
              d: 'M-2,2 l4,-4 M0,8 l8,-8 M6,10 l4,-4',
              stroke: token('colors.info.border.highest'),
              strokeWidth: 1.5,
            })
          ),
        },
        {
          type: 'solid',
          fill: token('colors.warning.surface.high'),
          stroke: token('colors.warning.border.highest'),
        },
      ]}
      showLegend
      showTooltip
    />
  );

export default BarChartPatternFillExample;

스택 막대

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartStackedExample = () => (
    <BarChart
      data={monthlyData}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="stacked"
      labels={{ revenue: '매출', cost: '비용' }}
      showLegend
      showTooltip
    />
  );

export default BarChartStackedExample;

가로 막대

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartHorizontalExample = () => <BarChart data={monthlyData} xKey="month" yKeys={['revenue']} layout="horizontal" />;

export default BarChartHorizontalExample;

값 라벨 (단일)

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartSingleWithLabelsExample = () => <BarChart data={monthlyData} xKey="month" yKeys={['revenue']} showValueText />;

export default BarChartSingleWithLabelsExample;

값 라벨 (그룹)

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartGroupedWithLabelsExample = () => (
    <BarChart
      data={monthlyData}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="grouped"
      labels={{ revenue: '매출', cost: '비용' }}
      showValueText
    />
  );

export default BarChartGroupedWithLabelsExample;

값 라벨 (스택 합계)

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartStackedWithLabelsExample = () => (
    <BarChart data={monthlyData} xKey="month" yKeys={['revenue', 'cost']} groupMode="stacked" showValueText />
  );

export default BarChartStackedWithLabelsExample;

값 라벨 (가로)

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartHorizontalWithLabelsExample = () => (
    <BarChart data={monthlyData} xKey="month" yKeys={['revenue']} layout="horizontal" showValueText />
  );

export default BarChartHorizontalWithLabelsExample;

값이 0인 경우

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

const zeroData = [
  { month: '1월', revenue: 4200, cost: 0 },
  { month: '2월', revenue: 0, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 0 },
  { month: '4월', revenue: 0, cost: 0 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 0, cost: 3800 },
];

const BarChartWithZeroValuesExample = () => (
    <BarChart
      data={zeroData}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="grouped"
      labels={{ revenue: '매출', cost: '비용' }}
      showLegend
      showTooltip
      showValueText
    />
  );

export default BarChartWithZeroValuesExample;

전체 0

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartAllZeroExample = () => (
    <BarChart
      data={monthlyData.map((d) => ({ ...d, revenue: 0, cost: 0 }))}
      xKey="month"
      yKeys={['revenue', 'cost']}
      groupMode="grouped"
      labels={{ revenue: '매출', cost: '비용' }}
      showLegend
    />
  );

export default BarChartAllZeroExample;

반응형 (너비 자동 조정)

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartResponsiveExample = () => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 32, width: '100%' }}>
      {([280, 480, 720] as const).map((w) => (
        <div key={w} style={{ width: w }}>
          <div style={{ marginBottom: 4, fontSize: 11, color: '#888' }}>{w}px</div>
          <div style={{ width: w, height: 240 }}>
            <BarChart
              data={monthlyData}
              xKey="month"
              yKeys={['revenue', 'cost']}
              groupMode="grouped"
              labels={{ revenue: '매출', cost: '비용' }}
              showLegend
            />
          </div>
        </div>
      ))}
    </div>
  );

export default BarChartResponsiveExample;

Compound 패턴 — 커스텀 라벨 포맷

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

const monthlyData = [
  { month: '1월', revenue: 4200, cost: 2800 },
  { month: '2월', revenue: 3800, cost: 2500 },
  { month: '3월', revenue: 5100, cost: 3200 },
  { month: '4월', revenue: 4600, cost: 3000 },
  { month: '5월', revenue: 5800, cost: 3500 },
  { month: '6월', revenue: 6200, cost: 3800 },
];

const BarChartCompoundWithCustomLabelsExample = () => (
    <BarChart data={monthlyData} xKey="month" yKeys={['revenue', 'cost']} groupMode="grouped">
      <BarChart.Grid />
      <BarChart.XAxis hideTicks hideAxisLine />
      <BarChart.YAxis hideTicks hideAxisLine />
      <BarChart.Bars />
      <BarChart.ValueText format={(v: number) => `${(v / 1000).toFixed(1)}k`} />
    </BarChart>
  );

export default BarChartCompoundWithCustomLabelsExample;