Badge
Marcador compacto de uma linha para rotular, classificar ou contar. Não é botão, não é chip, não é alerta.
Regras: cantos retos (pill apenas em BadgeCount), IBM Plex Mono uppercase por padrão, sem hover no badge inteiro — só no __dismiss interno.
Uso
<script setup lang="ts">
import { Badge, BadgeCount, BadgeDot } from '@halfbyte-labs/maka'
</script>
<template>
<Badge tone="success" dot>Ativo</Badge>
<Badge family="soft" tone="warning" dismissible @dismiss="removeFilter">Cliente: HalfByte</Badge>
<BadgeCount :value="7" tone="blue" />
</template>Família × Tonalidade
Família define o peso visual; tonalidade carrega o significado.
Solid — máximo destaque
Outline — metadado calmo
Soft — tabelas e listas densas (padrão recomendado)
<!-- Solid: hero, card destacado, status crítico -->
<Badge family="solid" tone="danger">Falhou</Badge>
<!-- Outline: Draft, v1.2, Beta — metadado calmo -->
<Badge family="outline" tone="black">Beta</Badge>
<!-- Soft: item de tabela, lista densa — padrão -->
<Badge family="soft" tone="success">Ativo</Badge>| Contexto | Família recomendada |
|---|---|
| Hero / marketing / CTA | solid (geralmente lime + display) |
| Card destacado, status crítico | solid |
| Item de tabela / lista densa | soft |
| Filtros ativos removíveis | soft + dismissible |
Tag de metadado calmo (Beta, v1.2) | outline |
| Sobre fundo colorido | outline ou solid white |
Tamanhos
<Badge size="xs">XS</Badge> <!-- inline em labels, tabelas densas -->
<Badge size="sm">SM</Badge> <!-- padrão — status em listas, cards -->
<Badge size="md">MD</Badge> <!-- headers de card, com ícone -->
<Badge size="lg">LG</Badge> <!-- pricing tier, marketing hero -->Tipografia
<Badge type="mono">Ativo</Badge> <!-- padrão — status, tags -->
<Badge type="display" tone="lime">Pro</Badge> <!-- marketing, pricing -->
<Badge type="body" family="soft">Cliente: HalfByte</Badge> <!-- filtros com valor humano -->type | Font | Uso |
|---|---|---|
mono | JetBrains Mono · uppercase | Status, tags, taxonomia — padrão |
display | Space Grotesk · uppercase | Marketing, pricing, hero |
body | Plus Jakarta Sans · sem caps | Filtros ativos com valor legível |
Status dot
<Badge family="soft" tone="success" dot>Online</Badge>
<Badge family="soft" tone="danger" dot>Offline</Badge>
<!-- Pulse APENAS para estado genuinamente ao vivo -->
<Badge family="solid" tone="blue" dot pulse>Ao vivo</Badge>Regra:
pulseé exclusivo de streaming / monitoramento em tempo real. Não anime badges parados.
Com ícone
<Badge family="soft" tone="success" size="md">
<template #icon>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
<polyline points="1,6 4.5,9.5 11,2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"/>
</svg>
</template>
Verificado
</Badge>Use o slot #icon para SVGs monocromáticos com stroke="currentColor". Nunca emoji ou unicode.
Dismissível (filtros ativos)
<Badge
family="soft"
type="body"
tone="blue"
dismissible
dismiss-label="Remover filtro: Cliente HalfByte"
@dismiss="removeFilter('cliente')"
>
Cliente: HalfByte
</Badge>- Use
type="body"(sem uppercase) para valores legíveis comoCliente: HalfByte dismiss-labeldeve descrever o que está sendo removido, não apenas "Fechar"- O evento
@dismissé emitido após o fade-out de 160ms
BadgeCount
Pill exclusivo para contagens. Pill (radius 999px) é a única exceção à regra de canto reto.
<BadgeCount :value="3" tone="blue" /> <!-- → "3" -->
<BadgeCount :value="100" tone="blue" /> <!-- → "99+" -->
<BadgeCount :value="2400" tone="blue" /> <!-- → "2.4K" -->
<BadgeCount :value="9900" tone="danger" /> <!-- → "9.9K" -->
<BadgeCount :value="3" tone="danger" size="lg" />Regra: nunca mostre
count: 0. Esconda oBadgeCountcomv-if="count > 0".
BadgeDot
Bolinha 8×8 sem texto — sinaliza "tem coisa nova". Sempre aria-hidden="true".
<button aria-label="Notificações, com novidades" style="position: relative">
<BellIcon />
<BadgeDot tone="blue" style="position: absolute; top: -2px; right: -2px" />
</button>Use halo-color para combinar com o fundo do container (cria o halo de separação):
<!-- BadgeDot sobre fundo preto -->
<BadgeDot tone="danger" halo-color="#111114" />Props — Badge
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
family | "solid" | "outline" | "soft" | "solid" | Peso visual |
tone | "black" | "blue" | "lime" | "cyan" | "white" | "gray" | "success" | "warning" | "danger" | "info" | "black" | Cor e significado |
size | "xs" | "sm" | "md" | "lg" | "sm" | Tamanho |
type | "mono" | "display" | "body" | "mono" | Família tipográfica |
dot | boolean | false | Exibe status dot à esquerda |
pulse | boolean | false | Anima o dot (requer dot) — apenas para "live" |
dismissible | boolean | false | Exibe botão "×" |
dismiss-label | string | "Remover" | aria-label do botão dismiss |
as | "span" | "mark" | "output" | "span" | Elemento semântico |
aria-label | string | — | Label acessível (use para siglas: aria-label="Novo") |
Evento: @dismiss — emitido 160ms após o clique no "×" (após o fade).
Slot #icon: SVG monocromático com stroke="currentColor".
Props — BadgeCount
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
value | number | string | — | Valor. Números >99 viram "99+". Strings são exibidas literalmente. |
tone | BadgeTone | "blue" | Tonalidade (usa família solid) |
size | "sm" | "lg" | "sm" | Tamanho |
Props — BadgeDot
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
tone | "blue" | "danger" | "lime" | "blue" | Cor do dot |
halo-color | string | var(--colors-bg) | Cor do halo (deve combinar com o fundo) |
Boas práticas
<!-- ✅ 1 palavra, semântica com texto -->
<Badge family="soft" tone="success" dot>Ativo</Badge>
<Badge family="soft" tone="danger" dot>Falhou</Badge>
<!-- ✅ Lime para destaque marketing — pontual -->
<Badge family="solid" tone="lime" type="display" size="lg">Pro</Badge>
<!-- ✅ Outline para metadado calmo -->
<Badge family="outline" tone="black">Beta</Badge>
<Badge family="outline" tone="black">v1.2.0</Badge>
<!-- ✅ Count com v-if para esconder zero -->
<BadgeCount v-if="unread > 0" :value="unread" tone="blue" />
<!-- ❌ Frase como conteúdo -->
<Badge>Status atual do usuário</Badge>
<!-- ❌ Não misture lime com success — são cores diferentes -->
<Badge tone="lime">Aprovado</Badge> <!-- errado — lime é detail/brand -->
<Badge tone="success">Aprovado</Badge> <!-- correto -->
<!-- ❌ Solid danger repetido em lista vira ruído -->
<Badge family="solid" tone="danger">Vencida</Badge> <!-- só para o mais crítico -->
<Badge family="soft" tone="danger">Vencida</Badge> <!-- use soft em listas -->