منتقي التاريخ: الأجزاء المركّبة
هذه الصفحة غير مترجمة بعد، وهي معروضة بالإنجليزية.
The DatePicker’s default layout is a root, a trigger and a popup. To place things between them, such as a visible label or a summary, build the layout yourself from the compound parts inside DatePicker.Provider.
No days picked.
import { useId, useState } from "react";
import { DatePicker, useDatePickerContext, type ISODate } from "slotsmith/date-picker";
/** Anything inside the provider reads the picker's state through the context. */
function DaysSummary() {
const { selectedDates, clear } = useDatePickerContext();
if (selectedDates.length === 0) return <p>No days picked.</p>;
return (
<p>
{selectedDates.length} {selectedDates.length === 1 ? "day" : "days"} picked{" "}
<button type="button" onClick={clear} style={{ background: "transparent" }}>
Clear
</button>
</p>
);
}
export default function CompoundParts() {
const labelId = useId();
const [daysOff, setDaysOff] = useState<ISODate[]>([]);
return (
<DatePicker.Provider mode="multiple" value={daysOff} onChange={setDaysOff} placeholder="Pick days">
<DatePicker.Root style={{ display: "grid", gap: "0.5rem" }}>
<label id={labelId}>Days off</label>
<DatePicker.Trigger aria-labelledby={labelId} />
<DatePicker.Popup />
<DaysSummary />
</DatePicker.Root>
</DatePicker.Provider>
);
}Pick a few days: the line under the picker reads the selection from the context and clears it.
The parts
DatePicker.Provider takes every DatePicker prop and renders no markup of its own. Inside it:
DatePicker.Root: the wrapper, carryingdata-mode,data-open,data-disabledanddata-empty. A pointer press outside it, or focus leaving it, closes the popup.DatePicker.Trigger: the combobox with the icon, the value or the placeholder, and the clear button. Name it here:aria-labeloraria-labelledbyon the trigger itself.DatePicker.Popup: the positioned dialog with the header, the grid and the footer. It renders nothing while closed.
For a popup laid out differently, the pieces of the default one are parts too: DatePicker.Header (the previous and next buttons and the month and year), DatePicker.Calendar (the grid, which owns the arrow keys), DatePicker.Day (one day, for a grid of your own) and DatePicker.Footer (the presets and “Go to today”).
These are layout parts, not slots: each still renders the slots inside it, so components replaces the elements while the parts decide where they go.
Reading the state
useDatePickerContext() returns the picker’s state and actions to any component inside the provider: value, selectedDates, range, open, month, and pick, clear, applyPreset, goToToday and setOpen, among others. The demo’s summary line uses selectedDates and clear.
To wrap DatePicker in a component of your own that takes the same props, splitDatePickerProps(props) separates the provider’s props from the root’s DOM props.
The hook
useDatePicker is the engine underneath, with no markup at all: the value in all three modes, the month on screen, the grid’s keyboard path with its roving tab stop, the range preview, the bounds and the ARIA wiring, as prop getters (getRootProps, getTriggerProps, getPopupProps, getGridProps, getCellProps, getDayProps). Use it for a shape the component does not cover, such as an inline calendar with no popup. It takes a locale tag, not a pack, and positioning is separate: usePopupPosition from slotsmith/autocomplete places a popup against its trigger.