Photonix

Bar Chart

Categorical data comparison using BarChart.

Preview

Usage
"use client";

import { Bar, BarChart, CartesianGrid, ChartContainer, ChartTooltip, XAxis, YAxis, type ChartConfig } from '@photonix/ultimate';

const data = [
    { month: 'Jan', users: 320 },
    { month: 'Feb', users: 460 },
    { month: 'Mar', users: 390 },
    { month: 'Apr', users: 520 },
];

const config: ChartConfig = {
    users: { label: 'Users', color: 'var(--chart-2)' },
};

export default function BarChartBasicExample() {
    return (
        <ChartContainer config={config} minHeight={260}>
            <BarChart data={data} margin={{ top: 20, right: 20, left: -20, bottom: 0 }}>
                <CartesianGrid strokeDasharray="3 3" vertical={false} />
                <XAxis dataKey="month" tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <YAxis tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <ChartTooltip />
                <Bar dataKey="users" fill="var(--color-users)" radius={[6, 6, 0, 0]} />
            </BarChart>
        </ChartContainer>
    );
}

Component API

BarChart

Prop
Type
Default
Description
data
any[]
-
The source data array.
children
ReactElement
-
Chart components (Bar, XAxis, Tooltip, Legend, etc).

Bar

Prop
Type
Default
Description
dataKey
string
-
The key of data to be displayed.
fill
string
-
The color of the bar.
radius
number | array
0
The radius of the bar.

Variants

Grouped bars

Compare multiple values inside each category.

Grouped bars
"use client";

import { Bar, BarChart, CartesianGrid, ChartContainer, ChartLegend, ChartTooltip, XAxis, YAxis, type ChartConfig } from '@photonix/ultimate';

const data = [
    { day: 'Mon', revenue: 420, cost: 240 },
    { day: 'Tue', revenue: 360, cost: 210 },
    { day: 'Wed', revenue: 510, cost: 280 },
    { day: 'Thu', revenue: 480, cost: 260 },
];

const config: ChartConfig = {
    revenue: { label: 'Revenue', color: 'var(--chart-2)' },
    cost: { label: 'Cost', color: 'var(--chart-3)' },
};

export default function BarChartGroupedExample() {
    return (
        <ChartContainer config={config} minHeight={260}>
            <BarChart data={data} margin={{ top: 20, right: 20, left: -20, bottom: 0 }}>
                <CartesianGrid strokeDasharray="3 3" vertical={false} />
                <XAxis dataKey="day" tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <YAxis tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <ChartTooltip />
                <ChartLegend />
                <Bar dataKey="revenue" fill="var(--color-revenue)" radius={[6, 6, 0, 0]} />
                <Bar dataKey="cost" fill="var(--color-cost)" radius={[6, 6, 0, 0]} />
            </BarChart>
        </ChartContainer>
    );
}

Horizontal bars

Switch the layout for ranking-style comparisons.

Horizontal bars
"use client";

import { Bar, BarChart, CartesianGrid, ChartContainer, ChartTooltip, XAxis, YAxis, type ChartConfig } from '@photonix/ultimate';

const data = [
    { team: 'Design', tasks: 38 },
    { team: 'Product', tasks: 52 },
    { team: 'Engineering', tasks: 74 },
    { team: 'Support', tasks: 29 },
];

const config: ChartConfig = {
    tasks: { label: 'Tasks', color: 'var(--chart-1)' },
};

export default function BarChartHorizontalExample() {
    return (
        <ChartContainer config={config} minHeight={260}>
            <BarChart data={data} layout="vertical" margin={{ top: 20, right: 20, left: 12, bottom: 0 }}>
                <CartesianGrid strokeDasharray="3 3" horizontal={false} />
                <XAxis type="number" tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <YAxis type="category" dataKey="team" tickLine={false} axisLine={false} width={88} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <ChartTooltip />
                <Bar dataKey="tasks" fill="var(--color-tasks)" radius={[0, 6, 6, 0]} />
            </BarChart>
        </ChartContainer>
    );
}

Custom width & spacing

Control the thickness of the bars and spacing between groups using barSize, barGap, and barCategoryGap.

Custom width & spacing
"use client";

import { Bar, BarChart, CartesianGrid, ChartContainer, ChartLegend, ChartTooltip, XAxis, YAxis, type ChartConfig } from '@photonix/ultimate';

const data = [
    { name: 'Mon', active: 400, inactive: 240 },
    { name: 'Tue', active: 300, inactive: 139 },
    { name: 'Wed', active: 200, inactive: 980 },
    { name: 'Thu', active: 278, inactive: 390 },
    { name: 'Fri', active: 189, inactive: 480 },
    { name: 'Sat', active: 239, inactive: 380 },
    { name: 'Sun', active: 349, inactive: 430 },
];

