Small status badge with variants
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
export default function BadgeDemoExample() {
return (
<div class="flex w-full flex-wrap justify-center gap-2">
<Badge>Badge</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
</div>
)
}
Installation
npx @fictjs/shadcn@latest add badgeInstall the runtime dependencies:
npm install @fictjs/radix-ui class-variance-authorityCopy the Fict shadcn component into your project.
Source
components/ui/badge.tsx
src/components/ui/badge.tsx
import { Slot } from '@fictjs/radix-ui'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/cn'
const badgeVariants = cva(
'inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-md border px-2 py-0.5 text-xs font-medium transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3',
{
variants: {
variant: {
default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
outline: 'text-foreground',
ghost: 'border-transparent hover:bg-accent hover:text-accent-foreground',
link: 'border-transparent text-primary underline-offset-4 hover:underline',
},
},
defaultVariants: {
variant: 'default',
},
},
)
type BadgeProps = JSX.IntrinsicElements['span'] & VariantProps<typeof badgeVariants> & {
asChild?: boolean
}
export function Badge(props: BadgeProps) {
const { asChild, class: className, variant = 'default', ...rest } = props
const classValue = cn(badgeVariants({ variant }), className)
if (asChild) {
return <Slot.Root class={classValue} data-slot='badge' data-variant={variant} {...rest} />
}
return <span class={classValue} data-slot='badge' data-variant={variant} {...rest} />
}
export { badgeVariants }
Usage
Examples
Variants
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
export default function BadgeVariantsExample() {
return (
<div class="flex flex-wrap gap-2">
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="ghost">Ghost</Badge>
</div>
)
}
Icon
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
function VerifiedIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" data-icon="inline-start" aria-hidden="true">
<path d="M12 3l2.1 2.1 3-.4.4 3 2.2 2.3-1.7 2.5.7 2.9-2.9.7-1.8 2.4-2-1.5-2 1.5-1.8-2.4-2.9-.7.7-2.9L4.3 10l2.2-2.3.4-3 3 .4z" />
<path d="m9 12 2 2 4-4" />
</svg>
)
}
function BookmarkIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" data-icon="inline-end" aria-hidden="true">
<path d="M6 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18l-6-4-6 4z" />
</svg>
)
}
export default function BadgeIconExample() {
return (
<div class="flex flex-wrap gap-2">
<Badge variant="secondary"><VerifiedIcon />Verified</Badge>
<Badge variant="outline">Bookmark<BookmarkIcon /></Badge>
</div>
)
}
Spinner
import { Badge } from '@/components/ui/badge'
import { Spinner } from '@/components/ui/spinner'
...import { Badge } from '@/components/ui/badge'
import { Spinner } from '@/components/ui/spinner'
export default function BadgeSpinnerExample() {
return (
<div class="flex flex-wrap gap-2">
<Badge variant="destructive"><Spinner data-icon="inline-start" />Deleting</Badge>
<Badge variant="secondary">Generating<Spinner data-icon="inline-end" /></Badge>
</div>
)
}
Link
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
function ExternalLinkIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" data-icon="inline-end" aria-hidden="true">
<path d="M7 17 17 7M7 7h10v10" />
</svg>
)
}
export default function BadgeLinkExample() {
return (
<Badge asChild>
<a href="#link">Open Link<ExternalLinkIcon /></a>
</Badge>
)
}
Colors
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
export default function BadgeColorsExample() {
return (
<div class="flex flex-wrap gap-2">
<Badge class="bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300">Blue</Badge>
<Badge class="bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300">Green</Badge>
<Badge class="bg-sky-50 text-sky-700 dark:bg-sky-950 dark:text-sky-300">Sky</Badge>
<Badge class="bg-purple-50 text-purple-700 dark:bg-purple-950 dark:text-purple-300">Purple</Badge>
<Badge class="bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-300">Red</Badge>
</div>
)
}
Rtl
import { Badge } from '@/components/ui/badge'
...import { Badge } from '@/components/ui/badge'
const translations = {
ar: ['شارة', 'ثانوي', 'مدمر', 'مخطط', 'متحقق', 'إشارة مرجعية'],
he: ['תג', 'משני', 'הרסני', 'קווי מתאר', 'מאומת', 'סימנייה'],
en: ['Badge', 'Secondary', 'Destructive', 'Outline', 'Verified', 'Bookmark'],
} as const
function CheckIcon() {
return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m7 12 3 3 7-7" /></svg>
}
function BookmarkIcon() {
return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M6 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18l-6-4-6 4z" /></svg>
}
export default function BadgeRtlExample() {
let language = $state<keyof typeof translations>('ar')
const text = () => translations[language]
const direction = () => language === 'en' ? 'ltr' : 'rtl'
return (
<div class="grid gap-4">
<select value={language} onChange={event => { language = event.currentTarget.value as keyof typeof translations }}>
<option value="ar">Arabic (العربية)</option>
<option value="he">Hebrew (עברית)</option>
<option value="en">English</option>
</select>
<div class="flex flex-wrap justify-center gap-2" dir={direction()}>
<Badge>{text()[0]}</Badge>
<Badge variant="secondary">{text()[1]}</Badge>
<Badge variant="destructive">{text()[2]}</Badge>
<Badge variant="outline">{text()[3]}</Badge>
<Badge variant="secondary"><CheckIcon />{text()[4]}</Badge>
<Badge variant="outline">{text()[5]}<BookmarkIcon /></Badge>
</div>
</div>
)
}