Skip to content
Versão preliminar. Cores, componentes e layout ainda vão mudar: falta receber o padrão de interface do TJES (template-basico-vue) e o manual de identidade visual.

BaseFileUpload ​

Recebe os anexos de um formulário: memória de cálculo, planilhas, fotos da obra. A pessoa arrasta os arquivos para a área ou usa o botão "Selecionar arquivos". Antes de qualquer erro, a área já diz o tipo e o tamanho aceitos; cada arquivo recusado aparece na lista com o motivo.

Memória de cálculo (obrigatório)

Arraste o arquivo para cá ou

PDF, até 20 MB

Use o PDF assinado pelo fiscal do contrato.

Fotos da obra (opcional)

Arraste os arquivos para cá ou

Imagem, até 10 MB

Uso ​

  • Use para anexar arquivos num formulário: memória de cálculo na medição, fotos no relatório de fiscalização, planilha no cadastro do contrato.
  • label diz o que se anexa ("Memória de cálculo"), não "Arquivo" ou "Anexo".
  • Informe accept e max-size sempre que houver regra. A área mostra a regra antes de errar ("PDF, até 20 MB") e o mesmo texto vale para o motivo da recusa. Prefira extensões (.pdf,.xlsx) a tipos MIME: elas aparecem melhor no texto.
  • Sem multiple, o campo guarda um arquivo; escolher outro substitui o atual, como no campo nativo. Com multiple, os arquivos novos entram no fim da lista.
  • v-model traz só os arquivos aceitos (File[]). Os recusados ficam na lista com erro até a pessoa removê-los ou escolher de novo, e chegam à tela pelo evento reject.
  • O componente não envia nada. A tela envia os arquivos do v-model ao salvar, ou mostra o envio em andamento com BaseFileItem (uploading, progress).
  • Use invalid para regras que só a tela confere, como um anexo obrigatório que faltou ao salvar.
  • Não coloque BaseFileUpload dentro de BaseField: o componente já tem legenda, ajuda e erro, e o BaseField criaria um segundo rótulo apontando para nenhum campo.

Regras e recusas ​

Arraste para a área abaixo um arquivo que não seja PDF, um PDF com mais de 1 MB ou o mesmo arquivo duas vezes.

Memória de cálculo da medição

Arraste os arquivos para cá ou

PDF, até 1 MB

SituaçãoMensagem na linha do arquivo
Tipo fora de accept"Tipo de arquivo não aceito. Envie PDF."
Acima de max-size"O arquivo tem 25 MB e passa do limite de 20 MB."; se o tamanho arredondado empatar com o limite, "O arquivo passa um pouco do limite de 20 MB."
Arquivo vazio (0 B)"O arquivo está vazio. Escolha outro."
Já está na lista"Este arquivo já está na lista."
Mais de um sem multiple"Este campo aceita um arquivo só. Escolha um por vez."

O mesmo arquivo é reconhecido pelo nome, tamanho e data de modificação.

Estados ​

Inválido

Arraste o arquivo para cá ou

PDF

Erro: Anexe a memória de cálculo assinada.

Aviso

Arraste o arquivo para cá ou

PDF

Atenção: A medição 28 foi enviada sem memória de cálculo.

Carregando

Arraste o arquivo para cá ou

PDF

  • memoria-calculo-28.pdf4 B
Desabilitado

Arraste o arquivo para cá ou

PDF

  • memoria-calculo-28.pdf4 B
Somente leitura
  • memoria-calculo-28.pdf4 B
  • planilha-vencedora-cf001.xlsx1 B
EstadoComo
PadrãoBorda tracejada; no hover e com o foco no botão, a borda fica azul
ArrastandoBorda contínua, fundo de seleção e o texto muda para "Solte para adicionar". Só arquivos ativam a área; texto ou link arrastado não muda nada
Inválidoinvalid, com invalid-text; sem texto, aparece "Anexe pelo menos um arquivo." A borda fica vermelha e a mensagem tem ícone
Avisowarn com warn-text; sem texto, o aviso não aparece
Carregandoloading: o botão continua focável, mostra o indicador e não abre o seletor; soltar arquivos não faz nada. Remover um arquivo continua permitido, e a tela recebe a mudança por update:modelValue
Desabilitadodisabled: área apagada, botão e remoção desabilitados
Somente leiturareadonly: mostra só a lista, sem área nem remoção; sem arquivos, "Nenhum arquivo anexado."

Tamanhos ​

Anexos

Arraste os arquivos para cá ou

Anexos

Arraste os arquivos para cá ou

PDF

Use sm em painéis laterais e cartões, como "Anexar outro PDF" na tela da medição: sem ícone, texto e botão na mesma linha, e linhas de arquivo compactas.

Estilo ​

PropriedadeToken
Área: fundo--tj-layer-02; hover e arrastando --tj-layer-selected-01; desabilitado --tj-field-disabled
Área: borda1,5 px tracejada --tj-border-strong-01; hover e foco --tj-border-interactive; arrastando contínua --tj-border-interactive; inválido --tj-support-error-text; aviso --tj-support-warning-text (3:1 sobre a área nos dois temas); desabilitado --tj-border-subtle-02. Arrastando vence inválido e aviso
Área: raio--tj-radius-lg (12 px)
Área: espaço interno--tj-space-6 (24 px); sm com --tj-space-4 (16 px)
Íconecloud-arrow-up, --tj-icon-lg (24 px), --tj-icon-interactive; arrastando file-earmark-arrow-down
Texto--tj-text-md, --tj-text-secondary; sm com --tj-text-sm; arrastando --tj-text-primary e --tj-weight-medium
Regra (tipo e tamanho)--tj-text-xs, --tj-text-helper
BotãoBaseButton secondary com ícone upload, do mesmo tamanho do componente
Foco do botãoContorno sólido de 2 px --tj-border-interactive, afastado 2 px. O --tj-ring translúcido fica abaixo de 3:1 sobre o fundo claro da área
Rótulo e mensagensOs mesmos de BaseField: --tj-text-sm, rótulo --tj-text-secondary semibold, erro --tj-support-error-text, aviso --tj-support-warning-text
ListaBaseFileItem, com --tj-space-2 entre as linhas (sm: --tj-space-1)
MovimentoBorda e fundo com --tj-duration-fast-02 e --tj-easing-standard; sem transição com movimento reduzido. O indicador de loading é o do BaseButton, que gira devagar com movimento reduzido
Alto contrasteBorda CanvasText; arrastando, borda e contorno interno Highlight; foco com contorno Highlight

