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.

BaseDateRange ​

Período com data de início e data de fim, como a vigência de um contrato. As duas datas ficam lado a lado, sob um rótulo só, e cada uma tem o próprio rótulo curto ("Início" e "Fim"). O componente confere sozinho se o fim não vem antes do início.

Vigência

12 meses a partir da ordem de serviço.

Prazo de execução (opcional)

Dentro da vigência: de 03/11/2026 a 02/11/2027.

Valor do v-model: { "start": "2026-11-03", "end": "2027-11-02" } e { "start": "", "end": "" }. Datas pela metade no prazo de execução: { "start": false, "end": false }.

Uso ​

  • Use para um período com começo e fim: vigência, prazo de execução, período de medição, afastamento. Para uma data só, use o BaseDateInput.
  • O rótulo do grupo diz qual é o período ("Vigência"). Os rótulos das datas ficam curtos: "Início" e "Fim" por padrão. Troque com start-label e end-label quando o nome da ponta ajudar ("Ordem de serviço", "Entrega da obra").
  • O v-model é um objeto { start, end }, cada data em ISO AAAA-MM-DD ou '' enquanto vazia ou incompleta. Formate para dd/mm/aaaa só na hora de mostrar.
  • Fim no mesmo dia do início vale. Fim antes do início mostra o erro: "O fim não pode ser antes do início. Confira as duas datas." Passe invalid-text para uma mensagem do seu caso.
  • O erro de ordem aparece quando o foco sai de uma das datas, nunca durante a digitação: enquanto o ano é digitado, o Chrome entrega 0002, 0020 e 0202 antes de 2026, e o erro piscaria. Ele some assim que as datas ficam em ordem, mesmo no meio da digitação.
  • Valor posto pelo código (por exemplo, um contrato carregado do servidor) com o fim antes do início mostra o erro na hora, tanto ao trocar o objeto inteiro quanto ao mudar só periodo.end.
  • Data pela metade (só dia e mês) ou impossível (31/02) chega ao v-model como '', igual a uma data vazia. Para separar as duas, use v-model:incomplete, um objeto { start, end } que fica true na ponta que sobrou pela metade. Assim a tela mostra "Data incompleta. Informe dia, mês e ano." com invalid e invalid-text, ao sair do campo ou ao enviar, como no BaseDateInput.
  • Para limpar o período, ponha { start: '', end: '' } no v-model e { start: false, end: false } no incomplete. Só assim somem as partes que o usuário deixou pela metade.
  • O calendário do fim só oferece dias a partir do início. Digitar uma data anterior continua possível, e aí vale o erro.
  • min e max valem para as duas datas. Diga o intervalo na ajuda: o navegador não explica por que um dia está bloqueado.
  • Para outras regras (período obrigatório, fora da vigência do contrato), valide ao sair do campo ou ao enviar e use invalid com um invalid-text que diga como corrigir. O invalid marca as duas datas; o erro de ordem marca só o fim.
  • Antes de enviar o formulário, confira a ordem com isDateRangeOrdered(periodo), exportada pelo pacote. Ela devolve true também quando falta uma das datas; trate o período obrigatório à parte.
  • Não coloque BaseDateRange dentro de BaseField: o período já tem rótulo, ajuda e erro. Se acontecer, as datas mantêm os próprios id e rótulos, mas o rótulo do BaseField fica sem campo.

Estados ​

Fim antes do início

O fim não pode ser antes do início. Confira as duas datas.

Inválido

Informe a vigência do contrato.

Aviso

Vigência acima de 5 anos. Confira se o edital permite.

Somente leitura
Desabilitado
  • Inválido sempre mostra ícone e texto. Sem invalid-text, aparece "Confira o início e o fim do período."; prefira uma mensagem que diga o que corrigir.
  • Aviso só aparece com warn-text. Com erro e aviso ao mesmo tempo, vale o erro.
  • Somente leitura mostra o período sem permitir mudança; as datas seguem no foco do teclado e legíveis.
  • Desabilitado é para quando o período não se aplica agora. Diga perto do campo por quê.

Tamanhos ​

Cada tamanho tem a altura do BaseInput correspondente, para o período alinhar com os outros campos da linha.

Pequeno
Médio
Grande

Estilo ​

As datas herdam o campo do BaseDateInput. Só o que é do período está abaixo.

PropriedadeToken
Rótulo do grupo--tj-text-secondary, --tj-text-sm, semibold; desabilitado --tj-text-placeholder, como no BaseFieldset
Rótulo de cada data--tj-text-secondary, --tj-text-sm, regular; desabilitado --tj-text-placeholder
Colunasduas iguais, espaço --tj-space-3 (o .tj-pair do protótipo v3); abaixo de 360 px, uma embaixo da outra
Rótulo até a data--tj-space-1
Borda com erro--tj-support-error-text no fim (ordem) ou nas duas datas (invalid)
Borda com aviso--tj-support-warning-text nas duas datas
Mensagemajuda --tj-text-helper; erro --tj-support-error-text; aviso --tj-support-warning-text; --tj-text-sm
Focoanel --tj-ring em cada data

