# Pie Chart Active

A donut where one slice is enlarged and outlined with an outer arc to highlight it.

Pie Chart Active 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/pie-chart-active

**React**

**Example**

```tsx title="components/charts/pie-chart-active.tsx"
"use client"

import { Pie, PieChart, Sector } from "recharts"

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

const chartData = [
  { device: "phone", users: 275, fill: "var(--color-phone)" },
  { device: "laptop", users: 200, fill: "var(--color-laptop)" },
  { device: "tablet", users: 187, fill: "var(--color-tablet)" },
  { device: "watch", users: 173, fill: "var(--color-watch)" },
  { device: "other", users: 90, fill: "var(--color-other)" },
]

const chartConfig = {
  users: { label: "Users" },
  phone: { label: "Phone", color: "var(--chart-1)" },
  laptop: { label: "Laptop", color: "var(--chart-2)" },
  tablet: { label: "Tablet", color: "var(--chart-3)" },
  watch: { label: "Watch", color: "var(--chart-4)" },
  other: { label: "Other", color: "var(--chart-5)" },
} satisfies ChartConfig

const ACTIVE = 0

export function PieChartActive() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Highlighted slice</CardTitle>
        <CardDescription>The selected slice pops out</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-52 w-full"
        >
          <PieChart accessibilityLayer>
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideLabel nameKey="device" />}
            />
            <Pie
              data={chartData}
              dataKey="users"
              nameKey="device"
              innerRadius="50%"
              outerRadius="78%"
              strokeWidth={0}
              shape={(props, index) =>
                index === ACTIVE ? (
                  <g>
                    <Sector
                      {...props}
                      outerRadius={(props.outerRadius ?? 0) + 10}
                    />
                    <Sector
                      {...props}
                      innerRadius={(props.outerRadius ?? 0) + 13}
                      outerRadius={(props.outerRadius ?? 0) + 16}
                    />
                  </g>
                ) : (
                  <Sector {...props} />
                )
              }
            />
          </PieChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

A donut with one slice pulled outward and traced by a thin outer arc, so a single category stands out from the rest. Use it to call attention to the segment a page is about, such as the current plan or the user's own device.

## Installation

### CLI

```bash title="Terminal"
npx shadcn@latest add @esuiss/pie-chart-active
```

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 pie-chart-active
```

### 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/pie-chart-active.tsx`:

```tsx title="components/charts/pie-chart-active.tsx"
"use client"

import { Pie, PieChart, Sector } from "recharts"

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

const chartData = [
  { device: "phone", users: 275, fill: "var(--color-phone)" },
  { device: "laptop", users: 200, fill: "var(--color-laptop)" },
  { device: "tablet", users: 187, fill: "var(--color-tablet)" },
  { device: "watch", users: 173, fill: "var(--color-watch)" },
  { device: "other", users: 90, fill: "var(--color-other)" },
]

const chartConfig = {
  users: { label: "Users" },
  phone: { label: "Phone", color: "var(--chart-1)" },
  laptop: { label: "Laptop", color: "var(--chart-2)" },
  tablet: { label: "Tablet", color: "var(--chart-3)" },
  watch: { label: "Watch", color: "var(--chart-4)" },
  other: { label: "Other", color: "var(--chart-5)" },
} satisfies ChartConfig

const ACTIVE = 0

export function PieChartActive() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Highlighted slice</CardTitle>
        <CardDescription>The selected slice pops out</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          className="aspect-auto h-52 w-full"
        >
          <PieChart accessibilityLayer>
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideLabel nameKey="device" />}
            />
            <Pie
              data={chartData}
              dataKey="users"
              nameKey="device"
              innerRadius="50%"
              outerRadius="78%"
              strokeWidth={0}
              shape={(props, index) =>
                index === ACTIVE ? (
                  <g>
                    <Sector
                      {...props}
                      outerRadius={(props.outerRadius ?? 0) + 10}
                    />
                    <Sector
                      {...props}
                      innerRadius={(props.outerRadius ?? 0) + 13}
                      outerRadius={(props.outerRadius ?? 0) + 16}
                    />
                  </g>
                ) : (
                  <Sector {...props} />
                )
              }
            />
          </PieChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

4. Update the import paths to match your project.

## Usage

```tsx
import { PieChartActive } from "@/components/charts/pie-chart-active"
```

```tsx
<PieChartActive />
```

Replace `chartData` with your categories, giving each a value and a `fill` that points at its color in `chartConfig`. Set `ACTIVE` to the index of the slice you want to emphasize, or drive it from state if it should follow a selection.

## Notes

The highlight is fixed and does not follow hover; wire `ACTIVE` to state if you need that.

**React Native, SwiftUI, Jetpack Compose**

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

```tsx title="uniwind/components/charts/pie-chart-active.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  Pie,
  PieChart,
} from "@/components/ui/chart"

