DateRangePicker

DateRangePicker combina um trigger com seleção de intervalo em Calendar. Escolha-o quando data inicial e final descrevem um período; escolha dois DatePickers apenas quando as datas tiverem significados ou regras distintos.

Exemplos

Um período de viagem completo

O trigger mostra data inicial e final selecionadas como um valor único. Selecionar o segundo limite no Calendar composto completa o intervalo e fecha o picker.

8/11/2026 to 8/15/2026

Texto de intervalo traduzido

labels.rangeSeparator e labels.incompleteRange controlam o texto entre data inicial e final e o marcador mostrado quando só existe a inicial. labels.rangeAnnouncement(start, end) controla o descrição acessível de um intervalo completo, anunciada após o rótulo do campo; inclua as duas datas formatadas no resultado.

Quando usar

Use DateRangePicker quando uma pessoa precisa escolher um período contínuo de datas locais, como viagem, disponibilidade ou uma janela de relatório.

Prefira outro componente quando:

  • Só uma data importa — use DatePicker.
  • As duas datas têm labels, validação ou etapas de fluxo distintos — use DatePickers separados.
  • A grade de datas pertence permanentemente à página — use Calendar diretamente.

Acessibilidade

  • O trigger é um botão nativo associado ao label por htmlFor. No desktop, ele é o trigger de Popover, com semântica de diálogo não modal, fechamento por Escape e retorno de foco.
  • O Calendar composto funciona em modo de intervalo. Ele mantém foco rotativo e navegação por teclado; a primeira seleção inicia o intervalo, a seguinte o conclui, e um intervalo completo fecha o picker.
  • O valor visível do trigger é uma única string formatada: data inicial, labels.rangeSeparator e a data final ou labels.incompleteRange. O rótulo do campo continua sendo o nome acessível. Com label, um intervalo completo também é descrito como “X to Y” por padrão, por um elemento visualmente oculto ligado via aria-describedby. Personalize com labels.rangeAnnouncement(start, end) em React ou com a opção rangeAnnouncement em Alpine, por exemplo de ${start} até ${end}. Estados vazio e incompleto não têm descrição.
  • error substitui hint; disabled desabilita o trigger.
  • Em viewports de 640px ou menos, o caminho de Popover passa a BottomSheet com Calendar. Título e nome de fechar vêm de label/labels.sheetTitle e labels.close. Aqui é apenas texto porque o stage não redimensiona o viewport.

API e código

NomeTipoObrigatóriaDescrição
labelstring—Label rendered above the picker trigger.
hintstring—Helper text rendered below the picker. Replaced by `error` when set.
errorstring—Error message that enables error styling and replaces `hint`.
valueDateRange | null—Controlled local-date range, or `null` with no range selected.
defaultValueDateRange | { start: Date | string; end: Date | string; }—Initial local-date range. ISO `YYYY-MM-DD` strings are accepted for convenience.
onChange(range: DateRange) => void—Called after the user selects either bound of the local-date range.
placeholderstring—Trigger text when no range is selected. Defaults to `labels.placeholder`.
minDate | string—Inclusive lower selection limit as a local date or ISO `YYYY-MM-DD` string.
maxDate | string—Inclusive upper selection limit as a local date or ISO `YYYY-MM-DD` string.
localestring—BCP 47 locale used to format selected dates and compose Calendar. Default: `"en-US"`.
labelsDateRangePickerLabels—Translatable visible and accessible labels, merged over the English defaults.
disabledboolean—Disables the picker trigger.

x-data="lyraDateRangePicker({ … })"

OpçãoTipoObrigatóriaDescrição
defaultValue{ start?: string | null; end?: string | null; } | null—Initial ISO `YYYY-MM-DD` bounds.
localestring—BCP 47 locale used for the trigger's selected-date text. Default: `"en-US"`.
placeholderstring—Trigger text when no range has started. Default: `"Select period"`.
rangeSeparatorstring—Text between formatted range bounds. Default: `" – "`.
incompleteRangestring—Text after the separator while the range has no end. Default: `"…"`.
rangeAnnouncement(start: string, end: string) => string—Accessible description of a complete range, referenced by `aria-describedby`. Includes both formatted dates. Default: `"X to Y"`.

Sem React, componha um trigger com classes de Popover e Calendar e implemente estado do intervalo, movimento de foco e a alternativa de folha mobile:

html
<div class="lyra-field">
  <label class="lyra-label" for="travel-dates">Datas da viagem</label>
  <span class="lyra-datepicker lyra-popover-anchor">
    <button
      class="lyra-input lyra-datepicker__btn"
      id="travel-dates"
      type="button"
      aria-haspopup="dialog"
      aria-expanded="true"
      aria-describedby="range-announcement"
    >
      <span>11/08/2026 – 15/08/2026</span>
    </button>
    <span id="range-announcement" class="lyra-visually-hidden">de 11/08/2026 até 15/08/2026</span>
    <div
      class="lyra-popover lyra-popover--bottom lyra-popover--align-start"
      role="dialog"
      aria-label="Seletor de intervalo"
    >
      <div class="lyra-cal">
        <button class="lyra-cal__day lyra-cal__day--selected" type="button" aria-pressed="true">
          11
        </button>
        <button class="lyra-cal__day lyra-cal__day--in-range" type="button">12</button>
        <button class="lyra-cal__day lyra-cal__day--selected" type="button" aria-pressed="true">
          15
        </button>
      </div>
    </div>
  </span>
</div>

<lyra:date-range-picker> Gerado do lyra-ds/blade v0.10.0.

O comportamento vem de lyraDateRangePicker() — instale @lyra-ds/alpine e veja a aba HTML + Alpine.

PropPadrãoObrigatóriaValores de exemplo
labelnull—0 Period
hintnull——
errornull——
defaultValuenull——
placeholdernull——
minnull——
maxnull——
locale'en-US'——
labels[]——
disabledfalse——
namenull——
blade
<lyra:date-range-picker
    name="reporting_period"
    label="Reporting period"
    :default-value="['start' => '2026-03-01', 'end' => '2026-03-31']"
    min="2026-01-01"
    max="2026-12-31"
    locale="en-US"
/>