Pie Chart

Build full-radius pie charts with accessible legend metadata.
alpha

Unovis uses VisDonut for both pie and donut charts. Set arc-width="0" to fill the center and render a pie. Pie charts work best with a small number of categories and a visible legend.

Default

Place the pie inside VisSingleContainer. Pass Donut to ChartTooltip.targets to connect each slice to the themed tooltip automatically.

Chrome
Safari
Firefox
Edge
Other
vue
<script setup lang="ts">
import { Donut } from '@unovis/ts'
import { VisDonut, VisSingleContainer } from '@unovis/vue'
import {
  ChartLegend,
  ChartRoot,
  ChartTooltip,
} from '@typlog/ui/charts'

interface Slice {
  browser: string
  visitors: number
}

const data: Slice[] = [
  { browser: 'chrome', visitors: 275 },
  { browser: 'safari', visitors: 200 },
  { browser: 'firefox', visitors: 187 },
  { browser: 'edge', visitors: 173 },
  { browser: 'other', visitors: 90 },
]
const config = {
  chrome: { label: 'Chrome' },
  safari: { label: 'Safari' },
  firefox: { label: 'Firefox' },
  edge: { label: 'Edge' },
  other: { label: 'Other' },
}
</script>

<template>
  <ChartRoot v-slot="{ mounted }" :config="config">
    <div class="mx-auto max-w-72">
      <VisSingleContainer v-if="mounted" :data="data" :height="260">
        <VisDonut
          :value="(slice: Slice) => slice.visitors"
          :arc-width="0"
        />
        <ChartTooltip :targets="[Donut]" :content-props="{ hideLabel: true }" />
      </VisSingleContainer>
    </div>
    <ChartLegend class="mt-3" align="center" />
  </ChartRoot>
</template>

Rounded segments

Padding and corner radius create clearer separation when the chart has only a few substantial slices. Avoid large gaps when values are small because spacing can visually distort the proportions.

Product
Docs
Blog
Community
vue
<script setup lang="ts">
import { Donut } from '@unovis/ts'
import { VisDonut, VisSingleContainer } from '@unovis/vue'
import {
  ChartLegend,
  ChartRoot,
  ChartTooltip,
  ChartTooltipContent,
  createChartTooltipTemplate,
} from '@typlog/ui/charts'

interface Slice {
  source: string
  sessions: number
}

const data: Slice[] = [
  { source: 'Product', sessions: 42 },
  { source: 'Docs', sessions: 28 },
  { source: 'Blog', sessions: 19 },
  { source: 'Community', sessions: 11 },
]
const config = Object.fromEntries(data.map(item => [item.source, { label: item.source }]))
const tooltipContent = createChartTooltipTemplate(config, ChartTooltipContent, { hideLabel: true })
const tooltipTriggers = {
  [Donut.selectors.segment]: (arc: { data: Slice }) => (
    tooltipContent({ [arc.data.source]: arc.data.sessions })
  ),
}
</script>

<template>
  <ChartRoot v-slot="{ mounted }" :config="config">
    <div class="mx-auto max-w-72">
      <VisSingleContainer v-if="mounted" :data="data" :height="260">
        <VisDonut
          :value="(slice: Slice) => slice.sessions"
          :arc-width="0"
          :pad-angle="0.035"
          :corner-radius="8"
        />
        <ChartTooltip :triggers="tooltipTriggers" />
      </VisSingleContainer>
    </div>
    <ChartLegend class="mt-3" align="center" />
  </ChartRoot>
</template>

Half pie

Set angleRange to render a semicircle when vertical space is limited. This shape is useful for compact status summaries, but it offers less area for labels and interactions.

Complete
In progress
Blocked
vue
<script setup lang="ts">
import { VisDonut, VisSingleContainer } from '@unovis/vue'
import { ChartLegend, ChartRoot } from '@typlog/ui/charts'

interface Slice {
  status: string
  value: number
}

const data: Slice[] = [
  { status: 'Complete', value: 58 },
  { status: 'In progress', value: 27 },
  { status: 'Blocked', value: 15 },
]
const config = Object.fromEntries(data.map(item => [item.status, { label: item.status }]))
</script>

<template>
  <ChartRoot v-slot="{ mounted }" :config="config">
    <div class="mx-auto max-w-72">
      <VisSingleContainer v-if="mounted" :data="data" :height="190">
        <VisDonut
          :value="(slice: Slice) => slice.value"
          :arc-width="0"
          :angle-range="[-Math.PI / 2, Math.PI / 2]"
          :pad-angle="0.025"
        />
      </VisSingleContainer>
    </div>
    <ChartLegend class="mt-3" align="center" />
  </ChartRoot>
</template>

Use a bar chart when precise comparisons matter more than part-to-whole shape, or when the data contains many small categories.

Last updated Sep 6, 2026