const chartData = [
  { device: "phone", users: 275 },
  { device: "laptop", users: 200 },
  { device: "tablet", users: 187 },
  { device: "watch", users: 173 },
  { device: "other", users: 90 },
]

const chartConfig = {
  users: { label: "Users" },
  phone: { label: "Phone", color: "chart-1" },
  laptop: { label: "Laptop", color: "chart-2" },
  tablet: { label: "Tablet", color: "chart-3" },
  watch: { label: "Watch", color: "chart-4" },
  other: { label: "Other", color: "chart-5" },
} satisfies ChartConfig

const ACTIVE = 0

export function PieChartActive() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Highlighted slice</CardTitle>
        <CardDescription>The selected slice pops out</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Highlighted slice"
          className="h-52 w-full"
        >
          <PieChart>
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideLabel nameKey="device" />}
            />
            <Pie
              data={chartData}
              dataKey="users"
              nameKey="device"
              innerRadius="50%"
              outerRadius="78%"
              strokeWidth={0}
              shape={(sector, index) =>
                index === ACTIVE
                  ? [
                      { ...sector, outerRadius: sector.outerRadius + 10 },
                      {
                        ...sector,
                        innerRadius: sector.outerRadius + 13,
                        outerRadius: sector.outerRadius + 16,
                      },
                    ]
                  : sector
              }
            />
          </PieChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}
```

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

private let chartData: [(device: String, users: Double)] = [
  ("phone", 275), ("laptop", 200), ("tablet", 187), ("watch", 173), ("other", 90),
]

private let chartConfig: ChartConfig = [
  "users": .init("Users"),
  "phone": .init("Phone", color: EsuissColor.chart1),
  "laptop": .init("Laptop", color: EsuissColor.chart2),
  "tablet": .init("Tablet", color: EsuissColor.chart3),
  "watch": .init("Watch", color: EsuissColor.chart4),
  "other": .init("Other", color: EsuissColor.chart5),
]

private let total = chartData.reduce(0) { $0 + $1.users }

public struct PieChartActive: View {
  @State private var selected = 0
  @Environment(\.accessibilityReduceMotion) private var reduceMotion

  public init() {}

  private var selection: Binding<Int?> {
    Binding(get: { selected }, set: { if let value = $0 { selected = value } })
  }

  public var body: some View {
    Card(.filled, size: .sm) {
      CardHeader("Highlighted slice", description: "The selected slice pops out")
      CardContent {
        ChartContainer(config: chartConfig) {
          ChartAnimator { progress in
            ZStack {
              GeometryReader { geometry in
                let radius = min(geometry.size.width, geometry.size.height) / 2
                let before = chartData.prefix(selected).reduce(0) { $0 + $1.users }
                ChartArc(
                  center: CGPoint(x: geometry.size.width / 2, y: geometry.size.height / 2),
                  radius: radius * 0.92,
                  thickness: radius * 0.029,
                  start: .degrees(before / total * 360 * progress),
                  end: .degrees((before + chartData[selected].users) / total * 360 * progress),
                  rounded: false
                )
                .fill(chartConfig.color(chartData[selected].device))
              }
              .accessibilityHidden(true)
              Chart {
                ForEach(chartData.indices, id: \.self) { index in
                  SectorMark(
                    angle: .value("Users", chartData[index].users * progress),
                    innerRadius: .ratio(0.5),
                    outerRadius: .ratio(index == selected ? 0.876 : 0.78)
                  )
                  .foregroundStyle(chartConfig.color(chartData[index].device))
                }
                ChartSectorRest(total: total, progress: progress)
              }
              .chartTooltip(
                angle: chartData.map(\.users),
                labels: chartData.map { chartConfig.label($0.device) },
                innerRadius: 0.5,
                outerRadius: 0.876,
                selection: selection,
                accessibilityLabel: "Highlighted slice",
                items: { [ChartTooltipItem(chartData[$0].device, value: chartData[$0].users)] }
              ) { payload in
                ChartTooltipContent(payload, hideLabel: true)
              }
            }
            .animation(reduceMotion ? nil : .easeOut(duration: 0.2), value: selected)
            .padding(5)
          }
        }
        .frame(height: 208)
      }
    }
  }
}
```