Diferenças em relação ao protótipo v3: lá as datas só tinham aria-label ("Início da vigência"); aqui cada uma tem um rótulo visível, como no Carbon, para quem enxerga saber qual ponta é qual sem depender da ordem.

Código ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { BaseDateRange, isDateRangeOrdered, type DateRange } from '@lab-inovacao/design-system'
const vigencia = ref<DateRange>({ start: '', end: '' })
const vigenciaIncompleta = ref({ start: false, end: false })
</script>

<BaseDateRange v-model="vigencia" v-model:incomplete="vigenciaIncompleta" label="Vigência" helper-text="12 meses a partir da ordem de serviço." required />
PropriedadeTipoPadrãoDescrição
v-model{ start: string, end: string }{ start: '', end: '' }Datas em ISO AAAA-MM-DD; '' quando vazia ou incompleta
v-model:incomplete{ start: boolean, end: boolean }{ start: false, end: false }true na ponta com data pela metade ou impossível; false vindo do pai apaga o que sobrou
labelstring—Nome do período (obrigatório), vira a legenda
startLabel / endLabelstring'Início' / 'Fim'Rótulo visível de cada data
min / maxstring— / '9999-12-31'Primeira e última data aceitas nas duas pontas, em ISO; o fim também não oferece dias antes do início
size'sm' | 'md' | 'lg''md'Altura das datas
helperTextstring—Ajuda abaixo das datas
invalidboolean—Marca as duas datas como inválidas, para regras da tela
invalidTextstringver UsoErro no lugar da ajuda, tanto com invalid quanto com o fim antes do início
warn / warnTextboolean / string—Aviso no lugar da ajuda; sem warnText não aparece
required / optionalboolean—Marca na legenda; required vai também para as duas datas
disabled / readonlyboolean—Estados das duas datas
hideLabelboolean—Legenda só para leitor de tela

Eventos:

  • update:modelValue: o objeto { start, end } inteiro, a cada mudança de uma das datas.
  • update:incomplete: o objeto { start, end } inteiro, quando uma das datas passa a estar ou deixa de estar pela metade.

Também exportados: os tipos DateRange e DateRangeIncomplete e a função isDateRangeOrdered(periodo), a mesma regra que o componente usa.

Acessibilidade ​

Usa o papel group do WAI-ARIA, dado pelo <fieldset> nativo, como os grupos de campos do APG.

  • O período é um <fieldset> com <legend>: a legenda é o nome do grupo, que o leitor de tela anuncia ao entrar nele antes do rótulo da data ("Início", "Fim").
  • Cada data é um BaseDateInput com <label for> visível. Cada parte (dia, mês, ano) é um campo giratório nativo e segue o teclado desse padrão: setas para cima e para baixo mudam a parte, seta para a direita e Tab passam para a seguinte, Backspace apaga.
  • Tab percorre dia, mês e ano do início, depois do fim, e sai do grupo; não há tecla própria do componente.
  • Ajuda, erro e aviso ficam em aria-describedby das duas datas, para a mensagem ser lida quando qualquer uma recebe foco.
  • Com erro, a data marcada recebe aria-invalid="true". A cor nunca é o único sinal: há sempre ícone e texto, inclusive sem invalid-text.
  • required vai para as duas datas como atributo nativo. O asterisco fica escondido do leitor de tela.
  • O erro de ordem nunca aparece durante a digitação, então o leitor de tela não ouve uma mensagem que surge a cada tecla. Ele pode sumir no meio da digitação, assim que as datas ficam em ordem.
  • Quando o foco sai de uma data e o erro de ordem aparece, uma região aria-live="polite" escondida anuncia o texto do erro, porque é o componente, e não a tela, que decide a hora do erro. A região lê o texto que estiver visível nessa hora e esvazia quando as datas ficam em ordem. Um invalid ligado pela tela sozinho não é anunciado pelo componente: a tela decide a hora desse erro.
  • Dentro de um BaseField (o que não se recomenda), as datas não herdam o id do campo: cada rótulo continua apontando para a própria data.
  • O foco aparece com o anel --tj-ring de 3 px em cada data. O componente não tem animação própria.
  • Testado com axe nestes estados: vazio, com ajuda, fim antes do início (com e sem invalid-text, com invalid, com aviso), erro de ordem depois de sair do campo, fim mudado pelo código no próprio objeto, data pela metade, inválido com e sem texto, aviso, obrigatório, opcional, somente leitura, desabilitado (também obrigatório), os três tamanhos, legenda oculta (também obrigatória) e rótulos trocados. O axe roda sem layout, então o contraste das cores é conferido na documentação renderizada.