feat: componente padrao de botao
This commit is contained in:
parent
35f9d57ce7
commit
751857b170
7 changed files with 416 additions and 17 deletions
64
src/componentes/EliBotao/EliBotao.vue
Normal file
64
src/componentes/EliBotao/EliBotao.vue
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<v-btn
|
||||
:color="color"
|
||||
:variant="variant"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
:loading="loading"
|
||||
v-bind="$attrs"
|
||||
class="text-none pt-1"
|
||||
>
|
||||
<slot />
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from "vue";
|
||||
|
||||
type BotaoVariant =
|
||||
| "elevated"
|
||||
| "flat"
|
||||
| "outlined"
|
||||
| "text"
|
||||
| "tonal"
|
||||
|
||||
type BotaoSize =
|
||||
| "x-small"
|
||||
| "small"
|
||||
| "default"
|
||||
| "large"
|
||||
|
||||
export default defineComponent({
|
||||
name: "EliBotao",
|
||||
|
||||
inheritAttrs: false,
|
||||
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: "primary"
|
||||
},
|
||||
|
||||
variant: {
|
||||
type: String as PropType<BotaoVariant>,
|
||||
default: "elevated",
|
||||
},
|
||||
|
||||
size: {
|
||||
type: String as PropType<BotaoSize>,
|
||||
default: "default",
|
||||
},
|
||||
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
173
src/componentes/EliBotao/README.md
Normal file
173
src/componentes/EliBotao/README.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
# 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 '@/components/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.
|
||||
|
||||
---
|
||||
4
src/componentes/EliBotao/index.ts
Normal file
4
src/componentes/EliBotao/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import EliBotao from "./EliBotao.vue";
|
||||
|
||||
export { EliBotao };
|
||||
export default EliBotao;
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
Este é um componente de exemplo integrado com Vuetify.
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn color="primary" block>
|
||||
<v-btn color="primary" variant="elevated" block style="padding: 10px;">
|
||||
Botão Vuetify
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue