Date Picker
Un campo que abre un calendario. Reemplaza a <input type="date">, cuyo calendario es del navegador y no se puede estilar.
import { DatePicker } from "sebs7n-ui/date-picker"Ejemplos
Básico
El campo es un botón: el `<Label htmlFor>` lo nombra y, al hacerle clic, abre el calendario.
import { DatePicker } from "sebs7n-ui/date-picker"
import { Label } from "sebs7n-ui/label"
import { useId } from "react"
function Basico() {
const id = useId()
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Label htmlFor={id}>Vencimiento</Label>
<DatePicker defaultValue={new Date(2026, 8, 27)} id={id} name="vencimiento" />
</div>
)
}Un rango
Se queda abierto después del desde y se cierra con el hasta.
import { DatePicker } from "sebs7n-ui/date-picker"
import { DateRange } from "sebs7n-ui/lib/dates"
import { Label } from "sebs7n-ui/label"
import { useId, useState } from "react"
function Rango() {
const id = useId()
const [periodo, setPeriodo] = useState<DateRange>({ from: null, to: null })
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Label htmlFor={id}>Período</Label>
<DatePicker id={id} mode="range" onValueChange={setPeriodo} value={periodo} />
</div>
)
}Con Limpiar
`clearable` suma un pie para vaciar la fecha: un filtro o un campo opcional no puede ser un camino sin vuelta.
import { DatePicker } from "sebs7n-ui/date-picker"
import { Label } from "sebs7n-ui/label"
import { useId } from "react"
function ConLimpiar() {
const id = useId()
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Label htmlFor={id}>Facturas desde</Label>
<DatePicker clearable defaultValue={new Date(2026, 8, 1)} id={id} name="desde" />
</div>
)
}Tamaños, formato y límites
Las mismas tres alturas que `Input`. `format` es el de `Intl.DateTimeFormat`.
import { DatePicker } from "sebs7n-ui/date-picker"
function TamanosYFormato() {
return (
<div className="flex w-full max-w-xs flex-col gap-3">
<DatePicker aria-label="Fecha corta" defaultValue={new Date(2026, 8, 27)} format={{ dateStyle: "short" }} size="sm" />
<DatePicker aria-label="Fecha larga" defaultValue={new Date(2026, 8, 27)} format={{ dateStyle: "long" }} />
<DatePicker aria-label="Turno" max={new Date(2026, 9, 16)} min={new Date(2026, 8, 7)} size="lg" />
<DatePicker aria-label="Sin turnos" disabled />
</div>
)
}Una fecha lejana
En el calendario, el título abre la grilla de meses y su año la de años. Escape vuelve a los días sin cerrar el panel.
import { DatePicker } from "sebs7n-ui/date-picker"
import { Label } from "sebs7n-ui/label"
import { useId } from "react"
function FechaDeAlta() {
const id = useId()
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Label htmlFor={id}>Fecha de alta del cliente</Label>
<DatePicker defaultValue={new Date(2006, 3, 12)} id={id} max={new Date(2026, 8, 29)} name="alta" />
</div>
)
}Idioma global
`LabelsProvider` con `dates`: idioma, semana y formato para `DatePicker`, `DateTimePicker` y `Calendar` de abajo (y `CalendarView`). La prop de cada uno le gana.
import { Calendar } from "sebs7n-ui/calendar"
import { DatePicker } from "sebs7n-ui/date-picker"
import { DateTimePicker } from "sebs7n-ui/date-time-picker"
import { Label } from "sebs7n-ui/label"
import { LabelsProvider } from "sebs7n-ui/labels"
import { useState } from "react"
function IdiomaGlobal() {
const [due, setDue] = useState<Date | null>(new Date(2026, 9, 15))
return (
<LabelsProvider value={{ dates: { locale: "en-US", weekStartsOn: 0, format: NUMERIC } }}>
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-1.5">
<Label htmlFor="due-global">Due date</Label>
<DatePicker className="w-56" id="due-global" onValueChange={setDue} value={due} />
</div>
<DateTimePicker aria-label="Issued at" className="w-72" defaultValue={new Date(2026, 9, 1, 9, 30)} />
<Calendar className="self-start" defaultMonth={new Date(2026, 9, 1)} />
</div>
</LabelsProvider>
)
}En un Field
`FieldLabel`, ayuda y error se enganchan solos; con `required`, sin fecha u hora `Form` no envía y enfoca el campo.
import { Button } from "sebs7n-ui/button"
import { DatePicker } from "sebs7n-ui/date-picker"
import { Field, FieldDescription, FieldError, FieldLabel } from "sebs7n-ui/field"
import { Form } from "sebs7n-ui/form"
import { TimePicker } from "sebs7n-ui/time-picker"
import { useState } from "react"
function EnField() {
const [sent, setSent] = useState<string | null>(null)
return (
<Form className="flex w-full max-w-sm flex-col gap-4" onFormSubmit={(values) => setSent(JSON.stringify(values))}>
<Field name="due">
<FieldLabel>Vencimiento</FieldLabel>
<DatePicker required />
<FieldDescription>El día que vence la factura.</FieldDescription>
<FieldError>Elegí una fecha.</FieldError>
</Field>
<Field name="sendAt">
<FieldLabel>Hora de envío</FieldLabel>
<TimePicker required />
<FieldError>Elegí una hora.</FieldError>
</Field>
<Button className="self-start" type="submit">
Programar
</Button>
{sent && <p className="text-footnote text-label-secondary">{sent}</p>}
</Form>
)
}Props
Generadas del TypeScript del paquete. Las propias del componente, más las heredadas del primitivo que tienen algo que explicar —marcadas «heredada de Base UI»—. El resto está en la línea «hereda de».
DatePicker
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
clearable | boolean | — | Suma un «Limpiar» al pie del calendario cuando hay fecha elegida: para un filtro o un campo opcional, donde elegir una fecha no puede ser un camino sin vuelta. |
defaultValue | Date | DateRange | — | La fecha elegida al montar, sin controlar. |
format | Intl.DateTimeFormatOptions | — | Cómo se escribe la fecha en el campo. Por defecto, { dateStyle: "medium" }: «27 sept 2026». |
isDateDisabled | (date: Date) => boolean | — | Apaga fechas sueltas: feriados, fines de semana, días sin turno. |
labels | Partial<DatePickerLabels & Labels["calendar"]> | — | El texto del campo vacío y los nombres de los botones del calendario. |
locale | string | — | El idioma de la fecha y del calendario, como lo entiende Intl. Por defecto, es-AR. |
max | Date | — | La última fecha que se puede elegir. |
min | Date | — | La primera fecha que se puede elegir. |
mode | "single" | "range" | — | single elige una fecha; range, un desde y un hasta. |
name | string | — | El nombre con el que la fecha viaja en un formulario, como 2026-09-27. En range salen dos campos: nombre-desde y nombre-hasta. |
numberOfMonths | number | — | Cuántos meses muestra el calendario, uno al lado del otro. Por defecto, 1. |
onOpenChange | (open: boolean) => void | — | Avisa cuando se abre o se cierra. |
onValueChange | ((value: Date | null) => void) | ((value: DateRange) => void) | — | Avisa la fecha elegida. |
open | boolean | — | El calendario abierto o cerrado, controlado. |
popupClassName | string | — | Clases del panel del calendario. |
required | boolean | — | Sin fecha no se puede enviar: dentro de un Form, el campo queda inválido y Form lo enfoca. En range, hacen falta las dos puntas. |
size | "sm" | "md" | "lg" | — | Las mismas tres alturas que Input, para que un formulario mixto quede alineado. |
value | Date | DateRange | — | La fecha elegida, controlada. null es ninguna. |
weekStartsOn | 0 | 1 | — | Con qué día arranca la semana: 1 lunes (el default), 0 domingo. |
disabled | boolean | — | Heredada de Base UI. Apaga la interacción y lo marca con data-disabled, que es el atributo del que cuelgan los estilos de apagado. |
className | string | — | Heredada de Base UI. Se fusiona con las clases del componente vía cn() (tailwind-merge): lo que pongas gana. |
Teclado
- Enter · Espacio
- Abre el calendario, con el foco en la fecha elegida.
- Escape
- Cierra y devuelve el foco al campo.
- ← → ↑ ↓
- Se mueve por los días. Ver
Calendar. - Escape (meses y años)
- Vuelve a los días; el segundo Escape cierra.
Accesibilidad
- El campo es un botón: necesita
aria-label,aria-labelledbyo un<Label htmlFor>apuntando a suid. - La fecha se escribe con
Intlen el idioma que se le pasa (locale), no en el del navegador. - Dentro de un
Fieldse registra como su control:FieldLabello nombra junto con la fecha («Vencimiento 27 sept 2026»),FieldDescriptionyFieldErrorlo describen yFormlo enfoca si queda inválido al enviar.
Reglas de uso
- En una pantalla angosta (< 640 px) el calendario se abre en la hoja de abajo, como el
Popover: a todo el ancho, arrastrable y con la X. ConnumberOfMonths={2}los meses se apilan. - Idioma y semana para toda la app:
<LabelsProvider value={{ dates: { locale: "en-US", weekStartsOn: 0 } }}>(tambiénformatpara el campo deDatePicker). Lo leenCalendar,DatePicker,DateTimePickeryCalendarView; la prop de cada uno gana. - Para fechas que se eligen mirando un calendario: un turno, un vencimiento cercano, un período.
- Una fecha lejana no se recorre mes por mes: el título del calendario abre la grilla de meses, y su año la de años. Si lo normal es tipearla —un vencimiento que se copia de un papel—, va un
Input. mode="range"elige desde y hasta en el mismo calendario, y se cierra recién con el segundo clic.- Con
name(o elnamedelField), la fecha viaja en el formulario como2026-09-27. En rango salen dos campos:nombre-desdeynombre-hasta. EnonFormSubmitdeFormllega el ISO (en rango,{ from, to }). required: sin fecha (en rango, sin las dos puntas)Formno envía, marca el campo inválido y lo enfoca.- Con
clearable, el pie del calendario ofrece «Limpiar» cuando hay fecha: para filtros y campos opcionales.