JBadge
Versatile badges for status indicators, labels, and counts.
Philosophy
"Small but clear markers of status and progress"
Badges are small but mighty—they convey status at a glance. Like the labels on Indonesia's infrastructure projects marking progress and completion, JBadge provides clear, immediate visual feedback about status, categories, and counts.
Basic Usage
<script setup lang="ts">
import { JBadge } from '@joko-ui/vue'
</script>
<template>
<JBadge>New</JBadge>
</template>Variants
Primary (Merah Presiden)
For primary status or featured items.
Primary<JBadge variant="primary">Primary</JBadge>Success (Hijau Pertumbuhan)
For completed, active, or positive status.
Success<JBadge variant="success">Success</JBadge>Warning (Kuning Hati-hati)
For pending, in-progress, or cautionary status.
Warning<JBadge variant="warning">Warning</JBadge>Error (Merah Bahaya)
For errors, failed, or critical status.
Error<JBadge variant="error">Error</JBadge>Neutral (Default)
For general labels and categories.
Neutral<JBadge variant="neutral">Neutral</JBadge>
<!-- or simply -->
<JBadge>Neutral</JBadge>Sizes
Badges come in three sizes for different contexts.
<JBadge size="sm">Small</JBadge>
<JBadge size="md">Medium (Default)</JBadge>
<JBadge size="lg">Large</JBadge>Shapes
Rounded (Default)
Fully rounded ends for a pill-like appearance.
Rounded<JBadge :rounded="true">Rounded</JBadge>
<!-- or simply -->
<JBadge>Rounded</JBadge>Square
More geometric, modern appearance.
Square<JBadge :rounded="false">Square</JBadge>Props API
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'success' | 'warning' | 'error' | 'neutral' | 'neutral' | Visual style and semantic meaning |
size | 'sm' | 'md' | 'lg' | 'md' | Badge size |
rounded | boolean | true | Fully rounded (pill) vs. square corners |
Common Use Cases
Status Indicators
<template>
<div class="project-card">
<h3>Infrastructure Project</h3>
<JBadge variant="success">Active</JBadge>
</div>
<div class="project-card">
<h3>Highway Construction</h3>
<JBadge variant="warning">In Progress</JBadge>
</div>
<div class="project-card">
<h3>Bridge Repair</h3>
<JBadge variant="error">Delayed</JBadge>
</div>
<div class="project-card">
<h3>Port Expansion</h3>
<JBadge variant="primary">Completed</JBadge>
</div>
</template>Labels & Categories
<template>
<article>
<h2>Article Title</h2>
<div class="tags">
<JBadge variant="neutral">Infrastructure</JBadge>
<JBadge variant="neutral">Development</JBadge>
<JBadge variant="neutral">Indonesia</JBadge>
</div>
</article>
</template>
<style scoped>
.tags {
display: flex;
gap: var(--joko-space-2);
flex-wrap: wrap;
}
</style>Notification Counts
<template>
<button class="notification-button">
<Bell :size="20" />
Notifications
<JBadge variant="error" size="sm">3</JBadge>
</button>
<button class="inbox-button">
<Mail :size="20" />
Inbox
<JBadge variant="primary" size="sm">12</JBadge>
</button>
</template>
<style scoped>
.notification-button,
.inbox-button {
display: inline-flex;
align-items: center;
gap: var(--joko-space-2);
}
</style>Table Status
<template>
<table>
<thead>
<tr>
<th>Project</th>
<th>Status</th>
<th>Progress</th>
</tr>
</thead>
<tbody>
<tr>
<td>Trans-Java Toll Road</td>
<td><JBadge variant="success">Completed</JBadge></td>
<td>100%</td>
</tr>
<tr>
<td>MRT Jakarta</td>
<td><JBadge variant="success">Operational</JBadge></td>
<td>100%</td>
</tr>
<tr>
<td>New Capital City</td>
<td><JBadge variant="warning">In Progress</JBadge></td>
<td>45%</td>
</tr>
</tbody>
</table>
</template>User Roles
<template>
<div class="user-list">
<div class="user">
<img src="/avatar1.jpg" alt="User" />
<span>Joko Widodo</span>
<JBadge variant="primary" size="sm">Admin</JBadge>
</div>
<div class="user">
<img src="/avatar2.jpg" alt="User" />
<span>Ma'ruf Amin</span>
<JBadge variant="success" size="sm">Moderator</JBadge>
</div>
<div class="user">
<img src="/avatar3.jpg" alt="User" />
<span>Guest User</span>
<JBadge variant="neutral" size="sm">Member</JBadge>
</div>
</div>
</template>Version Labels
<template>
<div class="feature">
<h3>
Dark Mode Support
<JBadge variant="primary" size="sm">New</JBadge>
</h3>
<p>Switch between light and dark themes.</p>
</div>
<div class="feature">
<h3>
API v2
<JBadge variant="warning" size="sm">Beta</JBadge>
</h3>
<p>Try our new REST API.</p>
</div>
<div class="feature">
<h3>
Old Dashboard
<JBadge variant="error" size="sm">Deprecated</JBadge>
</h3>
<p>This feature will be removed in v3.0.</p>
</div>
</template>Examples
Status Dashboard
<script setup>
const projects = [
{ name: 'Trans-Java Toll Road', status: 'completed', progress: 100 },
{ name: 'Jakarta-Bandung High Speed Rail', status: 'operational', progress: 100 },
{ name: 'Trans-Sumatra Toll Road', status: 'in-progress', progress: 67 },
{ name: 'New Capital City (IKN)', status: 'in-progress', progress: 45 },
]
const statusVariant = {
'completed': 'success',
'operational': 'primary',
'in-progress': 'warning',
'delayed': 'error'
}
</script>
<template>
<div class="dashboard">
<h2>Infrastructure Projects</h2>
<div class="project-grid">
<div
v-for="project in projects"
:key="project.name"
class="project-card"
>
<h3>{{ project.name }}</h3>
<div class="project-meta">
<JBadge :variant="statusVariant[project.status]">
{{ project.status }}
</JBadge>
<span class="progress">{{ project.progress }}%</span>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.dashboard {
padding: var(--joko-space-8);
}
.project-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: var(--joko-space-6);
margin-top: var(--joko-space-6);
}
.project-card {
padding: var(--joko-space-6);
background: var(--joko-white);
border: 1px solid var(--joko-neutral-200);
border-radius: var(--joko-rounded-lg);
}
.project-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: var(--joko-space-4);
}
.progress {
font-weight: var(--joko-font-semibold);
color: var(--joko-neutral-700);
}
</style>TypeScript
Full TypeScript support with exported types:
import type { JBadgeProps } from '@joko-ui/vue'
const badgeConfig: JBadgeProps = {
variant: 'success',
size: 'md',
rounded: true
}Accessibility
JBadge is designed with accessibility in mind:
- ✅ Semantic HTML — Uses
<span>element (inline) - ✅ High contrast — Meets WCAG AA standards
- ✅ Screen reader friendly — Text content is announced properly
- ✅ Not interactive — Badges are display-only (use buttons for actions)
Best Practices
✅ DO:
- Keep badge text short (1-2 words max)
- Use semantic variants appropriately
- Combine with icons when helpful
- Test color contrast in different themes
❌ DON'T:
- Make badges interactive (use buttons instead)
- Use badges for long text
- Rely only on color to convey meaning
- Use too many badges at once
Design Tokens
JBadge uses these design tokens. Override them for customization:
/* Colors - Primary */
--joko-red-100 /* Background */
--joko-red-800 /* Text */
/* Colors - Success */
--joko-success-100 /* Background */
--joko-success-800 /* Text */
/* Colors - Warning */
--joko-warning-100 /* Background */
--joko-warning-800 /* Text */
/* Colors - Error */
--joko-error-100 /* Background */
--joko-error-800 /* Text */
/* Colors - Neutral */
--joko-neutral-100 /* Background */
--joko-neutral-800 /* Text */
/* Spacing */
--joko-space-1 /* Padding Y (sm) */
--joko-space-2 /* Padding X (sm) */
--joko-space-3 /* Padding X (md) */
--joko-space-4 /* Padding X (lg) */
/* Typography */
--joko-font-sans /* Font family */
--joko-font-medium /* Font weight */
--joko-text-xs /* Font size (sm/md) */
--joko-text-sm /* Font size (lg) */
/* Border Radius */
--joko-rounded-md /* Square badges */
--joko-rounded-full /* Rounded badges */Related Components
Philosophy in Action
JBadge embodies all four pillars:
- 🚶 Blusukan — Clear, readable text with high contrast
- 🔄 Mental Revolusi — Clean, semantic variants
- 💪 Kerja — Immediate visual feedback at a glance
- 🌉 Infrastructure — Consistent design tokens across variants
"Small markers of big progress"
Every badge tells a story of status and progress.