HextaUI

Badge

Renkli noktalı durum etiketleri, kayarak kapanan kaldırılabilir etiketler ve yeni değerine dönen sayaçlar.

PendingIn progressIn reviewFailedSuccessExpired
import {
  IconAlertTriangle,
  IconCircleCheck,
  IconCircleX,
  IconClock,
  IconEye,
  IconLoader2,
} from "@tabler/icons-react"

import { Badge } from "@/components/ui/badge"

export function BadgeDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Badge variant="warning">
        <IconAlertTriangle data-icon="inline-start" />
        Pending
      </Badge>
      <Badge variant="info">
        <IconLoader2 data-icon="inline-start" />
        In progress
      </Badge>
      <Badge variant="warning">
        <IconEye data-icon="inline-start" />
        In review
      </Badge>
      <Badge variant="destructive">
        <IconCircleX data-icon="inline-start" />
        Failed
      </Badge>
      <Badge variant="success">
        <IconCircleCheck data-icon="inline-start" />
        Success
      </Badge>
      <Badge>
        <IconClock data-icon="inline-start" />
        Expired
      </Badge>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/badge.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import {
  Badge,
  BadgeClose,
  BadgeCount,
  BadgeDot,
} from "@/components/ui/badge"
<Badge variant="success">
  <BadgeDot />
  Paid
</Badge>
Badge
├── BadgeDot
├── BadgeCount
└── BadgeClose

Variant'lar ve görünümler

Varsayılan outline görünümü nötr bir yüzey tutar ve durum rengini noktaya veya simgeye verir. Rozetin öne çıkması gerektiğinde appearance="solid", sakin dolgulu bir çip için appearance="muted" kullanın. shape="pill" tamamen yuvarlar.

import { Badge, BadgeDot } from "@/components/ui/badge"

export function BadgeVariants() {
  return (
    <div className="flex flex-col items-center gap-3">
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge>
          <BadgeDot />
          Draft
        </Badge>
        <Badge variant="success">
          <BadgeDot />
          Paid
        </Badge>
        <Badge variant="info">
          <BadgeDot />
          Syncing
        </Badge>
        <Badge variant="warning">
          <BadgeDot />
          Pending
        </Badge>
        <Badge variant="destructive">
          <BadgeDot />
          Failed
        </Badge>
      </div>
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge appearance="solid">Draft</Badge>
        <Badge appearance="solid" variant="success">
          Paid
        </Badge>
        <Badge appearance="solid" variant="info">
          Syncing
        </Badge>
        <Badge appearance="solid" variant="warning">
          Pending
        </Badge>
        <Badge appearance="solid" variant="destructive">
          Failed
        </Badge>
      </div>
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge appearance="muted">Draft</Badge>
        <Badge appearance="muted" shape="pill">
          nngroup.com
        </Badge>
        <Badge appearance="muted" shape="pill" variant="info">
          <BadgeDot />
          Syncing
        </Badge>
      </div>
    </div>
  )
}

Boyutlar

sm, default ve lg. Simgeler, noktalar, kapatma düğmesi ve sayılar rozetle birlikte ölçeklenir.

import { IconCheck } from "@tabler/icons-react"

import { Badge, BadgeClose, BadgeCount, BadgeDot } from "@/components/ui/badge"

export function BadgeSizes() {
  return (
    <div className="flex flex-col items-center gap-3">
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge size="sm">Small</Badge>
        <Badge size="sm" variant="success">
          <IconCheck data-icon="inline-start" />
          Paid
        </Badge>
        <Badge size="sm" variant="info">
          <BadgeDot pulse />
          Live
        </Badge>
        <Badge size="sm">
          design
          <BadgeClose />
        </Badge>
        <Badge size="sm">
          <BadgeCount value={42} />
        </Badge>
      </div>
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge>Default</Badge>
        <Badge variant="success">
          <IconCheck data-icon="inline-start" />
          Paid
        </Badge>
        <Badge variant="info">
          <BadgeDot pulse />
          Live
        </Badge>
        <Badge>
          design
          <BadgeClose />
        </Badge>
        <Badge>
          <BadgeCount value={42} />
        </Badge>
      </div>
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge size="lg">Large</Badge>
        <Badge size="lg" variant="success">
          <IconCheck data-icon="inline-start" />
          Paid
        </Badge>
        <Badge size="lg" variant="info">
          <BadgeDot pulse />
          Live
        </Badge>
        <Badge size="lg">
          design
          <BadgeClose />
        </Badge>
        <Badge size="lg">
          <BadgeCount value={42} />
        </Badge>
      </div>
    </div>
  )
}

Kaldırılabilir

