@kenos-ui/react-datepicker
v0.5.0
Published
Headless date & scheduling primitives for React — Kenos UI DatePicker
Readme
@kenos-ui/react-datepicker
Headless date & scheduling primitives for React.
Built on native Intl, timescape (segmented inputs), and Floating UI. Full keyboard navigation, WAI-ARIA patterns, and a focus on real-world composition.
- Single, range, and multiple selection with one API (
mode) - Outstanding segmented date input (
<DatePicker.Input />) - Fully unstyled — bring your own CSS or Tailwind
- Excellent keyboard + screen reader support
- React 19+ and TypeScript-first
Installation
npm install @kenos-ui/react-datepickerQuick start (with segmented input)
import { DatePicker } from "@kenos-ui/react-datepicker";
function App() {
const [date, setDate] = useState<Date | null>(null);
return (
<DatePicker.Root value={date} onValueChange={setDate}>
<DatePicker.Label>Pick a date</DatePicker.Label>
<div>
<DatePicker.Input />
<DatePicker.Trigger>📅</DatePicker.Trigger>
</div>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
);
}The <DatePicker.Input /> gives users a native-feeling segmented editor (month / day / year) that respects the locale's order and separators.
Date range
One of the strongest use cases:
import { DatePicker, type DateRange } from "@kenos-ui/react-datepicker";
function TripDates() {
const [range, setRange] = useState<DateRange>({ start: null, end: null });
return (
<DatePicker.Root mode="range" value={range} onValueChange={setRange}>
<DatePicker.Label>Trip dates</DatePicker.Label>
<div>
<DatePicker.Input index={0} />
<span>to</span>
<DatePicker.Input index={1} />
<DatePicker.Trigger>📅</DatePicker.Trigger>
</div>
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>
);
}Range mode includes live hover preview between start and end.
Multiple dates
<DatePicker.Root mode="multiple" onValueChange={setDates}>
<DatePicker.Input />
<DatePicker.Trigger />
<DatePicker.Content>
<DatePicker.Calendar />
</DatePicker.Content>
</DatePicker.Root>Calendar composition
Use the convenient shorthand:
<DatePicker.Root>
<DatePicker.Calendar />
</DatePicker.Root>Or take full control:
<DatePicker.Root>
<DatePicker.ViewControl>
<DatePicker.PrevTrigger />
<DatePicker.ViewTrigger />
<DatePicker.NextTrigger />
</DatePicker.ViewControl>
<DatePicker.View view="day">
<DatePicker.Grid header={<DatePicker.WeekDays />}>
{({ weeks }) =>
weeks.map((week, i) => (
<tr key={i}>
{week.map((d, j) => (
<DatePicker.Day key={j} date={d}>
{({ isSelected, isToday }) => (
// custom rendering
<span className={isSelected ? "selected" : ""}>{d.getDate()}</span>
)}
</DatePicker.Day>
))}
</tr>
))
}
</DatePicker.Grid>
</DatePicker.View>
</DatePicker.Root>You can also render month/year grids with MonthGrid / YearGrid.
Positioning & advanced Content
<DatePicker.Content> is powered by Floating UI and supports:
side,align,sideOffset,alignOffsetportalforceMount(for enter/exit animations via[data-state="open"])avoidCollisions
<DatePicker.Content portal side="top" align="end" forceMount>
<DatePicker.Calendar />
</DatePicker.Content>Key props on Root
mode:"single" | "range" | "multiple"locale,weekStartsOnminDate,maxDate,disabledreadOnlymodal— opt-in focus trap +aria-modal(defaultfalse— follows popup policy)defaultOpen,closeOnSelect
See the full prop tables and more examples in the project README.
Localization
Everything is driven by Intl.Locale:
<DatePicker.Root locale="pt-BR" /> {/* dd/mm/yyyy, week starts Monday */}
<DatePicker.Root locale="ar" /> {/* RTL + Saturday start */}
<DatePicker.Root locale="ja-JP" />Requirements
- React ≥ 19
- Node ≥ 22
Exports
import {
DatePicker,
useDatePickerContext,
// types
type DatePickerRootProps,
type DateRange,
type DayCellMeta,
// ...
} from "@kenos-ui/react-datepicker";License
MIT
Kenos UI — https://github.com/allysontsoares/kenos-ui/tree/main/packages/datepicker