```kt title="kotlin/charts/PieChartActive.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.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.ChartConfig
import com.esuiss.ui.components.ChartConfigItem
import com.esuiss.ui.components.ChartContainer
import com.esuiss.ui.components.ChartTooltipContent
import com.esuiss.ui.components.PieChart
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import com.esuiss.ui.components.ChartRing
import com.esuiss.ui.components.ChartSector

private class PieActiveDeviceUsers(val device: String, val users: Double)

private val chartData = listOf(
    PieActiveDeviceUsers("phone", 275.0),
    PieActiveDeviceUsers("laptop", 200.0),
    PieActiveDeviceUsers("tablet", 187.0),
    PieActiveDeviceUsers("watch", 173.0),
    PieActiveDeviceUsers("other", 90.0),
)

private val chartConfig = ChartConfig(
    "users" to ChartConfigItem("Users"),
    "phone" to ChartConfigItem("Phone") { chart1 },
    "laptop" to ChartConfigItem("Laptop") { chart2 },
    "tablet" to ChartConfigItem("Tablet") { chart3 },
    "watch" to ChartConfigItem("Watch") { chart4 },
    "other" to ChartConfigItem("Other") { chart5 },
)

@Composable
fun PieChartActive(modifier: Modifier = Modifier) {
    var selected by remember { mutableIntStateOf(0) }
    Card(modifier, variant = CardVariant.Filled, size = CardSize.Sm) {
        CardHeader("Highlighted slice", description = "The selected slice pops out")
        CardContent {
            ChartContainer(
                chartConfig,
                Modifier
                    .fillMaxWidth()
                    .height(208.dp),
            ) {
                PieChart(
                    accessibilityLabel = "Highlighted slice",
                    selectedIndex = selected,
                    onSelectedIndexChange = { index -> if (index != null) selected = index },
                ) {
                    ChartTooltip { ChartTooltipContent(hideLabel = true) }
                    Pie(
                        chartData,
                        value = { it.users },
                        nameKey = { it.device },
                        innerRadius = 0.5f,
                        outerRadius = 0.78f,
                        strokeWidth = 0.dp,
                        sectors = { index -> if (index == selected) ChartSector(10.dp, ChartRing(3.dp, 3.dp)) else ChartSector() },
                    )
                }
            }
        }
    }
}
```

A `PieChart` donut inside a `Card`, showing users by device. `chartData` holds one record per device with a `users` count. The `Pie` `shape` callback enlarges the slice at index `ACTIVE` and adds a thin arc outside it. Pressing a slice shows a tooltip with its name and value.

## Installation

