# Bar Chart Negative

Monthly cash flow bars that turn green above zero and red below it, with a zero baseline.

Bar Chart Negative is an open-source chart from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.

Source: https://ui.suiss.app/docs/charts/bar-chart-negative

**React**

**Example**

```tsx title="components/charts/bar-chart-negative.tsx"
"use client"

import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  ReferenceLine,
  XAxis,
} from "recharts"

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", flow: 42 },
  { month: "February", flow: -18 },
  { month: "March", flow: 26 },
  { month: "April", flow: 55 },
  { month: "May", flow: -31 },
  { month: "June", flow: 12 },
  { month: "July", flow: 38 },
  { month: "August", flow: -9 },
  { month: "September", flow: 47 },
  { month: "October", flow: 21 },
  { month: "November", flow: -14 },
  { month: "December", flow: 60 },
]

const chartConfig = {
  flow: { label: "Cash flow" },
} satisfies ChartConfig

export function BarChartNegative() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Positive and negative</CardTitle>
        <CardDescription>Monthly cash flow · thousands</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-48 w-full"
        >
          <BarChart
            accessibilityLayer
            data={chartData}
            margin={{ top: 10, right: 4, left: 4, bottom: 0 }}
          >
            <CartesianGrid vertical={false} strokeDasharray="2 4" />
            <XAxis
              dataKey="month"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              interval={1}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ReferenceLine y={0} stroke="var(--input)" />
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideIndicator />}
            />
            <Bar dataKey="flow" radius={4} maxBarSize={18}>
              {chartData.map((item) => (
                <Cell
                  key={item.month}
                  fill={
                    item.flow >= 0
                      ? "var(--color-green-500)"
                      : "var(--color-red-500)"
                  }
                />
              ))}
            </Bar>
          </BarChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

Monthly cash flow where bars rise green above a zero line and drop red below it. Use it for any value that can be negative, such as profit, net change or deltas against a target.

## Installation

### CLI

```bash title="Terminal"
npx shadcn@latest add @esuiss/bar-chart-negative
```

Works in any project with a `components.json`. See [Installation](https://ui.suiss.app/docs/installation#add-components) for the one-line registry setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add charts bar-chart-negative
```

### Manual

1. Install the dependencies:

```bash title="Terminal"
npm install recharts
```

2. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

3. Copy the source into `components/charts/bar-chart-negative.tsx`:

```tsx title="components/charts/bar-chart-negative.tsx"
"use client"

import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  ReferenceLine,
  XAxis,
} from "recharts"

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", flow: 42 },
  { month: "February", flow: -18 },
  { month: "March", flow: 26 },
  { month: "April", flow: 55 },
  { month: "May", flow: -31 },
  { month: "June", flow: 12 },
  { month: "July", flow: 38 },
  { month: "August", flow: -9 },
  { month: "September", flow: 47 },
  { month: "October", flow: 21 },
  { month: "November", flow: -14 },
  { month: "December", flow: 60 },
]

const chartConfig = {
  flow: { label: "Cash flow" },
} satisfies ChartConfig

export function BarChartNegative() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Positive and negative</CardTitle>
        <CardDescription>Monthly cash flow · thousands</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-48 w-full"
        >
          <BarChart
            accessibilityLayer
            data={chartData}
            margin={{ top: 10, right: 4, left: 4, bottom: 0 }}
          >
            <CartesianGrid vertical={false} strokeDasharray="2 4" />
            <XAxis
              dataKey="month"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              interval={1}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ReferenceLine y={0} stroke="var(--input)" />
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideIndicator />}
            />
            <Bar dataKey="flow" radius={4} maxBarSize={18}>
              {chartData.map((item) => (
                <Cell
                  key={item.month}
                  fill={
                    item.flow >= 0
                      ? "var(--color-green-500)"
                      : "var(--color-red-500)"
                  }
                />
              ))}
            </Bar>
          </BarChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

4. Update the import paths to match your project.

## Usage

```tsx
import { BarChartNegative } from "@/components/charts/bar-chart-negative"
```

```tsx
<BarChartNegative />
```

Replace `chartData` with your values and rename `flow` in the data, the bar and `chartConfig`. The color for each bar is chosen per `Cell` based on its sign, so change the two colors there. Set `interval` on the axis to show more or fewer month labels.

## Notes

Because colors are set per bar instead of in the config, the tooltip has no color swatch, and green and red alone carry the sign; keep the zero line so the direction is clear without color. Focus the chart and use the arrow keys to move between months.

**React Native, SwiftUI, Jetpack Compose**

![Preview](https://ui.suiss.app/previews/charts-bar--negative.light.webp)

```tsx title="uniwind/components/charts/bar-chart-negative.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  ReferenceLine,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", flow: 42 },
  { month: "February", flow: -18 },
  { month: "March", flow: 26 },
  { month: "April", flow: 55 },
  { month: "May", flow: -31 },
  { month: "June", flow: 12 },
  { month: "July", flow: 38 },
  { month: "August", flow: -9 },
  { month: "September", flow: 47 },
  { month: "October", flow: 21 },
  { month: "November", flow: -14 },
  { month: "December", flow: 60 },
]

