Date Picker
Campo de data com digitação e calendário em popover, para uma data (DatePicker) ou um período (DateRangePicker).
'use client';
import { I18nProvider } from 'react-aria-components';
import { DatePicker } from '@/components/ui/date-picker';
export default function DatePickerDemo() {
return (
<I18nProvider locale="pt-BR">
<DatePicker label="Data da visita técnica" description="Digite a data ou abra o calendário." className="w-72" />
</I18nProvider>
);
}Instalação
npx shadcn@latest add @lenstech/date-pickerUso
import { I18nProvider } from "react-aria-components"
import { DatePicker, DateRangePicker } from "@/components/ui/date-picker"<I18nProvider locale="pt-BR">
<DatePicker label="Data da visita" name="visita" />
</I18nProvider>Datas são CalendarDate, não Date
O valor é um objeto do pacote @internationalized/date (CalendarDate), sem hora nem fuso.
No DateRangePicker o valor é { start, end }, cada um um CalendarDate.
- Criar:
today(getLocalTimeZone()),parseDate("2026-10-15"). - Enviar para a API:
data.toString()→"2026-10-15". Em formulários,name(oustartName/endName) já envia em ISO. - Converter para
Date:data.toDate(getLocalTimeZone()). - Calcular:
data.add({ days: 30 }),data.compare(outra)(negativo = antes).
Exemplos
Período (DateRangePicker)
Para filtros de relatório e reservas. Digite início e fim ou selecione os dois extremos no calendário.
'use client';
import { getLocalTimeZone, today } from '@internationalized/date';
import { I18nProvider } from 'react-aria-components';
import { DateRangePicker } from '@/components/ui/date-picker';
export default function DatePickerRange() {
const now = today(getLocalTimeZone());
return (
<I18nProvider locale="pt-BR">
<DateRangePicker
label="Período do relatório"
description="Últimos 30 dias por padrão."
defaultValue={{ start: now.subtract({ days: 29 }), end: now }}
maxValue={now}
className="w-80"
/>
</I18nProvider>
);
}Datas mínima, máxima e indisponíveis
minValue/maxValue limitam o intervalo; isDateUnavailable bloqueia dias específicos — aqui, fins de semana.
'use client';
import { getLocalTimeZone, isWeekend, today } from '@internationalized/date';
import { I18nProvider } from 'react-aria-components';
import { DatePicker } from '@/components/ui/date-picker';
export default function DatePickerUnavailable() {
const now = today(getLocalTimeZone());
return (
<I18nProvider locale="pt-BR">
<DatePicker
label="Agendar reunião de briefing"
description="Segunda a sexta, nos próximos 60 dias."
minValue={now}
maxValue={now.add({ days: 60 })}
isDateUnavailable={(date) => isWeekend(date, 'pt-BR')}
className="w-72"
/>
</I18nProvider>
);
}Controlado
Use value e onChange para definir a data por código (atalhos, limpar o campo) e ver o valor que seria enviado.
Valor enviado ao servidor: null
'use client';
import * as React from 'react';
import { getLocalTimeZone, today, type CalendarDate } from '@internationalized/date';
import { I18nProvider } from 'react-aria-components';
import { Button } from '@/components/ui/button';
import { DatePicker } from '@/components/ui/date-picker';
export default function DatePickerControlled() {
const [date, setDate] = React.useState<CalendarDate | null>(null);
return (
<I18nProvider locale="pt-BR">
<div className="flex w-72 flex-col gap-3">
<DatePicker label="Vencimento da fatura" value={date} onChange={setDate} />
<div className="flex gap-2">
<Button size="sm" variant="outline" onPress={() => setDate(today(getLocalTimeZone()).add({ days: 7 }))}>
Daqui a 7 dias
</Button>
<Button size="sm" variant="ghost" onPress={() => setDate(null)}>
Limpar
</Button>
</div>
<p className="text-sm text-muted-foreground">
Valor enviado ao servidor: <code className="font-mono text-foreground">{date ? date.toString() : 'null'}</code>
</p>
</div>
</I18nProvider>
);
}Validação
isRequired, minValue e validate funcionam com o Form. Clique em Criar campanha para ver os erros.
'use client';
import { getLocalTimeZone, today } from '@internationalized/date';
import { I18nProvider } from 'react-aria-components';
import { Button } from '@/components/ui/button';
import { DatePicker, DateRangePicker } from '@/components/ui/date-picker';
import { Form } from '@/components/ui/form';
export default function DatePickerValidation() {
const now = today(getLocalTimeZone());
return (
<I18nProvider locale="pt-BR">
<Form className="w-80 gap-4" onSubmit={(e) => e.preventDefault()}>
<DatePicker label="Data do evento" name="evento" isRequired minValue={now} />
<DateRangePicker
label="Período da campanha"
startName="inicio"
endName="fim"
isRequired
validate={(range) =>
range && range.end.compare(range.start.add({ days: 90 })) > 0 ? 'A campanha pode durar no máximo 90 dias.' : null
}
/>
<Button type="submit" className="self-start">
Criar campanha
</Button>
</Form>
</I18nProvider>
);
}Quando usar
- Use em formulários de agendamento, vencimentos e filtros de período.
- Não use para datas distantes que a pessoa sabe de cor (nascimento) — use
Date Field, mais rápido de digitar. - Não use quando o calendário deve ficar sempre visível na tela — use
Calendar. - Para relatórios, use o
DateRangePickercom um período padrão (ex.: últimos 30 dias) emaxValueem hoje.
API
DatePicker
Aceita todas as props do DatePicker do React Aria, mais:
Prop
Type
DateRangePicker
Aceita todas as props do DateRangePicker do React Aria, mais
label, description e errorMessage. Diferenças principais:
Prop
Type