UIPackage
Menu

Framework

Change language

Boilerplate repo

Badge

badge ui
Boilerplate repo

Small inline label for status, counts, or tags — sits beside other content, not as a standalone control. Seven variants: `default`, `secondary`, `destructive`, `outline`, `success`, `warning`, `info`.

Also available for React ->

Installation

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/badge.json
Named registry: npx shadcn-vue@latest add @uipkge/badge Installs to: app/components/ui/badge/

Examples

Loading interactive previews…

Props

Name Type / Values Default Required
variant
'default''secondary''destructive''outline''success''warning''info'
optional
class HTMLAttributes['class'] optional
asChild boolean optional
as string | object optional

Used by

Files installed (3)

  • app/components/ui/badge/Badge.vue 0.9 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { reactiveOmit } from '@vueuse/core'
    import { Primitive } from 'reka-ui'
    import { cn } from '@/lib/utils'
    import { badgeVariants } from './badge.variants'
    
    // Inlined unions: SFC compiler can't extract runtime props from
    // `BadgeVariants['variant']` or reka-ui's PrimitiveProps.
    const props = withDefaults(
      defineProps<{
        variant?: 'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'info'
        class?: HTMLAttributes['class']
        asChild?: boolean
        as?: string | object
      }>(),
      {
        // Match React Badge (`span`) so badges stay valid inside paragraphs/inline text.
        as: 'span',
      },
    )
    
    const delegatedProps = reactiveOmit(props, 'class')
    </script>
    
    <template>
      <Primitive data-uipkge data-slot="badge" :class="cn(badgeVariants({ variant }), props.class)" v-bind="delegatedProps">
        <slot />
      </Primitive>
    </template>
  • app/components/ui/badge/badge.variants.ts 1.8 kB
    import type { VariantProps } from 'class-variance-authority'
    import { cva } from 'class-variance-authority'
    
    /**
     * Variant definitions live in their own file (rather than the package
     * `index.ts`) so consuming Vue SFCs can import without creating a circular
     * dependency through the index. See card.variants.ts for the canonical
     * example + the SSR symptom that motivated the split.
     */
    
    export const badgeVariants = cva(
      'inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors duration-200 overflow-hidden',
      {
        variants: {
          variant: {
            default: 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
            secondary: 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
            destructive:
              'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
            outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
            success:
              'border-transparent bg-success/10 text-success dark:text-success [a&]:hover:bg-success/20',
            warning:
              'border-transparent bg-warning/10 text-warning dark:text-warning [a&]:hover:bg-warning/20',
            info: 'border-transparent bg-info/10 text-info dark:text-info [a&]:hover:bg-info/20',
          },
        },
        defaultVariants: {
          variant: 'default',
        },
      },
    )
    
    export type BadgeVariants = VariantProps<typeof badgeVariants>
  • app/components/ui/badge/index.ts 0.3 kB
    export { default as Badge } from './Badge.vue'
    
    // Re-export variant API from the sibling file (kept separate to avoid the
    // Component.vue <-> index.ts circular import that broke dev SSR for Card).
    export { badgeVariants, type BadgeVariants } from './badge.variants'

Raw manifest: https://uipkge.dev/r/vue/badge.json