Skip to content
touchcn
Esc
navigateopen⌘Jpreview
On this page

Badge

A small status descriptor for labeling and counts.

A small status descriptor for labels and counts, in a set of semantic variants.

Installation

npx touchcn add badge

Usage

<tcn-badge variant="primary">New</tcn-badge>
<tcn-badge variant="success">Active</tcn-badge>
import { TcnBadge } from '@/components/ui/badge';

<TcnBadge variant="primary">New</TcnBadge>
<TcnBadge variant="success">Active</TcnBadge>
<script setup lang="ts">
import { TcnBadge } from '@/components/ui/badge';
</script>

<template>
  <TcnBadge variant="primary">New</TcnBadge>
  <TcnBadge variant="success">Active</TcnBadge>
</template>

Props

Prop Type Default Description
variant 'primary' | 'secondary' | 'success' | 'destructive' | 'neutral' 'primary' Visual style.
Source · Angular
export * from './tcn-badge';
import { Component, computed, ElementRef, inject, input } from '@angular/core';
import { cn } from '@touchcn/core';

export type TcnBadgeVariant = 'primary' | 'secondary' | 'success' | 'destructive' | 'neutral';

const base = 'inline-flex items-center justify-center rounded-full px-2 py-0.5 text-xs font-semibold leading-none';

const variantClass: Record<TcnBadgeVariant, string> = {
  primary: 'bg-[var(--color-primary)] text-[var(--color-on-primary)]',
  secondary: 'bg-[var(--color-secondary-container)] text-[var(--color-on-secondary-container)]',
  success: 'bg-[var(--color-success)] text-white',
  destructive: 'bg-[var(--color-destructive)] text-[var(--color-on-destructive)]',
  neutral: 'bg-[color-mix(in_srgb,var(--color-on-surface)_12%,transparent)] text-[var(--color-on-surface)]',
};

@Component({
  selector: 'tcn-badge',
  template: '<ng-content />',
  host: { '[class]': 'classes()' },
})
export class TcnBadge {
  private readonly authored = inject(ElementRef<HTMLElement>).nativeElement.getAttribute('class') ?? '';

  readonly variant = input<TcnBadgeVariant>('primary');

  protected readonly classes = computed(() => cn(base, variantClass[this.variant()], this.authored));
}
Source · React
export * from './tcn-badge';
import { forwardRef } from 'react';
import type { ComponentPropsWithoutRef } from 'react';
import { cn } from '@touchcn/core';

export type TcnBadgeVariant = 'primary' | 'secondary' | 'success' | 'destructive' | 'neutral';

const base = 'inline-flex items-center justify-center rounded-full px-2 py-0.5 text-xs font-semibold leading-none';

const variantClass: Record<TcnBadgeVariant, string> = {
  primary: 'bg-[var(--color-primary)] text-[var(--color-on-primary)]',
  secondary: 'bg-[var(--color-secondary-container)] text-[var(--color-on-secondary-container)]',
  success: 'bg-[var(--color-success)] text-white',
  destructive: 'bg-[var(--color-destructive)] text-[var(--color-on-destructive)]',
  neutral: 'bg-[color-mix(in_srgb,var(--color-on-surface)_12%,transparent)] text-[var(--color-on-surface)]',
};

export interface TcnBadgeProps extends ComponentPropsWithoutRef<'span'> {
  variant?: TcnBadgeVariant;
}

export const TcnBadge = forwardRef<HTMLSpanElement, TcnBadgeProps>(function TcnBadge(
  { variant = 'primary', className, children, ...props },
  ref,
) {
  return (
    <span ref={ref} className={cn(base, variantClass[variant], className)} {...props}>
      {children}
    </span>
  );
});
Source · Vue
<script lang="ts">
export type TcnBadgeVariant = 'primary' | 'secondary' | 'success' | 'destructive' | 'neutral';

const base = 'inline-flex items-center justify-center rounded-full px-2 py-0.5 text-xs font-semibold leading-none';

const variantClass: Record<TcnBadgeVariant, string> = {
  primary: 'bg-[var(--color-primary)] text-[var(--color-on-primary)]',
  secondary: 'bg-[var(--color-secondary-container)] text-[var(--color-on-secondary-container)]',
  success: 'bg-[var(--color-success)] text-white',
  destructive: 'bg-[var(--color-destructive)] text-[var(--color-on-destructive)]',
  neutral: 'bg-[color-mix(in_srgb,var(--color-on-surface)_12%,transparent)] text-[var(--color-on-surface)]',
};
</script>

<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@touchcn/core';

const props = withDefaults(defineProps<{ variant?: TcnBadgeVariant }>(), { variant: 'primary' });

const classes = computed(() => cn(base, variantClass[props.variant]));
</script>

<template>
  <span :class="classes">
    <slot />
  </span>
</template>
export { default as TcnBadge } from './TcnBadge.vue';
export type { TcnBadgeVariant } from './TcnBadge.vue';

Last updated on July 24, 2026

Was this page helpful?