Skip to content

Delta

See how much a value changed as a signed percentage, and whether the change is for the better.

Spending

-9.5%, bettervs August

€3,640

in September

Spending by month
WhenSpent
October 2025€3,420
November 2025€3,610
December 2025€4,280
January 2026€3,180
February 2026€3,050
March 2026€3,390
April 2026€3,520
May 2026€3,710
June 2026€3,460
July 2026€3,890
August 2026€4,020
September 2026€3,640

<script setup lang="ts">import { computed, ref } from 'vue'import { UiChartCard, UiDelta, UiAreaChart, UiRadioGroup, UiRadio, useUiT } from 'grani' const { n } = useUiT() const eur = (v: number) => n(v, { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }) const MONTHS = [  '2025-10',  '2025-11',  '2025-12',  '2026-01',  '2026-02',  '2026-03',  '2026-04',  '2026-05',  '2026-06',  '2026-07',  '2026-08',  '2026-09',] const BEFORE = [3420, 3610, 4280, 3180, 3050, 3390, 3520, 3710, 3460, 3890, 4020] // Spending: lower is better, so a fall is success and a rise danger (`invert`).const SEPTEMBER = { fell: 3640, rose: 4380, flat: 4021, first: 3640 } as const const state = ref<keyof typeof SEPTEMBER>('fell') const current = computed(() => SEPTEMBER[state.value]) const previous = computed(() => (state.value === 'first' ? null : BEFORE[10]!)) const series = computed(() => [  { key: 'spent', label: 'Spent', values: [...BEFORE, current.value], variant: 'line' as const },])</script> <template>  <div class="flex w-full flex-col items-center gap-4">    <UiChartCard      title="Spending"      :value="current"      caption="in September"      :format="eur"      class="w-full max-w-lg"    >      <template #actions>        <UiDelta :current="current" :previous="previous" invert label="vs August" />      </template>      <UiAreaChart        :x="MONTHS"        :series="series"        :format="eur"        :y-axis="false"        :legend="false"        :height="140"        ariaLabel="Spending by month"      />    </UiChartCard>    <UiRadioGroup v-model="state" variant="segmented" aria-label="September against August">      <UiRadio value="fell">Less</UiRadio>      <UiRadio value="rose">More</UiRadio>      <UiRadio value="flat">No change</UiRadio>      <UiRadio value="first">Nothing to compare</UiRadio>    </UiRadioGroup>  </div></template>

Also called trend indicator, change indicator, percent change.

Usage

<UiDelta :current="current" />

With GraniResolver in the Vite config, a template needs no import: set it up once.

API

Name · typeDefaultDescription
current*numberThe value now.
previousnumber | null= nullnullThe value it is compared with; null, missing, zero or not finite draws nothing.
invertboolean= falsefalseLower is better: a fall is success, growth danger.
labelstring= """"What it is compared with, shown after the badge: "vs August". A screen reader reads it as text after the verdict.
sizesm | md= "sm""sm"sm on a chart card's title line, in a row or a cell; md beside a larger heading.

Anything else lands on the root element: native attributes, aria-*, data-testid.

When to use another component

When you needTake
The trend itselfSparkline beside it
A state wordBadge
A countCount
A share of a wholeProgress