Bir rozeti kaldırılabilir yapmak için <BadgeClose /> ekleyin. Rozet küçülerek kapanır, komşuları boşluğa kayar, sonra odak bir sonraki kapatma düğmesine geçer. Çıkış animasyonunun önce bitebilmesi için öğeyi verinizden onOpenChangeComplete içinde kaldırın.

"use client"

import * as React from "react"

import { Badge, BadgeClose } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"

const initialTags = [
  "design",
  "engineering",
  "research",
  "marketing",
  "customer-success",
  "ops",
]

export function BadgeRemovable() {
  const [tags, setTags] = React.useState(initialTags)
  const [next, setNext] = React.useState(1)

  return (
    <div className="flex w-full max-w-md flex-col gap-3">
      <div className="flex flex-wrap items-center gap-2">
        {tags.map((tag) => (
          <Badge
            key={tag}
            onOpenChangeComplete={(open) => {
              if (!open) {
                setTags((current) => current.filter((item) => item !== tag))
              }
            }}
          >
            {tag}
            <BadgeClose />
          </Badge>
        ))}
      </div>
      <div className="flex flex-wrap items-center gap-2">
        <Button
          variant="outline"
          size="sm"
          onClick={() => {
            setTags((current) => [...current, `tag-${next}`])
            setNext((value) => value + 1)
          }}
        >
          Add tag
        </Button>
        <Button variant="ghost" size="sm" onClick={() => setTags(initialTags)}>
          Reset
        </Button>
      </div>
    </div>
  )
}

Kontrollü

Görünürlüğü kendiniz yönetmek için open ve onOpenChange geçin. open değerini tekrar true yapmak rozeti bir giriş animasyonuyla geri getirir.

"use client"

import * as React from "react"

import { Badge, BadgeClose } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"

export function BadgeControlled() {
  const [open, setOpen] = React.useState(true)

  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Badge variant="warning" open={open} onOpenChange={setOpen}>
        Beta features on
        <BadgeClose />
      </Badge>
      <Button
        variant="outline"
        size="sm"
        disabled={open}
        onClick={() => setOpen(true)}
      >
        Restore
      </Button>
    </div>
  )
}

Sayılar

<BadgeCount /> yalnızca değişen basamakları döndürür ve max değerinde (varsayılan 99) artı işaretiyle sınırlanır. Ekran okuyucular her zaman gerçek sayıyı duyar.

"use client"

import * as React from "react"
import { IconInbox } from "@tabler/icons-react"

import { Badge, BadgeCount } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"

export function BadgeCounts() {
  const [count, setCount] = React.useState(9)

  return (
    <div className="flex flex-col items-center gap-4">
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Badge appearance="solid" variant="destructive">
          <BadgeCount value={count} />
        </Badge>
        <Badge>
          <BadgeCount value={count} max={999} />
          unread
        </Badge>
        <Button variant="outline">
          <IconInbox />
          Inbox
          <Badge size="sm">
            <BadgeCount value={count} />
          </Badge>
        </Button>
      </div>
      <div className="flex flex-wrap items-center justify-center gap-2">
        <Button
          variant="outline"
          size="sm"
          onClick={() => setCount((value) => value + 1)}
        >
          +1
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => setCount((value) => Math.max(0, value - 1))}
        >
          −1
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => setCount((value) => value + 10)}
        >
          +10
        </Button>
        <Button
          variant="ghost"
          size="sm"
          onClick={() => setCount(Math.floor(Math.random() * 1200))}
        >
          Random
        </Button>
      </div>
    </div>
  )
}

Etkileşimli

Bir rozeti bağlantı veya düğme yapmak için render kullanın. Üzerine gelince ton değişimi, basınca ölçek küçülmesi ve odak halkası kazanır. aria-invalid hata durumunu gösterir.

import { IconArrowUpRight, IconX } from "@tabler/icons-react"

import { Badge, BadgeDot } from "@/components/ui/badge"

export function BadgeInteractive() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Badge render={<a href="#changelog" />}>
        v2.0 is out
        <IconArrowUpRight data-icon="inline-end" />
      </Badge>
      <Badge render={<button type="button" />} variant="info">
        <BadgeDot />
        Filter: open
      </Badge>
      <Badge render={<a href="#new" />}>New</Badge>
      <Badge render={<button type="button" />} aria-invalid>
        <IconX data-icon="inline-start" />
        Invalid
      </Badge>
    </div>
  )
}

Uzun içerik

Rozet asla kapsayıcısından geniş olmaz. Uzun etiketler üç nokta ile kısaltılır; simgeler ve kapatma düğmesi görünür kalır.

import { IconCheck } from "@tabler/icons-react"

import { Badge, BadgeClose } from "@/components/ui/badge"

