No description
Find a file
2026-01-28 14:51:47 -03:00
.vscode Primeira Versão do Sistema de componentes Vue 2025-12-08 13:59:04 -03:00
dist bkp 2026-01-28 14:51:47 -03:00
public bkp 2026-01-27 14:48:51 -03:00
src bkp 2026-01-28 14:51:47 -03:00
.agent bkp 2026-01-27 15:51:54 -03:00
.gitignore adicionado dist 2026-01-03 18:08:35 -03:00
IA.md adiconado imput de porcentagem 2026-01-10 13:37:34 -03:00
index.html Primeira Versão do Sistema de componentes Vue 2025-12-08 13:59:04 -03:00
package.json bkp 2026-01-28 14:51:47 -03:00
pnpm-lock.yaml bkp 2026-01-27 12:07:22 -03:00
README.md adiconado imput de porcentagem 2026-01-10 13:37:34 -03:00
tsconfig.app.json Primeira Versão do Sistema de componentes Vue 2025-12-08 13:59:04 -03:00
tsconfig.build.json Primeira Versão do Sistema de componentes Vue 2025-12-08 13:59:04 -03:00
tsconfig.json chore: alinhar projeto às regras do agent 2026-01-02 21:16:50 -03:00
vite.config.ts Primeira Versão do Sistema de componentes Vue 2025-12-08 13:59:04 -03:00

eli-vue — Design System (Vue 3 + TypeScript)

Biblioteca de componentes Vue 3 (Design System) para reutilização em múltiplos projetos.

Este README foi escrito para humanos e IAs: ele descreve o objetivo do repositório, regras, estrutura, fluxo de contribuição, comandos e um roadmap de melhorias.

Fonte da verdade (regras)

As regras oficiais do repositório estão no arquivo .agent.

Antes de propor mudanças:

  • leia o .agent
  • procure padrões já existentes no código
  • atualize a documentação correspondente (README raiz e/ou README do componente)

Objetivos

  • consistência visual e comportamental
  • tipagem forte (TypeScript strict)
  • documentação em português
  • exemplos executáveis via playground

O que NÃO entra no contexto

  • node_modules/: dependências (não versionar; não usar como fonte da verdade)
  • dist/: gerado no build (não versionar)

Arquitetura do repositório

src/
  componentes/
    botao/
      EliBotao.vue
      index.ts
      README.md
    campo/
      EliInput.vue
      index.ts
      README.md
    indicador/
      EliBadge.vue
      index.ts
      README.md
    data_hora/
      EliDataHora.vue
      index.ts
      README.md
  tipos/
    botao.ts
    campo.ts
    indicador.ts
    index.ts
  playground/
    App.vue
    *.playground.vue
  index.ts

Convenções (nomenclatura)

  • Componentes usam prefixo Eli (ex.: EliBotao, EliInput).
  • Pastas preferem português (ex.: src/componentes/botao, src/componentes/campo).
  • Tipos compartilhados ficam em src/tipos/.
  • Sem TSX; padrão SFC: <template> + <script lang="ts"> + defineComponent.
  • any é proibido.

Instalação

pnpm add eli-vue

Observação: vue e vuetify são peerDependencies.

Instalação (projeto consumidor já usa Vuetify)

Se o seu projeto já está configurado com Vuetify 3, basta instalar este pacote:

pnpm add eli-vue

Dica: mantenha vue e vuetify atualizados dentro das faixas suportadas.

Uso

1) Registro global (plugin)

import { createApp } from "vue";
import EliVue from "eli-vue";

import App from "./App.vue";

createApp(App).use(EliVue).mount("#app");

Exemplo completo (main.ts) — com Vuetify 3

Este é o modelo recomendado para projetos consumidores (Vite + Vue 3) que já usam Vuetify 3:

import { createApp } from "vue";
import App from "./App.vue";

// Vuetify
import "vuetify/styles";
import { createVuetify } from "vuetify";

// eli-vue (Design System)
import EliVue from "eli-vue";
import "eli-vue/dist/eli-vue.css";

const vuetify = createVuetify({
  // opcional: componentes/directives/tema do seu projeto
});

createApp(App)
  .use(vuetify)
  .use(EliVue)
  .mount("#app");

Nota: o eli-vue não cria nem configura Vuetify; ele assume que o consumidor já tem Vuetify.

2) Importação direta de componentes