Código ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { BaseFileUpload } from '@lab-inovacao/design-system'

const memoria = ref<File[]>([])
</script>

<template>
  <BaseFileUpload
    v-model="memoria"
    label="Memória de cálculo"
    accept=".pdf"
    :max-size="20 * 1024 * 1024"
    :invalid="tentouSalvar && memoria.length === 0"
    required
    @reject="registrarRecusa"
  />
</template>
PropriedadeTipoPadrãoDescrição
v-modelFile[][]Arquivos aceitos, na ordem em que entraram
labelstring—O que se anexa; obrigatório. Vira a legenda do grupo
acceptstring—Tipos aceitos, na sintaxe do campo nativo: .pdf,.xlsx, image/*
maxSizenumber—Tamanho máximo em bytes
multiplebooleanfalseAceita vários arquivos; sem ele, um novo substitui o atual
size'sm' | 'md''md'Densidade da área, do botão e das linhas
buttonLabelstring"Selecionar arquivos" (ou "Selecionar arquivo")Texto do botão
helperTextstring—Ajuda abaixo da área
invalid / invalidTextboolean / string— / "Anexe pelo menos um arquivo."Erro no lugar da ajuda
warn / warnTextboolean / string—Aviso no lugar da ajuda
required / optionalbooleanfalseMarca na legenda
disabledbooleanfalseDesabilita área, botão e remoção
readonlybooleanfalseMostra só a lista
loadingbooleanfalseBloqueia novos arquivos enquanto a tela trabalha
hideLabelbooleanfalseLegenda só para leitor de tela
EventoDadosQuando
update:modelValueFile[]Arquivos aceitos entraram ou um saiu
reject{ file: File, reason: string }[]Uma escolha ou um arraste teve arquivos recusados

Para usar as mesmas regras fora do componente, src/lib/fileUpload.ts exporta selectFiles, fileRejectionReason, matchesAccept, describeAccept e uploadHint.

Acessibilidade ​

  • Segue o padrão de botão da WAI-ARIA APG: "Selecionar arquivos" é um <button> nativo, alcançado pelo Tab e acionado com Enter ou Espaço. Ele abre o seletor de arquivos do sistema, de um <input type="file"> escondido. Arrastar é um atalho para o mouse; tudo o que ele faz, o botão também faz.
  • O nome do botão é o texto visível, então quem usa comando de voz diz "Selecionar arquivos" (WCAG 2.5.3). O botão é descrito pela regra ("PDF, até 20 MB") e pela ajuda, erro ou aviso (aria-describedby).
  • Área, botão e lista ficam num <fieldset> com a legenda do label: o leitor de tela anuncia "Memória de cálculo" ao entrar no grupo. A lista tem role="list", para o Safari não perder a semântica de lista sem marcadores, e o nome "Arquivos de" mais o label, que distingue duas listas na mesma tela. Obrigatório tem asterisco visível e "(obrigatório)" para o leitor de tela, porque um botão não tem required.
  • Uma região aria-live="polite" anuncia o que mudou: "memoria-calculo-29.pdf adicionado.", "2 arquivos adicionados: a.pdf e b.pdf. 1 arquivo recusado.", "memoria-calculo-29.pdf removido.". Cada linha recusada lê o próprio motivo, pelo BaseFileItem. A região é esvaziada antes de cada texto, então o mesmo resultado duas vezes seguidas ("1 arquivo recusado.") é lido de novo.
  • Ao remover um arquivo, o foco vai para o botão de remover que ocupou o lugar, para o anterior ou, com a lista vazia, para "Selecionar arquivos". O foco nunca se perde.
  • Erro e aviso têm ícone, texto e borda; a mensagem começa com "Erro: " ou "Atenção: " escondido na tela. Arrastando, além da cor, a borda fica contínua e o texto muda. A cor nunca é o único sinal.
  • O foco do botão é um contorno sólido com 3:1 sobre a área, que continua visível no alto contraste do Windows.
  • Com loading, o botão continua focável, em vez de sumir da ordem do Tab, e é marcado como indisponível (aria-disabled) e ocupado (aria-busy). O grupo não recebe aria-busy, para não segurar os anúncios da região aria-live que fica dentro dele.
  • Com movimento reduzido, a área muda sem transição.
  • Dentro de um BaseField (o que não se recomenda), o componente não herda o id do campo: o rótulo do BaseField fica sem campo, e a legenda do grupo continua sendo o nome.
  • Testado com axe em todos os estados: padrão, com regra e ajuda, com lista, obrigatório, opcional, inválido, aviso, desabilitado, somente leitura (com e sem arquivos), carregando, compacto, legenda escondida, arrastando, com arquivos recusados anunciados e com um segundo arquivo recusado sem multiple. O contraste vem dos tokens de função, que mantêm AA nos dois temas; o jsdom não calcula cores.