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

Data Display

Badge

Data Display

Badge React component for Tailwind CSS v4

AvatarCalendar View
Live props
Content
children
removeLabel
Appearance
variant
tone
color
size
radius
dot
pulse
Behavior
max99
showZero
locale
asChild
State
disabled
Code
import { Badge } from "@/components/ui/badge"

<Badge>Nou</Badge>
  1. Home
  2. Components
  3. Data Display
  4. Badge
Free

Badge React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React badge for status chips, removable filters and animated counts in three variants and six tones, plus a count or dot on any corner.

A status badge is plain text in a tinted pill; with pulse its dot pings like a live light. A count rolls to the new number, up when it grows and down when it shrinks, the pill widens on a smooth spring and gives a small bounce on every new item; at 0 it scales away. Removable chips show a round x: click or tap it (a 36px target on touch), or focus it with Tab and press Enter, Backspace or Delete. With asChild the badge is a real link or button with a hover tint, a press dip, a focus ring and a 44px tall touch target. BadgeAnchor pins a badge to a corner of an icon button or avatar, cut out by a thin ring, and pops it in and out.

Badge is a free React component in the React data display components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add badge, together with Motion presets, Tones and UIProvider and the npm packages @radix-ui/react-slot, lucide-react and motion.

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 badge

Usage

Import Badge from @/components/ui/badge.

import { Bell } from "lucide-react"
import { Badge, BadgeAnchor } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"

export function OrderHeader({ unread, onOpenInbox }: { unread: number; onOpenInbox: () => void }) {
  return (
    <div className="flex items-center gap-3">
      <Badge tone="success" dot>Paid</Badge>
      <Badge tone="warning">Low stock</Badge>
      <BadgeAnchor offset={5} badge={<Badge variant="solid" tone="danger" size="sm" count={unread} aria-hidden />}>
        <Button variant="soft" size="icon" radius="full" aria-label={`Notifications, ${unread} unread`} onClick={onOpenInbox}>
          <Bell />
        </Button>
      </BadgeAnchor>
    </div>
  )
}

Props

  • childrendefault "Nou"
    ReactNode

    The label. Long labels truncate with an ellipsis. Leave it empty (with no icons or count) and the badge becomes a status dot.

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

    soft (a tinted pill) for statuses, solid for counts and the one label that must stand out, outline for filters and quiet tags.

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

    Semantic color from the design tokens: success for paid or online, warning for low stock, danger for cancelled or failed, info for in progress. Pair color with the text, never color alone.

  • colordefault ""
    string

    Any CSS color. Replaces the tone in every variant; text on a solid fill turns black or white by lightness. Leave empty to use the tone.

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

    Height 20 / 24 / 28px with 11 / 12 / 13px text and 12 / 12 / 14px icons.

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

    Corner shape: 0 / 4 / 6 / 8px or a pill. Badges default to pills (a deliberate difference from controls); the square steps suit tag-like labels.

  • dotdefault false
    boolean

    A leading status dot in the tone (in the text color on a solid badge).

  • pulsedefault false
    boolean

    The dot pings, for live, recording or online. Implies dot. Decorative (hidden from screen readers); under reduced motion the dot stays still.

  • maxdefault 99
    number

    Counts above it read "99+". Values below 1 fall back to 99. Only used with count.

  • showZerodefault false
    boolean

    A count of 0 scales the badge away unless this is set. Try it on the bell: tap it to mark all as read.

  • localedefault ""
    string

    Formats the count through Intl, e.g. "en-US" turns 1250 into 1,250 and "de-DE" into 1.250. Empty uses the reader's locale; pass one for server-rendered counts of 1000 or more so the grouping matches after hydration.

  • removeLabeldefault "Remove"
    string

    aria-label of the remove button, e.g. "Remove the Brooklyn filter". Only used with onRemove.

  • disableddefault false
    boolean

    Dims the badge (a count too) and hides the remove button. With asChild the link gets aria-disabled, leaves the tab order and ignores clicks.

  • asChilddefault false
    boolean

    Renders your single child (an <a>, a router Link, a button) as the badge, with a hover tint, a press dip and a focus ring. asChild badges have no remove button, since a button inside a link is invalid. The demo swaps in a link.

  • count
    number

    Shows this number instead of children and animates every change: the digits slide, the width follows on a spring and the badge bumps when it grows. Negative values clamp to 0, fractions round. The demo's bell drives it with the + and - buttons.

  • leftIcon
    ReactNode

    An icon before the label. Unsized svgs follow the size (12 / 12 / 14px).

  • rightIcon
    ReactNode

    An icon after the label, like an arrow on a link badge.

  • onRemove
    () => void

    Shows a round x button that calls it on click, tap, Enter, Backspace or Delete. The click does not bubble, so a chip inside a clickable row removes itself without opening the row.

  • classNames
    Partial<Record<"dot" | "icon" | "label" | "count" | "remove", string>>

    Extra classes for the inner parts: the status dot, each icon wrapper, the label, the count and the remove button.

  • className
    string

    Extra classes for the badge itself, merged last. Override the tone vars here, e.g. [--tone-foreground:white].

