Badge
A small pill used to label status, counts or categories.
A small pill for a count, a state or a label. The dot variant puts a filled circle before the text, which is how a status reads at a glance without relying on the pill’s colour alone.
newt-badgeimport { Badge } from "@/registry/bases/newt/ui/badge"
export default function BadgeDemo() {
return (
<div className="flex flex-wrap items-center gap-2">
<Badge variant="brand" dot>
Brand
</Badge>
<Badge variant="success" dot>
Online
</Badge>
<Badge variant="danger" dot>
Error
</Badge>
</div>
)
}<script setup lang="ts">
import { Badge } from "~~/registry/bases/newt/ui/badge"
</script>
<template>
<div class="flex flex-wrap items-center gap-2">
<Badge variant="brand" dot>Brand</Badge>
<Badge variant="success" dot>Online</Badge>
<Badge variant="danger" dot>Error</Badge>
</div>
</template>Installation
pnpm dlx newtui@latest add badgenpx newtui@latest add badgeyarn dlx newtui@latest add badgebunx newtui@latest add badgeInstall the dependencies
pnpm dlx --yes class-variance-authoritynpx --yes class-variance-authorityyarn dlx --yes class-variance-authoritybunx --yes class-variance-authorityCopy the source into your project
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-semibold leading-4",
{
variants: {
variant: {
default: "bg-newt-bg-elevated text-newt-text-secondary",
brand: "bg-[rgba(88,101,242,0.15)] text-newt-mention-text",
success: "bg-[rgba(35,165,90,0.15)] text-[#45c178]",
warning: "bg-[rgba(240,178,50,0.15)] text-newt-mention-role",
danger: "bg-[rgba(242,63,66,0.15)] text-[#f4878a]",
},
dot: {
true: "before:h-1.5 before:w-1.5 before:rounded-full before:bg-current before:content-['']",
false: "",
},
},
defaultVariants: {
variant: "default",
dot: false,
},
}
)
export interface BadgeProps
extends
React.HTMLAttributes<HTMLSpanElement>,
VariantProps<typeof badgeVariants> {}
const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
({ className, variant, dot, ...props }, ref) => (
<span
ref={ref}
className={cn(badgeVariants({ variant, dot }), className)}
{...props}
/>
)
)
Badge.displayName = "Badge"
export { Badge, badgeVariants }<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
import { badgeVariants, type BadgeVariants } from "."
const props = defineProps<{
class?: HTMLAttributes["class"]
variant?: BadgeVariants["variant"]
dot?: boolean
}>()
</script>
<template>
<span
:class="
cn(badgeVariants({ variant: props.variant, dot: props.dot }), props.class)
"
>
<slot />
</span>
</template>import { cva, type VariantProps } from "class-variance-authority"
export { default as Badge } from "./Badge.vue"
export const badgeVariants = cva(
"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-semibold leading-4",
{
variants: {
variant: {
default: "bg-newt-bg-elevated text-newt-text-secondary",
brand: "bg-[rgba(88,101,242,0.15)] text-newt-mention-text",
success: "bg-[rgba(35,165,90,0.15)] text-[#45c178]",
warning: "bg-[rgba(240,178,50,0.15)] text-newt-mention-role",
danger: "bg-[rgba(242,63,66,0.15)] text-[#f4878a]",
},
dot: {
true: "before:h-1.5 before:w-1.5 before:rounded-full before:bg-current before:content-['']",
false: "",
},
},
defaultVariants: {
variant: "default",
dot: false,
},
}
)
export type BadgeVariants = VariantProps<typeof badgeVariants>Update the import paths
The files import @/lib/utils and sibling components through the aliases in your components.json. Point them at wherever those live in your project.
Usage
import { Badge } from "@/components/ui/badge"
export function Example() {
return <Badge />
}<script setup lang="ts">
import { Badge } from "@/components/ui/badge"
</script>
<template>
<Badge />
</template>API reference
Badge
variant?"default" | "brand" | "success" | "warning" | "danger"
What the badge is reporting.
"default" | "brand" | "success" | "warning" | "danger""default"dot?boolean
Renders a leading dot in the current text colour.
booleanfalseEvery part also accepts the native attributes of the element it renders, and a className that is merged rather than replaced.
Accessibility
A badge is text, not a control. If it reports something that changes — an unread count, a build status — put it in a container with aria-live="polite" so the change is announced. Never let the colour be the only difference between two states: the words in the badge should differ too.
Tokens
Badge reads its colours, radii and motion from the --newt-* tokens installed with the library. Override a token and every component that reads it follows, including this one — see the token layer. In the plain HTML and CSS distribution the same component is newt-badge.