const chartConfig = {
  flow: { label: "Cash flow" },
} satisfies ChartConfig

export function BarChartNegative() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Positive and negative</CardTitle>
        <CardDescription>Monthly cash flow · thousands</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Positive and negative"
          className="h-48 w-full"
        >
          <BarChart
            data={chartData}
            margin={{ top: 10, right: 4, left: 4, bottom: 0 }}
          >
            <CartesianGrid vertical={false} strokeDasharray="2 4" />
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={1}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ReferenceLine y={0} stroke="input" />
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideIndicator />}
            />
            <Bar dataKey="flow" radius={4} maxBarSize={18}>
              {chartData.map((item) => (
                <Cell
                  key={item.month}
                  fill={item.flow >= 0 ? "green-500" : "red-500"}
                />
              ))}
            </Bar>
          </BarChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

```swift title="swift/Charts/BarChartNegative.swift"
import Charts
import SwiftUI

private let chartData: [(month: String, flow: Double)] = [
  ("January", 42), ("February", -18), ("March", 26), ("April", 55), ("May", -31), ("June", 12),
  ("July", 38), ("August", -9), ("September", 47), ("October", 21), ("November", -14), ("December", 60),
]

private let chartConfig: ChartConfig = [
  "flow": .init("Cash flow"),
]

public struct BarChartNegative: View {
  @State private var selection: Int?

  public init() {}

  public var body: some View {
    Card(.filled, size: .sm) {
      CardHeader("Positive and negative", description: "Monthly cash flow · thousands")
      CardContent {
        ChartContainer(config: chartConfig) {
          ChartAnimator(animationDuration: 400) { progress in
            Chart {
              RuleMark(y: .value("Zero", 0))
                .lineStyle(StrokeStyle(lineWidth: 1))
                .foregroundStyle(EsuissColor.input)
              ForEach(chartData.indices, id: \.self) { index in
                BarMark(x: .value("Month", chartData[index].month), y: .value("Flow", chartData[index].flow * progress), width: .fixed(18))
                  .clipShape(RoundedRectangle(cornerRadius: 4, style: .continuous))
                  .foregroundStyle(chartData[index].flow >= 0 ? Palette.green500 : Palette.red500)
                ChartAnchorMark(x: .value("Month", chartData[index].month), y: .value("Flow", chartData[index].flow))
              }
            }
            .chartXAxis { ChartAxis.x(values: chartData.indices.filter { $0.isMultiple(of: 2) }.map { chartData[$0].month }) { String($0.prefix(3)) } }
            .chartYAxis { ChartAxis.grid() }
            .chartTooltip(
              x: chartData.map(\.month),
              selection: $selection,
              cursor: false,
              accessibilityLabel: "Positive and negative",
              items: { [ChartTooltipItem("flow", value: chartData[$0].flow)] }
            ) { payload in
              ChartTooltipContent(payload, hideIndicator: true)
            }
          }
        }
        .frame(height: 192)
      }
    }
  }
}
```