Parts

  • BadgeAnchor

    component

    Pins a badge to a corner of its child (an icon button, an avatar). badge: the Badge to place (a count, or an empty Badge for a dot). placement: "top-end" (default) | "top-start" | "bottom-end" | "bottom-start", logical so it flips in RTL. offset: px, default 0; positive moves the badge inward, about 5 to 6px puts it on the edge of a round 40px host. invisible: scales it out and back in. ringColor: default var(--background), the 2px ring that cuts the badge out of its host (pass var(--surface) on panels). classNames.badge: the placed wrapper, which lets clicks through to the host. Props: BadgeAnchorProps.

Examples

Variants and tones

Three variants across the six tones, each with a status it would really carry.

Sizes and radii

20, 24 and 28px. Pills by default; the square steps suit tag-like labels.

Dot and pulse

A status dot, and a ping for anything live. An empty badge is a dot on its own.

Counts

Digits roll with the change and 128 reads 99+. The last row is de-DE with max 9999. Click a row to clear it.

Removable filter chips

Click the x or focus it and press Delete; the rest slide into place and focus moves to the next chip.

Anchored to an icon or avatar

A count on a bell, dots for unread and online, cut out by a ring in the panel's color.

Custom color and links

Any CSS color, and asChild for a badge that is a real link with hover, press and focus.

Long labels

A badge never grows past its container.

Dependencies

@radix-ui/react-slotlucide-reactmotionmotiontonesui-config

Files

  • components/ui/badge.tsx

FAQ

Is the React Badge component free?

Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.

How do I install Badge?

Run npx wingo-ui@latest add badge. It also adds the Wingo UI items it builds on (Motion presets, Tones and UIProvider) and the npm packages @radix-ui/react-slot, lucide-react and motion. With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/badge.json.

See also

AvatarButtonAnimated CounterNotification BellToneslib

Used in

Listing cardBottom Tab BarMarketplace Home PageMobile App HomeKanbanLeaderboardOrder trackerCheckout stepsCart drawerSegmented ControlUser MenuModel Picker

and 94 more.

More React data display components

File managerCountdownApproval FlowCalendar ViewCode BlockComment Thread
All 23 React data display components

Articles using this component

  • Tailwind v4 Design Tokens: Colors, Dark Mode and Contrast

    Next.js and Tailwind CSS · Oct 9, 2026 · 20 min read

PreviousAvatarNext Calendar View

Recent orders

Updated today, 2:32 PM

3

Order status

#10486 · Anna Price

Nou
  • Michael Hayes

    #10482 · Sep 21, 2026

    $1,249.00Paid
  • Jessica Dunn

    #10483 · Sep 22, 2026

    $389.90Shipping
  • Andrew Porter

    #10484 · Sep 22, 2026

    $2,150.00Cancelled
  • Ellen Stone

    #10485 · Sep 23, 2026

    $74.50Low stock
3 unread

Tap the bell to mark all as read: at 0 the badge scales away. Past 99 it reads 99+.