**React Native**

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

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 pie-chart-active
```

**SwiftUI**

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

**Jetpack Compose**

```bash title="Terminal"
npx @esuiss/ui@latest add pie-chart-active --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/pie-chart-active.tsx`:

- `uniwind/components/charts/pie-chart-active.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/pie-chart-active.tsx`:

```tsx title="nativewind/components/charts/pie-chart-active.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  Pie,
  PieChart,
} from "@/components/ui/chart"

const chartData = [
  { device: "phone", users: 275 },
  { device: "laptop", users: 200 },
  { device: "tablet", users: 187 },
  { device: "watch", users: 173 },
  { device: "other", users: 90 },
]

const chartConfig = {
  users: { label: "Users" },
  phone: { label: "Phone", color: "chart-1" },
  laptop: { label: "Laptop", color: "chart-2" },
  tablet: { label: "Tablet", color: "chart-3" },
  watch: { label: "Watch", color: "chart-4" },
  other: { label: "Other", color: "chart-5" },
} satisfies ChartConfig

const ACTIVE = 0

export function PieChartActive() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Highlighted slice</CardTitle>
        <CardDescription>The selected slice pops out</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Highlighted slice"
          className="h-52 w-full"
        >
          <PieChart>
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideLabel nameKey="device" />}
            />
            <Pie
              data={chartData}
              dataKey="users"
              nameKey="device"
              innerRadius="50%"
              outerRadius="78%"
              strokeWidth={0}
              shape={(sector, index) =>
                index === ACTIVE
                  ? [
                      { ...sector, outerRadius: sector.outerRadius + 10 },
                      {
                        ...sector,
                        innerRadius: sector.outerRadius + 13,
                        outerRadius: sector.outerRadius + 16,
                      },
                    ]
                  : sector
              }
            />
          </PieChart>
        </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/pie-chart-active.tsx`:

```tsx title="stylesheet/components/charts/pie-chart-active.tsx"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  type ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  Pie,
  PieChart,
} from "@/components/ui/chart"

const chartData = [
  { device: "phone", users: 275 },
  { device: "laptop", users: 200 },
  { device: "tablet", users: 187 },
  { device: "watch", users: 173 },
  { device: "other", users: 90 },
]

const chartConfig = {
  users: { label: "Users" },
  phone: { label: "Phone", color: "chart-1" },
  laptop: { label: "Laptop", color: "chart-2" },
  tablet: { label: "Tablet", color: "chart-3" },
  watch: { label: "Watch", color: "chart-4" },
  other: { label: "Other", color: "chart-5" },
} satisfies ChartConfig

const ACTIVE = 0

export function PieChartActive() {
  return (
    <Card variant="filled" size="sm">
      <CardHeader>
        <CardTitle>Highlighted slice</CardTitle>
        <CardDescription>The selected slice pops out</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer
          config={chartConfig}
          accessibilityLabel="Highlighted slice"
          style={{ height: 208 }}
        >
          <PieChart>
            <ChartTooltip
              cursor={false}
              content={<ChartTooltipContent hideLabel nameKey="device" />}
            />
            <Pie
              data={chartData}
              dataKey="users"
              nameKey="device"
              innerRadius="50%"
              outerRadius="78%"
              strokeWidth={0}
              shape={(sector, index) =>
                index === ACTIVE
                  ? [
                      { ...sector, outerRadius: sector.outerRadius + 10 },
                      {
                        ...sector,
                        innerRadius: sector.outerRadius + 13,
                        outerRadius: sector.outerRadius + 16,
                      },
                    ]
                  : sector
              }
            />
          </PieChart>
        </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/PieChartActive.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/PieChartActive.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 { PieChartActive } from "@/components/charts/pie-chart-active"
```

```tsx
<PieChartActive />
```

Replace `chartData` with your records and keep `dataKey` and `nameKey` in step with your field names. Add one entry per slice to `chartConfig` with its label and color; change `ACTIVE` to highlight a different slice. The component takes no props.