```kt title="kotlin/charts/BarChartNegative.kt"
package com.esuiss.ui.charts

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.esuiss.ui.components.BarChart
import com.esuiss.ui.components.Card
import com.esuiss.ui.components.CardContent
import com.esuiss.ui.components.CardHeader
import com.esuiss.ui.components.CardSize
import com.esuiss.ui.components.CardVariant
import com.esuiss.ui.components.ChartCell
import com.esuiss.ui.components.ChartConfig
import com.esuiss.ui.components.ChartConfigItem
import com.esuiss.ui.components.ChartContainer
import com.esuiss.ui.components.ChartMargin
import com.esuiss.ui.components.ChartRadius
import com.esuiss.ui.components.ChartTooltipContent
import com.esuiss.ui.theme.EsuissTheme
import com.esuiss.ui.theme.Palette

private class CashFlow(val month: String, val flow: Double)

private val chartData = listOf(
    CashFlow("January", 42.0),
    CashFlow("February", -18.0),
    CashFlow("March", 26.0),
    CashFlow("April", 55.0),
    CashFlow("May", -31.0),
    CashFlow("June", 12.0),
    CashFlow("July", 38.0),
    CashFlow("August", -9.0),
    CashFlow("September", 47.0),
    CashFlow("October", 21.0),
    CashFlow("November", -14.0),
    CashFlow("December", 60.0),
)

private val chartConfig = ChartConfig(
    "flow" to ChartConfigItem("Cash flow"),
)

@Composable
fun BarChartNegative(modifier: Modifier = Modifier) {
    val colors = EsuissTheme.colors
    Card(modifier, variant = CardVariant.Filled, size = CardSize.Sm) {
        CardHeader("Positive and negative", description = "Monthly cash flow · thousands")
        CardContent {
            ChartContainer(
                chartConfig,
                Modifier
                    .fillMaxWidth()
                    .height(192.dp),
            ) {
                BarChart(
                    chartData,
                    margin = ChartMargin(top = 10.dp, right = 4.dp, bottom = 0.dp, left = 4.dp),
                    accessibilityLabel = "Positive and negative",
                ) {
                    CartesianGrid(strokeDasharray = listOf(2f, 4f))
                    XAxis(label = { it.month }, tickMargin = 8.dp, interval = 1, tickFormatter = { it.take(3) })
                    ReferenceLine(0.0, stroke = colors.input)
                    ChartTooltip(cursor = null) { ChartTooltipContent(hideIndicator = true) }
                    Bar(
                        "flow",
                        value = { it.flow },
                        radius = ChartRadius(4.dp),
                        maxBarSize = 18.dp,
                        cells = { index -> ChartCell(if (chartData[index].flow >= 0) Palette.green500 else Palette.red500) },
                    )
                }
            }
        }
    }
}
```

One bar per month, colored per value through a `Cell`: green when the flow is positive and red when it is negative. A `ReferenceLine` at zero anchors the bars, and the month axis shows every other label.

## Installation

**React Native**

```bash title="Terminal"
npx shadcn@latest add @esuiss-rn/bar-chart-negative
```

See [Installation](https://ui.suiss.app/docs/installation) for the `components.json` setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add bar-chart-negative
```

**SwiftUI**

```bash title="Terminal"
npx @esuiss/ui@latest add bar-chart-negative --platform swift
```

**Jetpack Compose**

```bash title="Terminal"
npx @esuiss/ui@latest add bar-chart-negative --platform kotlin
```

The CLI also adds what it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

### Manual

**React Native**

**Uniwind**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/bar-chart-negative.tsx`:

- `uniwind/components/charts/bar-chart-negative.tsx`: shown above

3. Update the import paths to match your project.

**NativeWind**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/bar-chart-negative.tsx`:

```tsx title="nativewind/components/charts/bar-chart-negative.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  ReferenceLine,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", flow: 42 },
  { month: "February", flow: -18 },
  { month: "March", flow: 26 },
  { month: "April", flow: 55 },
  { month: "May", flow: -31 },
  { month: "June", flow: 12 },
  { month: "July", flow: 38 },
  { month: "August", flow: -9 },
  { month: "September", flow: 47 },
  { month: "October", flow: 21 },
  { month: "November", flow: -14 },
  { month: "December", flow: 60 },
]

const chartConfig = {
  flow: { label: "Cash flow" },
} satisfies ChartConfig

export function BarChartNegative() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Positive and negative</CardTitle>
        <CardDescription>Monthly cash flow · thousands</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Positive and negative"
          className="h-48 w-full"
        >
          <BarChart
            data={chartData}
            margin={{ top: 10, right: 4, left: 4, bottom: 0 }}
          >
            <CartesianGrid vertical={false} strokeDasharray="2 4" />
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={1}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ReferenceLine y={0} stroke="input" />
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideIndicator />}
            />
            <Bar dataKey="flow" radius={4} maxBarSize={18}>
              {chartData.map((item) => (
                <Cell
                  key={item.month}
                  fill={item.flow >= 0 ? "green-500" : "red-500"}
                />
              ))}
            </Bar>
          </BarChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

3. Update the import paths to match your project.

**StyleSheet**

