Skip to main content

Badge Component

The Badge component displays a small visual indicator that helps highlight status, categories, or counts with different styling variants that can be applied to text or used as labels.

Import

import { Badge } from '@/components/ui/badge';

Usage

Basic Usage

<Badge>New</Badge>

Variants

Default

<Badge variant="default">Default</Badge>

Secondary

<Badge variant="secondary">Secondary</Badge>

Destructive

<Badge variant="destructive">Destructive</Badge>

Outline

<Badge variant="outline">Outline</Badge>

You can use the badgeVariants helper to apply badge styling to other elements:

import { badgeVariants } from '@/components/ui/badge';
import Link from 'next/link';

<Link href="/categories/new" className={badgeVariants({ variant: 'outline' })}>
View Category
</Link>

Props

PropTypeDefaultDescription
variant'default' | 'secondary' | 'destructive' | 'outline''default'The visual style variant of the badge
classNamestringundefinedAdditional CSS classes to apply to the badge
childrenReactNodeRequiredThe content to display inside the badge

TypeScript

// Component Type Definition
type BadgeProps = {
variant?: 'default' | 'secondary' | 'destructive' | 'outline';
children: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>;

Customization

Style Overrides

The Badge component can be customized using the following approaches:

  1. Using the className prop to add additional Tailwind classes:
<Badge className="px-4 py-1 text-sm">Custom Sized</Badge>
  1. Extending with custom colors:
<Badge className="bg-blue-500 hover:bg-blue-600 text-white">Custom Color</Badge>

Extending the Component

For project-specific badge variants, you can extend the base Badge component:

import { Badge, badgeVariants } from '@/components/ui/badge';
import { cn } from '@/lib/utils';

const SuccessBadge = ({ children, className, ...props }) => {
return (
<Badge
{...props}
className={cn(
'bg-green-500 text-white hover:bg-green-600',
className
)}
>
{children}
</Badge>
);
};

Examples

Integration with Cards

import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';

<Card>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>Project Status</CardTitle>
<Badge variant="secondary">In Progress</Badge>
</div>
</CardHeader>
<CardContent>
Project details here...
</CardContent>
</Card>

Integration with Forms

import { useForm } from 'react-hook-form';
import { Form, FormField, FormItem, FormLabel, FormControl } from '@/components/forms/form';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';

const TaggedFormField = () => {
const form = useForm();

return (
<Form {...form}>
<form>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-2">
<FormLabel>Email</FormLabel>
<Badge variant="outline">Required</Badge>
</div>
<FormControl>
<Input placeholder="you@example.com" {...field} />
</FormControl>
</FormItem>
)}
/>
</form>
</Form>
);
};

Integration with Buttons

import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';

<div className="flex items-center gap-2">
<Button variant="outline">
Notifications
<Badge className="ml-2" variant="secondary">5</Badge>
</Button>
</div>

Responsive Behavior

The Badge component is inherently responsive with its default styling. Here's how it behaves across different screen sizes:

  • Mobile: Badges maintain their compact size for mobile interfaces
  • Tablet/Desktop: Badges scale naturally with their container elements without requiring specific responsive adjustments

For custom responsive behaviors:

<Badge className="px-2 md:px-3 py-0.5 md:py-1 text-xs md:text-sm">
Responsive Badge
</Badge>

Accessibility

The Badge component follows these accessibility best practices:

  • Uses appropriate color contrast ratios for all variants to ensure readability
  • Maintains readable text sizes in the default styling
  • When used for status indicators, should be paired with appropriate ARIA attributes for screen readers
  • For interactive badges, ensure they receive focus styles and keyboard interaction support

Example with enhanced accessibility:

<Badge 
role="status"
aria-label="3 unread notifications"
>
3
</Badge>

Implementation Details

The Badge component:

  • Renders as a <div> element by default
  • Uses the class-variance-authority (CVA) utility for variant management
  • Applies TailwindCSS utility classes for styling
  • Supports standard HTML div attributes through React HTMLAttributes spreading
  • Uses a rounded-full design by default for the classic badge appearance

Common Pitfalls

  • Crowding with content: Avoid placing badges too close to other UI elements without adequate spacing
  • Overusing variants: Use variants consistently to maintain their meaning throughout the application
  • Inaccessible color combinations: Be cautious when overriding colors to maintain sufficient contrast

Testing

// Example test for the Badge component
import { render, screen } from '@testing-library/react';
import { Badge } from '@/components/ui/badge';

describe('Badge', () => {
it('renders with default variant correctly', () => {
render(<Badge>Test Badge</Badge>);
const badge = screen.getByText('Test Badge');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('bg-primary'); // Check for default variant class
});

it('applies custom className', () => {
render(<Badge className="test-class">Test Badge</Badge>);
const badge = screen.getByText('Test Badge');
expect(badge).toHaveClass('test-class');
});

it('renders with different variants', () => {
const { rerender } = render(<Badge variant="secondary">Secondary</Badge>);
expect(screen.getByText('Secondary')).toHaveClass('bg-secondary');

rerender(<Badge variant="destructive">Destructive</Badge>);
expect(screen.getByText('Destructive')).toHaveClass('bg-destructive');

rerender(<Badge variant="outline">Outline</Badge>);
expect(screen.getByText('Outline')).toHaveClass('text-foreground');
});
});
  • Button: Often used together with badges to show counts or status
  • Card: Badges can be used in card headers to indicate status or categories
  • Alert: Similar to badges but for more prominent notifications or messages