6.3 KiB
6.3 KiB
EliBadge
Componente base de badge do design system
O EliBadge encapsula o v-badge do Vuetify para aplicar padrões visuais, tipagem e comportamento previsível em toda a aplicação.
⚠️ Nunca use
v-badgediretamente fora do design system.
Utilize sempre oEliBadgepara manter consistência visual e compatibilidade entre versões do Vuetify.
Visão geral
O EliBadge foi projetado para:
- Garantir consistência visual no uso de badges;
- Fornecer uma API tipada (TypeScript) e com autocomplete;
- Controlar corretamente a exibição do badge sem afetar o conteúdo principal;
- Permitir presets semânticos de
border-radiuse valores CSS customizados; - Repassar atributos e listeners de forma transparente ao
v-badge.
Principais decisões de implementação
inheritAttrs: false— o componente fazv-bind="$attrs"manualmente nov-badge.- Uso de CSS Variable (
--eli-badge-radius) para controlar oborder-radius. - Presets tipados para
radius+ fallback para valores CSS livres. - O slot padrão nunca é removido: apenas o badge é condicional.
Tipagem (TypeScript)
type LocalBadge =
| "top right"
| "right center"
| "bottom right"
| "top center"
| "bottom center"
| "top left"
| "left center"
| "bottom left";
type Offset = "-20" | "-15" | "-10" | "-5" | "0" | "20" | "15" | "10" | "5";
type BadgeRadiusPreset = "suave" | "pill";
type CssLength = `${number}px` | `${number}rem` | `${number}%` | "0";
---
## Props
| Prop | Tipo | Default | Descrição |
| ---------- | -------------------------------- | ------------- | ---------------------------------------------- |
| `color` | `string` | `"primary"` | Cor visual do badge (Vuetify theme). |
| `location` | `LocalBadge` | `"top right"` | Posição do badge em relação ao conteúdo. |
| `offsetX` | `Offset` | `"0"` | Deslocamento horizontal. |
| `offsetY` | `Offset` | `"0"` | Deslocamento vertical. |
| `dot` | `boolean` | `false` | Exibe badge no formato de ponto. |
| `visible` | `boolean` | `true` | Controla a exibição do badge (slot permanece). |
| `badge` | `string \| number \| undefined` | `undefined` | Conteúdo textual ou numérico do badge. |
| `radius` | `BadgeRadiusPreset \| CssLength` | `"suave"` | Preset ou valor CSS de `border-radius`. |
Presets de radius
{
suave: "4px", // cantos levemente arredondados
pill: "10px", // cantos bem arredondados
}
---
Repasso de atributos e listeners
Como inheritAttrs: false e v-bind="$attrs" são usados:
1. Atributos HTML (ex.: type, aria-label, class, style) passados para <EliBadge> serão aplicados ao v-badge filho.
2. Listeners (ex.: @click) também são repassados ao v-badge — use o componente como se estivesse escutando eventos diretamente no v-badge.
Exemplo:
<EliBadge badge="3" aria-label="Notificações">
<v-icon>mdi-bell</v-icon>
</EliBadge>
---
Slot
O EliBadge expõe um slot padrão para o conteúdo que será "badged" — normalmente um ícone, avatar ou texto.
Exemplos:
<EliBadge badge="3">
<v-icon>mdi-bell</v-icon>
</EliBadge>
<EliBadge badge="Novo">
<button>Vistoria</button>
</EliBadge>
Se visible for false, o slot continua sendo renderizado (o badge some, mas o conteúdo permanece).
---
Exemplos de uso
Preset suave (padrão):
<EliBadge badge="5" radius="suave">
<v-icon>mdi-email</v-icon>
</EliBadge>
Preset pill (mais arredondado):
<EliBadge badge="99+" radius="pill">
<v-icon>mdi-chat</v-icon>
</EliBadge>
Valor custom:
<EliBadge badge="1" radius="0"> <!-- totalmente reto -->
<v-icon>mdi-alert</v-icon>
</EliBadge>
<EliBadge badge="8" radius="12px">
<v-icon>mdi-star</v-icon>
</EliBadge>
Esconder só o badge (manter conteúdo):
<EliBadge badge="Novo" :visible="false">
Vistoria
</EliBadge>
<!-- RENDERIZA: "Vistoria" (sem o indicador "Novo") -->
Mostrar dot (ponto):
<EliBadge dot :visible="true">
<img src="avatar.png" alt="Usuário"/>
</EliBadge>
---
Acessibilidade (A11y)
1. Forneça aria-label quando o badge transmitir informação importante sem texto adicional.
2. Evite usar cor sozinha para transmitir significado — combine com texto ou atributos ARIA.
3. Para badges que comunicam contagem (ex.: notificações), adicione aria-live ou texto alternativo
no componente pai conforme a necessidade do caso de uso.
---
Boas práticas
1. Prefira presets (suave, pill) para consistência visual; use valores custom apenas quando necessário.
2. Não aplique estilos inline que conflitem com tokens do design system; prefira classes e variáveis do Vuetify.
3. Documente o uso do visible e badge nos locais onde o componente for amplamente adotado.
4. Evite usar visible=false se você espera apenas esconder zero/empty — prefira lógica que passe badge = undefined ou :visible="count > 0".
---
Testes
Recomenda-se testar:
1. Renderização com badge presente e badge === undefined.
2. Comportamento de visible (assegurar que o slot continua visível quando visible=false).
3. dot true/false.
4. Aplicação da variável CSS (--eli-badge-radius) e que o border-radius interno do Vuetify muda conforme o radius.
5. $attrs repassados para o v-badge (por exemplo: aria-label, class).
Exemplo (pseudocódigo):
const wrapper = mount(EliBadge, {
props: { badge: '3' },
slots: { default: '<button>Inbox</button>' }
});
expect(wrapper.html()).toContain('Inbox');
expect(wrapper.findComponent({ name: 'v-badge' }).exists()).toBe(true);
---
Observações sobre Vuetify
1. O EliBadge usa seletor com `:deep(...)` para alterar o border-radius do elemento interno do `v-badge`. Se você atualizar o Vuetify, verifique os nomes de classe (`.v-badge__badge` / `.v-badge__content`) e ajuste o seletor se necessário.
2. Prop names do v-badge (ex.: location, offset-x, offset-y, content, dot) podem variar entre versões do Vuetify — reveja a docs da versão em uso se algo não for aplicado como esperado.