import { EliBotao, EliInput, EliBadge, EliDataHora } from "eli-vue";

Exemplos rápidos de uso

EliBotao

<template>
  <EliBotao @click="salvar">Salvar</EliBotao>
</template>

EliInput (v-model)

<template>
  <EliInput v-model="nome" label="Nome" placeholder="Digite seu nome" />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const nome = ref("");
    return { nome };
  },
});
</script>

EliInput (porcentagem)

Use type="porcentagem" quando precisar de um campo numérico com sufixo % embutido.

<template>
  <EliInput v-model="taxa" type="porcentagem" label="Taxa" placeholder="0,00" />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const taxa = ref("");
    return { taxa };
  },
});
</script>

EliBadge

<template>
  <EliBadge badge="3">
    <v-icon>mdi-bell</v-icon>
  </EliBadge>
</template>

EliDataHora

Entrada/saída sempre em ISO 8601.

  • Aceita UTC absoluto (Z) ou com offset.
  • Emite ISO com offset local.
<template>
  <EliDataHora v-model="agendamento" rotulo="Agendamento" />
  <EliDataHora v-model="nascimento" modo="data" rotulo="Nascimento" />
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import { EliDataHora } from "eli-vue";

export default defineComponent({
  components: { EliDataHora },
  setup() {
    const agendamento = ref<string | null>("2026-01-09T16:15:00Z");
    const nascimento = ref<string | null>("2026-01-09T00:00:00-03:00");
    return { agendamento, nascimento };
  },
});
</script>

Troubleshooting (problemas comuns)

1) "Failed to resolve component" / componente não registrado

Você provavelmente esqueceu de:

  • usar o plugin: app.use(EliVue)
  • ou importar e registrar o componente localmente

2) Estilos não aplicam / layout estranho

Confirme que o consumidor importou:

  • vuetify/styles
  • eli-vue/dist/eli-vue.css

3) Ícones não aparecem

Alguns exemplos usam <v-icon> com Material Design Icons. O eli-vue não instala ícones no seu projeto.

  • garanta que o seu projeto consumidor está configurado com o pacote de ícones desejado (ex.: MDI)
  • ou substitua o conteúdo do slot por outro elemento

Exemplo de composição (pipeline estilo Trello)

O caso mais comum no gestor de oportunidades e propostas comerciais é compor UI a partir de componentes básicos. Exemplo: um pipeline em colunas (estilo Trello/Kanban) com cards de oportunidades.

Este exemplo usa Vuetify para layout/containers e o eli-vue para inputs, botões e indicadores.

<template>
  <v-container class="py-6">
    <div class="toolbar">
      <h2 class="text-h6">Pipeline de Oportunidades</h2>
      <EliInput
        v-model="filtro"
        label="Buscar"
        placeholder="Cliente, proposta, valor..."
        density="compact"
      />
      <EliBotao @click="criarOportunidade">Nova oportunidade</EliBotao>
    </div>

    <div class="colunas">
      <section
        v-for="coluna in colunas"
        :key="coluna.id"
        class="coluna"
      >
        <header class="coluna-header">
          <strong>{{ coluna.titulo }}</strong>
          <EliBadge :badge="coluna.itens.length" radius="pill" />
        </header>

        <div class="cards">
          <v-card
            v-for="item in itensFiltrados(coluna.itens)"
            :key="item.id"
            class="card"
            variant="outlined"
          >
            <v-card-title class="d-flex justify-space-between align-center">
              <span class="text-subtitle-2">{{ item.titulo }}</span>
              <EliBadge
                v-if="item.alerta"
                dot
                color="error"
                :visible="true"
              >
                <span />
              </EliBadge>
            </v-card-title>

            <v-card-text class="text-body-2">
              <div><strong>Cliente:</strong> {{ item.cliente }}</div>
              <div><strong>Valor:</strong> {{ item.valor }}</div>
              <div><strong>Vencimento:</strong> {{ item.vencimento }}</div>
            </v-card-text>

            <v-card-actions>
              <EliBotao variant="text" @click="abrir(item)">Abrir</EliBotao>
              <EliBotao variant="text" color="secondary" @click="editar(item)">
                Editar
              </EliBotao>
            </v-card-actions>
          </v-card>
        </div>
      </section>
    </div>
  </v-container>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import { EliBadge, EliBotao, EliInput } from "eli-vue";

