Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Charts & Stats

Trend badge

Charts & Stats

Trend badge React chart component for Tailwind CSS v4

TrackerAccordion
Live props
Content
value
format
currency
decimals
emptyText
label
Layout
labelPosition
State
trend
flatThreshold
invertTrend
Appearance
variant
size
radius
icon
showSign
neutralTone
positiveTone
negativeTone
positiveColor
negativeColor
Behavior
animated
locale
Code
import { TrendBadge } from "@/components/ui/trend-badge"

<TrendBadge />
  1. Home
  2. Components
  3. Charts & Stats
  4. Trend badge
Pro

Trend badge React chart component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React trend badge, the delta chip for KPIs, table cells and leaderboards: an arrow, a signed change and a color that says if it is good.

A read-only chip, not focusable: an arrow and a signed number ("+12.4%", "−$3,200") tinted green when the change is good and red when it is bad, gray when nothing moved. Screen readers hear the direction in words ("Up 12.4% vs. last month"), never the arrow. With animated on it counts up from zero the first time it scrolls into view, glides to every new value without the pill changing width midway, and the arrow cross-fades when the direction flips. Tap the playground's Change button to watch it. Reduced motion shows the final number at once.

Trend badge is a Pro React chart component in the React chart and stat components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add trend-badge, together with Motion presets, Number format, Tones, UIProvider and useLocale and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add trend-badge

Trend badge is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import TrendBadge from @/components/ui/trend-badge.

import { TrendBadge } from "@/components/ui/trend-badge"

export function RevenueKpi() {
  return (
    <div className="flex flex-col gap-1">
      <span className="text-[13px] text-muted-foreground">Revenue</span>
      <span className="text-2xl font-semibold tabular-nums">$128,450</span>
      <TrendBadge value={12.4} label="vs. last month" locale="en-US" animated />
      <TrendBadge
        value={-2.5}
        invertTrend
        formatValue={(v) => `${v < 0 ? "−" : "+"}${Math.abs(v).toLocaleString("en-US")} days`}
      />
    </div>
  )
}

