Appearance
@carrot/design-vue-badges
Vue 3 badge components for the Carrot Design System. Provides label badges, notification counts, and status dots.
Installation
ts
import { CarrotBadge, CarrotBadgeCount, CarrotDot } from "@carrot/design-vue-badges";Requires the CSS layer from @carrot/design-components-badges.
Components
CarrotBadge
Label badge with variant styling, auto-color generation, and optional dismiss button.
Usage
vue
<!-- Basic -->
<CarrotBadge label="New" />
<!-- Variants -->
<CarrotBadge label="Active" variant="success" />
<CarrotBadge label="Warning" variant="warning-subtle" />
<CarrotBadge label="Outline" variant="outline" />
<!-- Auto-colored genre pills -->
<CarrotBadge label="Electronic" auto-color />
<CarrotBadge label="Jazz" auto-color />
<CarrotBadge label="Hip Hop" auto-color />
<!-- Custom colors -->
<CarrotBadge label="Custom" bg-color="#ff6b6b" />
<!-- Interactive -->
<CarrotBadge label="Click me" interactive @click="handleClick" />
<!-- Dismissible -->
<CarrotBadge label="Removable" dismissible @dismiss="handleRemove" />
<!-- With icons -->
<CarrotBadge label="Tagged">
<template #left><TagIcon /></template>
</CarrotBadge>
<!-- Sizes -->
<CarrotBadge label="Small" size="sm" />
<CarrotBadge label="Large" size="lg" />
<!-- Shape -->
<CarrotBadge label="Square" :pill="false" square />Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | required | Badge text content |
variant | BadgeVariant | "accent-subtle" | Visual variant |
size | BadgeSize | "md" | sm · md · lg |
pill | boolean | true | Full border radius |
square | boolean | false | Small border radius |
interactive | boolean | false | Button role + hover state |
dismissible | boolean | false | Show remove button, emit dismiss |
autoColor | boolean | false | Deterministic color from label text |
bgColor | string | — | Override background color |
fgColor | string | — | Override text color (auto-contrasted from bgColor) |
Events
| Event | Payload | Description |
|---|---|---|
dismiss | — | Remove button clicked |
Slots
| Slot | Description |
|---|---|
left | Leading icon |
right | Trailing icon (hidden when dismissible) |
dismiss-icon | Custom dismiss button content (default: ×) |
CarrotBadgeCount
Notification count badge — works standalone (inline) or anchored to a child element.
Usage
vue
<!-- Inline count -->
<CarrotBadgeCount :count="5" />
<!-- Overflow -->
<CarrotBadgeCount :count="150" :max="99" />
<!-- Renders: "99+" -->
<!-- Anchored to an icon/button -->
<CarrotBadgeCount :count="3">
<BellIcon />
</CarrotBadgeCount>
<!-- Pulse on change -->
<CarrotBadgeCount :count="unreadCount" pulse />
<!-- Show zero -->
<CarrotBadgeCount :count="0" :hide-zero="false" />
<!-- Custom styling -->
<CarrotBadgeCount :count="7" variant="accent" bg-color="#7c5cff" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | required | The count to display |
max | number | 99 | Overflow threshold (shows max+) |
variant | BadgeVariant | "danger" | Visual variant |
size | BadgeSize | "sm" | Size preset |
hideZero | boolean | true | Hide badge when count is 0 |
pulse | boolean | false | Pulse animation on count change |
bgColor | string | — | Override background color |
fgColor | string | — | Override text color |
Slots
| Slot | Description |
|---|---|
default | Anchor element — when provided, count positions as superscript |
CarrotDot
Minimal status dot indicator.
Usage
vue
<!-- Basic -->
<CarrotDot />
<!-- Variants -->
<CarrotDot variant="success" aria-label="Online" />
<CarrotDot variant="danger" aria-label="Error" />
<!-- Pulsing (live indicator) -->
<CarrotDot variant="success" pulse aria-label="Live" />
<!-- Custom color -->
<CarrotDot color="#ff6b6b" aria-label="Custom status" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | BadgeVariant | "accent" | Visual variant |
color | string | — | Override dot color |
pulse | boolean | false | Pulsing animation |
ariaLabel | string | — | Accessible label (sets role="img", otherwise presentation) |
Dependencies
| Package | Purpose |
|---|---|
@carrot/core | ColorFromString for auto-color and contrast |
@carrot/design-components-badges | CSS tokens + generated styles |
Build
bash
npm run buildBuilt with Vite + vite-plugin-dts. Outputs ES module with TypeScript declarations.
Usage Guide
Setup
ts
import { CarrotBadge, CarrotBadgeCount, CarrotDot } from "@carrot/design-vue-badges";
import "@carrot/design-components-badges";CarrotBadge
Status and variant badges
vue
<script setup lang="ts">
import { CarrotBadge } from "@carrot/design-vue-badges";
</script>
<template>
<CarrotBadge label="Active" variant="success" />
<CarrotBadge label="Pending" variant="warning-subtle" />
<CarrotBadge label="Archived" variant="muted" />
<CarrotBadge label="Error" variant="danger" />
</template>Auto-colored genre/tag pills
vue
<script setup lang="ts">
import { CarrotBadge } from "@carrot/design-vue-badges";
const genres = ["Electronic", "Jazz", "Hip Hop", "Classical", "Rock"];
</script>
<template>
<!-- Each badge gets a unique deterministic color derived from its label -->
<div style="display: flex; gap: 6px; flex-wrap: wrap">
<CarrotBadge v-for="genre in genres" :key="genre" :label="genre" auto-color />
</div>
</template>Dismissible filter chips
vue
<script setup lang="ts">
import { CarrotBadge } from "@carrot/design-vue-badges";
import { ref } from "vue";
const activeFilters = ref(["Electronic", "Live", "2024"]);
function removeFilter(filter: string) {
activeFilters.value = activeFilters.value.filter((f) => f !== filter);
}
</script>
<template>
<div style="display: flex; gap: 6px">
<CarrotBadge
v-for="filter in activeFilters"
:key="filter"
:label="filter"
dismissible
@dismiss="removeFilter(filter)"
/>
</div>
</template>CarrotBadgeCount
Notification bell with count
vue
<script setup lang="ts">
import { CarrotBadgeCount } from "@carrot/design-vue-badges";
import { ref } from "vue";
const unreadCount = ref(7);
</script>
<template>
<!-- Count anchors as superscript over the icon -->
<CarrotBadgeCount :count="unreadCount" pulse>
<BellIcon />
</CarrotBadgeCount>
<!-- Standalone inline count -->
<span>Notifications</span>
<CarrotBadgeCount :count="unreadCount" />
</template>CarrotDot
Live status indicator
vue
<script setup lang="ts">
import { CarrotDot } from "@carrot/design-vue-badges";
defineProps<{ isLive: boolean }>();
</script>
<template>
<div style="display: flex; align-items: center; gap: 6px">
<CarrotDot :variant="isLive ? 'success' : 'muted'" :pulse="isLive" :aria-label="isLive ? 'Live' : 'Offline'" />
<span>{{ isLive ? "Live" : "Offline" }}</span>
</div>
</template>Common Patterns
Tag list with overflow
vue
<script setup lang="ts">
import { CarrotBadge } from "@carrot/design-vue-badges";
import { CarrotOverflowRow } from "@carrot/design-vue-core";
const tags = [
{ id: 1, label: "House" },
{ id: 2, label: "Electronic" },
{ id: 3, label: "Minimal" },
{ id: 4, label: "Deep" },
];
</script>
<template>
<CarrotOverflowRow :items="tags">
<template #item="{ item }">
<CarrotBadge :label="item.label" auto-color size="sm" />
</template>
<template #overflow="{ hiddenCount }">
<CarrotBadge :label="`+${hiddenCount}`" variant="muted" size="sm" />
</template>
</CarrotOverflowRow>
</template>