type Oportunidade = {
  id: string;
  titulo: string;
  cliente: string;
  valor: string;
  vencimento: string;
  alerta?: boolean;
};

type Coluna = {
  id: string;
  titulo: string;
  itens: Oportunidade[];
};

export default defineComponent({
  name: "PipelineExemplo",
  components: { EliBadge, EliBotao, EliInput },
  setup() {
    const filtro = ref("");

    const colunas = ref<Coluna[]>([
      {
        id: "novo",
        titulo: "Novo",
        itens: [
          {
            id: "1",
            titulo: "Proposta #1024",
            cliente: "ACME Ltda",
            valor: "R$ 12.500,00",
            vencimento: "10/01/2026",
            alerta: true,
          },
        ],
      },
      {
        id: "negociacao",
        titulo: "Negociação",
        itens: [
          {
            id: "2",
            titulo: "Oportunidade #204",
            cliente: "Empresa X",
            valor: "R$ 8.000,00",
            vencimento: "15/01/2026",
          },
        ],
      },
      {
        id: "ganho",
        titulo: "Ganho",
        itens: [],
      },
    ]);

    function itensFiltrados(itens: Oportunidade[]) {
      const q = filtro.value.trim().toLowerCase();
      if (!q) return itens;
      return itens.filter((i) =>
        `${i.titulo} ${i.cliente} ${i.valor}`.toLowerCase().includes(q)
      );
    }

    function criarOportunidade() {
      // aqui você abriria um modal / rota de criação
    }

    function abrir(item: Oportunidade) {
      // aqui você navega para detalhes da oportunidade
    }

    function editar(item: Oportunidade) {
      // aqui você abre edição
    }

    return {
      filtro,
      colunas,
      itensFiltrados,
      criarOportunidade,
      abrir,
      editar,
    };
  },
});
</script>

<style scoped>
.toolbar {
  display: grid;
  grid-template-columns: 1fr minmax(260px, 420px) auto;
  gap: 12px;
  align-items: center;
  margin-bottom: 16px;
}

.colunas {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.coluna {
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 12px;
  padding: 12px;
  background: rgba(0, 0, 0, 0.02);
}

.coluna-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.cards {
  display: grid;
  gap: 12px;
}

.card {
  border-radius: 12px;
}

@media (max-width: 720px) {
  .toolbar {
    grid-template-columns: 1fr;
  }
}
</style>

Como rodar localmente

Playground

pnpm dev

O playground (src/playground) valida visualmente variações e interações.

Build da lib + geração de tipos

pnpm run build

Gera dist/ (artefatos de build) e dist/types (declarações .d.ts).

Guia rápido para IAs (antes de codar)

  1. Leia .agent e este README.
  2. Busque padrões antes de criar API nova (props/emits/slots).
  3. Não use any.
  4. Centralize tipos em src/tipos/.
  5. Ao mudar API/comportamento:
    • atualize o README.md do componente
    • atualize ou crie um *.playground.vue
  6. Rode pnpm run build antes de finalizar.

Como criar/alterar um componente (checklist)

  1. Criar pasta em src/componentes/<nome_em_portugues>/
  2. Criar EliNomeDoComponente.vue com defineComponent + comentários úteis
  3. Criar index.ts com re-export (ex.: export { default as EliX } from './EliX.vue')
  4. Criar README.md do componente (API, exemplos, casos de borda, A11y)
  5. Criar playground em src/playground/<nome>.playground.vue (mín. 3 variações)
  6. Exportar no src/index.ts

Critérios de aceite (qualidade)

  • pnpm run build passa (inclui vue-tsc)
  • zero any
  • defineComponent em todos os componentes
  • README do componente atualizado quando API mudar
  • playground demonstrando variações + interação

Roadmap de melhorias (a aplicar)

Curto prazo (qualidade / consistência)

  • Padronizar comentários úteis em todos os componentes (explicar decisões e estados)
  • Tipar emits com validação de payload (quando houver)
  • Consolidar nomenclatura de props/eventos em português (avaliar breaking changes)

Médio prazo (DX + segurança)

  • Adicionar ESLint + Prettier e regras (incluindo proibição de any)
  • Adicionar testes unitários com Vitest + @vue/test-utils
  • Criar pipeline de CI rodando pnpm run build

Longo prazo (docs e maturidade)

  • Documentação visual (Storybook ou VitePress)
  • Tokens de design (cores/spacing) e guideline de acessibilidade