Badge

Displays a badge or a component that looks like a badge.

Examples

Basic

PropDefaultTypeDescription
label-stringThe label of the badge.
Preview
Code
Badge 4

Variant

PropDefaultTypeDescription
badgesoft{variant}The variant of the badge.
VariantDescription
softThe default variant.
solidThe solid variant.
outlineThe outline variant.
~The unstyle or base variant
Preview
Code
Soft BadgeSolid BadgeOutline BadgeBase Badge

Color

PropDefaultTypeDescription
badge{variant}-primary{variant}-{color}The color of the badge.
Preview
Code
Dynamic colors:
soft-primary (default)solid-pinkoutline-infosoft-successoutline-yellowsolid-erroroutline-indigo
Static colors:
soft-graysolid-blackoutline-white

Size

PropDefaultTypeDescription
sizexsstringAllows you to change the size of the input.

🚀 Adjust input size freely using any size, breakpoints (e.g., sm:sm, xs:lg), or states (e.g., hover:lg, focus:3xl).

Preview
Code
BadgeBadgeBadge

Icon

icon={icon} - add an icon to the badge.

Preview
Code
v1.2.0OfflineOnline

Closable

PropDefaultTypeDescription
closablefalsebooleanAdd a close icon to the badge.
Preview
Code
BadgeBadgeBadgeBadgeBadgeBadge

Slots

NamePropsDescription
default-The badge label.
Preview
Code
Evan You Anthony Fu Daniel Roe Sébastien Chopin Pooya Parsa Eduardo San Martin Morote Guillaume Chau

Events

Event NameDescription
@closeemit an event when the close icon is clicked. Use in conjunction with closable.

Presets

shortcuts/badge.ts
type BadgePrefix = 'badge'

export const staticBadge: Record<`${BadgePrefix}-${string}` | BadgePrefix, string> = {
  // config
  'badge-default-variant': 'badge-soft',
  'badge-close-icon': 'i-close',

  // base
  'badge': 'text-xs leading-tight py-0.3333333333333333em px-0.6666666666666666em gap-x-0.25em inline-flex items-center rounded-md font-medium text-brand',
  'badge-icon-base': 'text-1em',
  'badge-close': 'relative rounded-sm h-1.16em w-1.16em grid place-items-center -mr-0.375em hover:bg-brand/20 bg-transparent',
  'badge-close-icon-base': 'text-brand/75 group-hover:text-brand/90',

  // variants
  'badge-soft-gray': 'bg-muted text-muted n-gray-900 dark:n-gray-50 ring-1 ring-gray-700/10 dark:ring-gray-400/30',
  'badge-solid-black': 'bg-inverted text-inverted n-gray-300 dark:n-gray-600',
  'badge-outline-white': 'bg-base text-base ring-1 ring-base n-gray-600 dark:n-gray-300',
}

export const dynamicBadge: [RegExp, (params: RegExpExecArray) => string][] = [
  // variants
  [/^badge-solid(-(\S+))?$/, ([, , c = 'primary']) => `bg-${c}-100 dark:bg-${c}-800 n-${c}-700 dark:n-${c}-200`],
  [/^badge-soft(-(\S+))?$/, ([, , c = 'primary']) => `bg-${c}-50 n-${c}-700 dark:n-${c}-400 ring-1 ring-${c}-700/10 dark:bg-${c}-400/10 dark:ring-${c}-400/30`],
  [/^badge-outline(-(\S+))?$/, ([, , c = 'primary']) => `bg-transparent n-${c}-700 dark:n-${c}-400 ring-1 ring-${c}-700/10 dark:ring-${c}-400/30`],
]

export const badge = [
  ...dynamicBadge,
  staticBadge,
]

Props

types/badge.ts
export interface NBadgeProps {
  /**
   * Allows you to add `UnaUI` badge preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/badge.ts
   * @example
   * badge="solid-yellow"
   */
  badge?: string
  /**
   * Add a label to the badge.
   */
  label?: string
  /**
   * Display an icon on the left side of the badge,
   * this also allows you to add utility classes to customize icon.
   *
   * @example
   * icon="i-heroicons-information-circle text-green-500 dark:text-green-400 text-2xl"
   */
  icon?: string
  /**
   * Display `close` icon on the right side of the badge,
   *
   * @default false
   */
  closable?: boolean

  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/badge.ts
   */
  una?: {
    // base
    badgeDefaultVariant?: string
    badge?: string
    badgeIconBase?: string
    badgeClose?: string
    badgeCloseIconBase?: string

    // icons
    badgeCloseIcon?: string
  }
}

Components

Badge.vue
<script setup lang="ts">
import type { NBadgeProps } from '../../types'

import { computed } from 'vue'
import NIcon from './Icon.vue'

const props = withDefaults(defineProps<NBadgeProps>(), {
  una: () => ({
    badgeDefaultVariant: 'badge-default-variant',
  }),
})

const emit = defineEmits(['close'])

const badgeVariants = ['solid', 'soft', 'outline'] as const
const hasVariant = computed(() => badgeVariants.some(badgeVariants => props.badge?.includes(badgeVariants)))
const isBaseVariant = computed(() => props.badge?.includes('~'))
</script>

<template>
  <span
    :badge="badge"
    class="badge"
    :class="[
      !hasVariant && !isBaseVariant ? una?.badgeDefaultVariant : '',
      una?.badge,
    ]"
  >
    <NIcon
      v-if="icon"
      badge="icon-base"
      :class="una?.badgeIconBase"
      :name="icon"
    />

    <slot>
      {{ label }}
    </slot>

    <button
      v-if="closable"
      badge="close"
      :class="una?.badgeClose"
      group
      @click="emit('close')"
    >
      <NIcon
        :name="una?.badgeCloseIcon ?? 'badge-close-icon'"
        :class="una?.badgeCloseIconBase"
        badge="close-icon-base"
      />
      <span class="absolute -inset-0.25em" />
    </button>
  </span>
</template>