const config: ChartConfig = {
    active: { label: 'Active Users', color: 'var(--chart-1)' },
    inactive: { label: 'Inactive Users', color: 'var(--chart-2)' },
};

export default function BarChartCustomSizeExample() {
    return (
        <ChartContainer config={config} minHeight={260}>
            <BarChart 
                data={data} 
                margin={{ top: 20, right: 20, left: -20, bottom: 0 }}
                barGap={6}              // Spacing between bars inside the same category group
                barCategoryGap="35%"    // Spacing between different category groups (relative to width)
            >
                <CartesianGrid strokeDasharray="3 3" vertical={false} />
                <XAxis dataKey="name" tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <YAxis tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <ChartTooltip />
                <ChartLegend />
                <Bar dataKey="active" fill="var(--color-active)" radius={[4, 4, 0, 0]} barSize={12} />
                <Bar dataKey="inactive" fill="var(--color-inactive)" radius={[4, 4, 0, 0]} barSize={12} />
            </BarChart>
        </ChartContainer>
    );
}

Interactive selection

Click on a bar to select it. Unselected bars will render in gray with a diagonal hatching pattern.

Interactive selection
"use client";

import React, { useState } from 'react';
import { Bar, BarChart, CartesianGrid, ChartContainer, ChartTooltip, XAxis, YAxis, Cell, type ChartConfig } from '@photonix/ultimate';

const data = [
    { month: 'Jan', users: 320000, fill: 'var(--color-users)' },
    { month: 'Feb', users: 460000, fill: 'var(--color-users)' },
    { month: 'Mar', users: 390000, fill: 'var(--color-users)' },
    { month: 'Apr', users: 520000, fill: 'var(--color-users)' },
    { month: 'May', users: 300000, fill: 'var(--color-users)' },
    { month: 'Jun', users: 410000, fill: 'var(--color-users)' },
];

const config: ChartConfig = {
    users: { label: 'Users', color: 'var(--chart-2)' },
};

const formatCompactNumber = (value: number) => {
    if (value >= 1e9) {
        return `${(value / 1e9).toFixed(1).replace(/\.0$/, '')}B`;
    }
    if (value >= 1e6) {
        return `${(value / 1e6).toFixed(1).replace(/\.0$/, '')}M`;
    }
    if (value >= 1e3) {
        return `${(value / 1e3).toFixed(1).replace(/\.0$/, '')}K`;
    }
    return value.toString();
};

export default function BarChartInteractiveExample() {
    const [activeIndex, setActiveIndex] = useState<number | null>(null);
    const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);

    const handleClick = (index: number) => {
        setActiveIndex((prev) => (prev === index ? null : index));
    };

    return (
        <ChartContainer config={config} minHeight={260}>
            <BarChart data={data} margin={{ top: 20, right: 20, left: -20, bottom: 0 }}>
                <defs>
                    <pattern 
                        id="diagonalHatch" 
                        width="8" 
                        height="8" 
                        patternUnits="userSpaceOnUse" 
                        patternTransform="rotate(45)"
                    >
                        {/* Gray background for unselected bar */}
                        <rect width="8" height="8" fill="var(--background-neutral-secondary)" />
                        {/* Diagonal lines */}
                        <line 
                            x1="0" 
                            y1="0" 
                            x2="0" 
                            y2="8" 
                            stroke="var(--border-neutral-tertiary)" 
                            strokeWidth="2" 
                        />
                    </pattern>
                </defs>
                <CartesianGrid strokeDasharray="3 3" vertical={false} />
                <XAxis dataKey="month" tickLine={false} axisLine={false} tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} />
                <YAxis 
                    tickLine={false} 
                    axisLine={false} 
                    tick={{ fill: 'var(--text-neutral-secondary)', fontSize: 12 }} 
                    tickFormatter={formatCompactNumber}
                />
                <ChartTooltip />
                <Bar dataKey="users" fill="var(--color-users)" radius={[6, 6, 0, 0]}>
                    {data.map((entry, index) => {
                        const isSelected = activeIndex === index;
                        const isHovered = hoveredIndex === index;
                        return (
                            <Cell
                                key={`cell-${index}`}
                                cursor="pointer"
                                onMouseEnter={() => setHoveredIndex(index)}
                                onMouseLeave={() => setHoveredIndex(null)}
                                onClick={() => handleClick(index)}
                                fill={(isSelected || isHovered) ? 'var(--color-users)' : 'url(#diagonalHatch)'}
                            />
                        );
                    })}
                </Bar>
            </BarChart>
        </ChartContainer>
    );
}

On this page

Preview
Component API
Variants
Grouped bars
Horizontal bars
Custom width & spacing
Interactive selection
Photonix UI - React Components, Templates & Figma Design System