Props

  • value*default 12.4
    number | null

    The change, in format units: 12.4 is +12.4% with percent, 3200 is +$3,200 with currency. null or NaN renders emptyText in gray, without an arrow.

  • formatdefault "percent"
    "percent" | "number" | "currency"

    How the number prints, through Intl with the locale. Values of a million and up go compact ("+$1.3M").

  • currencydefault "USD"
    string

    ISO 4217 code for format="currency", printed with its narrow symbol ("$", "€", "£").

  • decimalsdefault -1
    number

    Fraction digits (0 to 6). The default -1 is auto: 1 for percent, 0 for numbers, and 0 for currency from 100 up (2 below).

  • formatValue
    (value: number) => string

    Full control over the visible text, e.g. v => `−${Math.abs(v)} days`. The sr sentence uses it too.

  • emptyTextdefault "–"
    string

    Shown instead of the number when value is null or NaN. Screen readers hear labels.empty.

  • labeldefault ""
    ReactNode

    The comparison, like "vs. last month". Joined into the spoken sentence.

  • labelPositiondefault "outside"
    "inside" | "outside"

    outside puts the label after the pill in muted text (the stat card look) and wraps it below on narrow widths; inside keeps it in the pill.

  • trenddefault "auto"
    "auto" | "up" | "down" | "flat"

    auto reads the sign of value. Force a direction when the meaning does not follow the sign.

  • flatThresholddefault 0.05
    number

    A change smaller than this (absolute, in format units) counts as no change and gets the gray look.

  • invertTrenddefault false
    boolean

    Down is good: costs, churn, response time. A fall turns green and a rise red.

  • variantdefault "soft"
    "soft" | "solid" | "outline" | "ghost"

    soft is the tinted pill, solid a filled chip for emphasis, outline a hairline border, ghost colored text with an arrow and no fill (for table cells).

  • sizedefault "md"
    "sm" | "md" | "lg"

    Height 20 / 24 / 28px with 11 / 12 / 13px text (the outside label follows). md matches the stat card's delta pill.

  • radiusdefault "full"
    "none" | "sm" | "md" | "lg" | "full"

    Corner shape: square, 4px, 6px, 8px or a pill (the badge's radii).

  • icondefault "arrow"
    "arrow" | "trend" | "chevron" | "none"

    Diagonal arrows, trend lines or chevrons (a dash or a flat arrow when nothing moved). Mirrors in RTL.

  • showSigndefault true
    boolean

    Prefix gains with a plus. A loss always shows its minus (the typographic one, as wide as the plus).

  • neutralTonedefault false
    boolean

    Every direction in the neutral ink, for places where green and red would suggest a judgment.

  • positiveTonedefault "success"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The color of a good change. info suits a metric that is not good or bad, like open tickets.

  • negativeTonedefault "danger"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The color of a bad change. warning softens it for metrics that are not alarming.

  • positiveColordefault ""
    string

    Any CSS color for a good change, replacing positiveTone in every variant. No change stays gray and neutralTone still wins.

  • negativeColordefault ""
    string

    Any CSS color for a bad change, replacing negativeTone in every variant.

  • animateddefault false
    boolean

    Counts up from zero when first in view and glides between values. Off by default so a table of badges does not all count at once.

  • localedefault ""
    string

    Intl locale for the number. Empty follows the UIProvider, then the page.

  • labels
    { up?: (text: string) => string; down?: (text: string) => string; flat?: string; empty?: string }

    The spoken sentence. Defaults "Up {x}", "Down {x}", "No change", "No data"; e.g. up: x => `up ${x}`.

  • classNames
    Partial<Record<"icon" | "value" | "label" | "group", string>>

    Extra classes for the icon, the number, the label and the wrapper around pill and outside label.

  • className
    string

    Extra classes for the pill, merged last. Override the tone vars here, e.g. [--tone-soft:transparent].

Parts

  • getTrend

    function

    The direction of a change: up, down, or flat when the absolute value is under the threshold (and for 0, null or NaN). Use it to pick an icon or sort rows the way the badge does. Signature: (value: number | null | undefined, options?: { flatThreshold?: number }) => "up" | "down" | "flat".

  • getTrendIntent

    function

    What a direction means: up is positive unless the metric is inverted (costs, churn, response time); flat is neutral. Signature: (trend: TrendDirection, invertTrend?: boolean) => "positive" | "negative" | "neutral".

  • DEFAULT_TREND_BADGE_LABELS

    constant

    The English screen reader sentences: up(text) "Up 12.4%", down(text) "Down 12.4%", flat "No change", empty "No data". Spread it to translate. Type: Required<TrendBadgeLabels>.

  • TrendDirection

    type

    "up" | "down" | "flat".

  • TrendIntent

    type

    "positive" | "negative" | "neutral", which picks the tone.

Examples

KPI rows

Percent, count and a custom unit; inverted for a metric where down is good.

Variants

soft, solid, outline and ghost across up, down and no change.

Sizes and icons

20, 24 and 28px with arrows, trend lines or chevrons.

In a table

Ghost badges in a right-aligned column: color without the weight of a fill.

Currency

Narrow symbols per locale, compact from a million up.

Custom tones

info and warning for metrics that are not good or bad, brand, any CSS color, and neutralTone for running text.

Edge cases

No data (with a custom emptyText), changes too small to count, a forced direction, the label inside.

Dependencies

motionlucide-reactmotionnumber-formattonesui-configuse-locale

Files

  • components/ui/trend-badge.tsx

FAQ

Is the React Trend badge chart component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Trend badge?

Run npx wingo-ui@latest add trend-badge. It also adds the Wingo UI items it builds on (Motion presets, Number format, Tones, UIProvider and useLocale) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/trend-badge.

See also

BadgeAnimated CounterChart kitlibNumber formatlib

Used in

SparklineLeaderboard

More React chart and stat components

GaugeGitHub ActivityRadial barTrackerHeatmap calendarStat Card
All 16 React chart and stat components

Articles using this component

  • Shadcn KPI Cards: Deltas, Sparklines and Goal Bars

    Component guides · Nov 6, 2026 · 9 min read

  • React Sparkline: Table Cells, KPI Tiles, Delta Chips

    Component guides · Oct 19, 2026 · 9 min read

PreviousTrackerNext Accordion
RevenueSept. 2026
$128,450+12.4%Up 12.4%vs. last month

Collected from 342 invoices issued

vs. Sept. 2025–No data
animated: off