# EliBotao

**Componente base de botão do design system**

O `EliBotao` encapsula o `v-btn` do Vuetify para aplicar padrões visuais, acessibilidade e comportamentos esperados em toda a aplicação.

> ⚠️ **Nunca use `v-btn` diretamente fora do design system.**
> Utilize sempre o `EliBotao`.

---

## Visão geral

O `EliBotao` oferece uma API simples e tipada para botões, controlando atributos, listeners e estilos por padrão. Foi projetado para:

* Garantir consistência visual e de comportamento;
* Facilitar a adoção de boas práticas de A11y;
* Permitir repasse transparente de atributos e listeners ao `v-btn` interno.

### Principais decisões de implementação

* `inheritAttrs: false` — o componente faz `v-bind="$attrs"` manualmente no `v-btn` filho.
* Slot padrão para conteúdo (texto, ícones ou markup).
* Classes base aplicadas: `text-none pt-1` (podem ser sobrescritas via `class`).

---

## Tipagem (TypeScript)

```ts
type BotaoVariant = 'elevated' | 'flat' | 'outlined' | 'text' | 'tonal'
type BotaoSize = 'x-small' | 'small' | 'default' | 'large'

interface EliBotaoProps {
  color?: string
  variant?: BotaoVariant
  size?: BotaoSize
  disabled?: boolean
  loading?: boolean
}
```

---

## Props

| Prop       | Tipo           | Default      | Descrição                                                         |
| ---------- | -------------- | ------------ | ----------------------------------------------------------------- |
| `color`    | `string`       | `"primary"`  | Cor visual do botão (usa as cores registradas no Vuetify).        |
| `variant`  | `BotaoVariant` | `"elevated"` | Variante visual: `elevated`, `flat`, `outlined`, `text`, `tonal`. |
| `size`     | `BotaoSize`    | `"default"`  | Tamanho do botão (`x-small`, `small`, `default`, `large`).        |
| `disabled` | `boolean`      | `false`      | Desabilita interação e aplica estilo inativo.                     |
| `loading`  | `boolean`      | `false`      | Exibe indicador de carregamento e bloqueia interação.             |

### Notas sobre props

* **`color`**: utilize as cores definidas na configuração do Vuetify para manter consistência.
* **`disabled`** e **`loading`**: quando `true`, o botão deixa de responder a eventos e apresenta feedback visual apropriado.

---

## Repasso de atributos e listeners

O componente define `inheritAttrs: false` e aplica `v-bind="$attrs"` ao `v-btn` interno. Isso implica que:

1. **Atributos HTML** (ex.: `type`, `aria-label`, `class`, `style`) passados para `<EliBotao>` serão aplicados ao `v-btn` filho.
2. **Listeners** (ex.: `@click`, `@mouseover`) também fazem parte de `$attrs` no Vue 3 e são repassados ao `v-btn` — use o componente como se estivesse escutando eventos diretamente no botão.

**Exemplo:**

```vue
<EliBotao @click="onClick" type="button">Salvar</EliBotao>
```

O `onClick` será invocado quando o `v-btn` emitir o evento.

---

## Slot

O `EliBotao` expõe um slot padrão para o conteúdo do botão. Pode ser texto, ícone ou markup mais complexo.

Exemplos:

```vue
<EliBotao>Salvar</EliBotao>

<EliBotao>
  <v-icon left>mdi-check</v-icon>
  Salvar
</EliBotao>

<EliBotao>
  <span>Texto com <strong>destaque</strong></span>
</EliBotao>
```

---

## Exemplo de uso completo

```vue
<template>
  <EliBotao
    color="primary"
    variant="elevated"
    :loading="isSaving"
    aria-label="Salvar formulário"
    @click="salvar"
    type="button"
  >
    <v-icon left>mdi-content-save</v-icon>
    Salvar
  </EliBotao>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import EliBotao from '@/componentes/botao/EliBotao.vue'

export default defineComponent({
  components: { EliBotao },
  setup() {
    const isSaving = ref(false)
    function salvar() {
      // lógica de salvamento
    }
    return { salvar, isSaving }
  }
})
</script>
```

---

## Acessibilidade (A11y)

* Sempre forneça `aria-label` quando o botão exibir apenas um ícone.
* Para botões de ação em formulários, defina explicitamente `type="button"` ou `type="submit"` conforme apropriado.
* Evite usar apenas `color` para transmitir significado; combine com texto e atributos ARIA quando necessário.

---

## Boas práticas

* **Consistência visual**: não aplique estilos inline no lugar de tokens do design system — prefira classes e variáveis do Vuetify.
* **Overrides de classe**: a classe padrão `text-none pt-1` pode ser sobrescrita via `class` em `$attrs` (ex.: `<EliBotao class="ma-2">`).
* **Estados**: gerencie `loading` e `disabled` no nível do componente pai quando necessário para evitar condições de corrida.

---

## Testes

O `EliBotao` é intencionalmente simples e fácil de testar:

* Monte o componente em testes unitários e verifique que `$attrs` é repassado ao `v-btn`.
* Asserte que `loading` exibe o spinner e que `disabled` impede emissão de eventos.

Exemplo (pseudocódigo):

```ts
const wrapper = mount(EliBotao, { attrs: { 'aria-label': 'Salvar', type: 'button' } })
expect(wrapper.findComponent({ name: 'v-btn' }).attributes('aria-label')).toBe('Salvar')
```

---

## Observações finais

* O componente foi projetado para ser um adaptador seguro para `v-btn`: aplica padrões do design system e centraliza comportamento comum.
* Se precisar estender o componente (por exemplo, adicionar variantes visuais específicas do produto), prefira criar wrappers ou classes utilitárias no design system ao invés de alterar o `EliBotao` diretamente.

---