export function BadgeLongContent() {
  return (
    <div className="flex w-56 max-w-full flex-col items-start gap-2">
      <Badge>
        SupercalifragilisticexpialidociousSupercalifragilisticexpialidocious
      </Badge>
      <Badge variant="success">
        <IconCheck data-icon="inline-start" />
        [email protected]
        <BadgeClose />
      </Badge>
    </div>
  )
}

Sağdan sola

Simgeler, kapatma düğmesi ve daralma animasyonu okuma yönünü izler. Sayılar her zaman soldan sağa okunur.

import { IconCheck } from "@tabler/icons-react"

import { Badge, BadgeClose, BadgeCount, BadgeDot } from "@/components/ui/badge"

export function BadgeRtl() {
  return (
    <div dir="rtl" className="flex flex-wrap items-center justify-center gap-2">
      <Badge variant="success">
        <IconCheck data-icon="inline-start" />
        مدفوع
      </Badge>
      <Badge>
        <BadgeDot pulse />
        مباشر
      </Badge>
      <Badge>
        تصميم
        <BadgeClose />
      </Badge>
      <Badge>
        <BadgeCount value={120} />
      </Badge>
    </div>
  )
}

Bu tuşlar <BadgeClose /> için geçerlidir.

TuşAction
EnterSpaceRozeti kaldırır.
BackspaceDeleteRozeti kaldırır.
TabSonraki kapatma düğmesine geçer. Bir kaldırmadan sonra odak sonraki kapatma düğmesine, son düğmeyse öncekine iner.
  • Kapatma düğmesi rozetin adını taşır; böylece ekran okuyucu yalnızca “Remove” yerine “Remove design” duyurur. Geçersiz kılmak için aria-label geçin.
  • <BadgeDot /> dekoratiftir ve yardımcı teknolojilerden gizlenir. Durumu metin etiketinde tutun.
  • <BadgeCount />, görünen metin 99+ gibi sınırlandırılmış olsa bile tam değeri sunar.
  • Azaltılmış hareket açıkken kaldırma ve sayı animasyonları atlanır.

<Badge /> bir <span> oluşturur ve onun tüm niteliklerini kabul eder.

PropTürVarsayılan
variantoutline'da noktayı ve simgeleri, solid'de yüzeyi renklendirir.
"default" | "success" | "info" | "warning" | "destructive""default"
appearance
"outline" | "solid" | "muted""outline"
shape
"default" | "pill""default"
size
"sm" | "default" | "lg""default"
openKontrollü görünürlük.
boolean–
defaultOpen
booleantrue
onOpenChangeBadgeClose etkinleştirildiğinde çağrılır.
(open: boolean) => void–
onOpenChangeCompleteÇıkış animasyonu bittikten sonra çağrılır. Öğeyi verinizden burada kaldırın.
(open: boolean) => void–
render
ReactElement | (props, state) => ReactElement<span>
ÖznitelikAçıklama
data-slot="badge"CSS'te rozetleri hedefleyin.
data-variantGeçerli varyant.
data-appearanceGeçerli görünüm.
data-shapeGeçerli şekil.
data-sizeGeçerli boyut.
data-ending-styleRozet çıkış animasyonu yaparken bulunur.
--badge-accentNokta ve simgelerin kullandığı durum rengi. Özel bir vurgu için geçersiz kılın.
--badge-heightRozet yüksekliği.
--badge-radiusKöşe yarıçapı. Kapatma düğmesi kendi yarıçapını buna göre türetir.
PropTürVarsayılan
pulseCanlı durumlar için bir ping animasyonu ekler. Azaltılmış hareket açıkken kapalıdır.
booleanfalse
ÖznitelikAçıklama
data-slot="badge-dot"CSS'te noktaları hedefleyin.
data-pulsepulse açıkken bulunur.
PropTürVarsayılan
children
ReactNode<IconX />
aria-labelOtomatik “Remove {label}” adını geçersiz kılar.
string–
onClickRozeti açık tutmak için event.preventDefault() çağırın.
(event) => void–
ÖznitelikAçıklama
data-slot="badge-close"CSS'te kapatma düğmesini hedefleyin.
PropTürVarsayılan
valueNegatif ve sonlu olmayan değerler 0 gösterir.
number–
maxBunun üzerindeki değerler max+ olarak gösterilir. Sınır olmaması için Infinity geçin.
number99
duration
number600
animated
booleantrue
trendBasamakların dönüş yönü.
"auto" | "up" | "down" | "shortest""auto"
locales
Intl.LocalesArgument–
format
Intl.NumberFormatOptions–
ÖznitelikAçıklama
data-slot="badge-count"CSS'te sayıları hedefleyin.

Kullanıldığı bloklar

Badge üzerine kurulan bloklar.