1. Add the pieces it builds on: [Card](https://ui.suiss.app/docs/components/card), [Chart](https://ui.suiss.app/docs/components/chart).

2. Copy the source into `components/charts/bar-chart-negative.tsx`:

```tsx title="stylesheet/components/charts/bar-chart-negative.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  ReferenceLine,
  XAxis,
} from "@/components/ui/chart"

const chartData = [
  { month: "January", flow: 42 },
  { month: "February", flow: -18 },
  { month: "March", flow: 26 },
  { month: "April", flow: 55 },
  { month: "May", flow: -31 },
  { month: "June", flow: 12 },
  { month: "July", flow: 38 },
  { month: "August", flow: -9 },
  { month: "September", flow: 47 },
  { month: "October", flow: 21 },
  { month: "November", flow: -14 },
  { month: "December", flow: 60 },
]

const chartConfig = {
  flow: { label: "Cash flow" },
} satisfies ChartConfig

export function BarChartNegative() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Positive and negative</CardTitle>
        <CardDescription>Monthly cash flow · thousands</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Positive and negative"
          style={{ height: 192 }}
        >
          <BarChart
            data={chartData}
            margin={{ top: 10, right: 4, left: 4, bottom: 0 }}
          >
            <CartesianGrid vertical={false} strokeDasharray="2 4" />
            <XAxis
              dataKey="month"
              tickMargin={8}
              interval={1}
              tickFormatter={(value: string) => value.slice(0, 3)}
            />
            <ReferenceLine y={0} stroke="input" />
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideIndicator />}
            />
            <Bar dataKey="flow" radius={4} maxBarSize={18}>
              {chartData.map((item) => (
                <Cell
                  key={item.month}
                  fill={item.flow >= 0 ? "green-500" : "red-500"}
                />
              ))}
            </Bar>
          </BarChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

3. Update the import paths to match your project.

**SwiftUI**

1. Target iOS 17 or later.

2. Copy the theme files every view uses:

- `swift/Theme/Theme.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Theme/Theme.swift)

- `swift/Theme/Tokens.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Theme/Tokens.swift)

3. Copy the source and every file it uses:

- `swift/Charts/BarChartNegative.swift`: shown above

- `swift/Components/Card.swift`: see [Card](https://ui.suiss.app/docs/components/card.md)

- `swift/Components/Chart.swift`: see [Chart](https://ui.suiss.app/docs/components/chart.md)

- `swift/Components/Haptics.swift`: see [Haptics](https://ui.suiss.app/docs/components/haptics.md)

- `swift/Components/Item.swift`: see [Item](https://ui.suiss.app/docs/components/item.md)

- `swift/Components/Separator.swift`: see [Separator](https://ui.suiss.app/docs/components/separator.md)

- `swift/Components/TextVariant.swift`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/swiftui/Sources/EsuissUI/Components/TextVariant.swift)

4. Add the files to your app target.

**Jetpack Compose**

1. Set `minSdk` to 24 or higher and add the dependencies:

```kotlin title="build.gradle.kts"
implementation(platform("androidx.compose:compose-bom:2026.09.00"))
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.ui:ui")
```

2. Copy the theme files every view uses:

- `kotlin/theme/Theme.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/theme/Theme.kt)

- `kotlin/theme/Tokens.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/theme/Tokens.kt)

3. Copy the source and every file it uses:

- `kotlin/charts/BarChartNegative.kt`: shown above

- `kotlin/components/Card.kt`: see [Card](https://ui.suiss.app/docs/components/card.md)

- `kotlin/components/Chart.kt`: see [Chart](https://ui.suiss.app/docs/components/chart.md)

- `kotlin/components/Content.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/components/Content.kt)

- `kotlin/components/FormSupport.kt`: [source](https://github.com/e-suiss/ui/blob/main/packages/mobile/kotlin/ui/src/main/kotlin/com/esuiss/ui/components/FormSupport.kt)

- `kotlin/components/Haptics.kt`: see [Haptics](https://ui.suiss.app/docs/components/haptics.md)

- `kotlin/components/Icon.kt`: see [Icon](https://ui.suiss.app/docs/components/icon.md)

4. Update the `com.esuiss.ui` package names to match your project.

## Usage

```tsx
import { BarChartNegative } from "@/components/charts/bar-chart-negative"
```

```tsx
<BarChartNegative />
```

Replace `chartData` with your months and signed `flow` values. Change the colors in the `Cell` `fill` expression. The component takes no props.

