Date picker: Day content
To show more than the number in a day of the slotsmith date picker, such as a price, a dot or a badge, replace the DayContent slot. It receives the day and its state, and renders inside the day button, so the keyboard and the selection stay as they are.
Pick two dates to see the total.
import { useState, type CSSProperties } from "react";
import { addDays, DatePicker, type CalendarDay, type DatePickerComponents, type DateRange, type ISODate } from "slotsmith/date-picker";
import { useToday } from "../shared/today";
/** A made-up nightly price for a date, the same on every render. */
const fare = (date: ISODate) => 60 + ((Number(date.slice(8)) * 37 + Number(date.slice(5, 7)) * 11) % 90);
/** What a stay costs: every night from the first date up to, not including, the last. */
function total(from: ISODate, to: ISODate) {
let sum = 0;
for (let night = from; night < to; night = addDays(night, 1)) sum += fare(night);
return sum;
}
/** One part replaced: DayContent receives the day, so the price goes under its number. */
const components: Partial<DatePickerComponents> = {
DayContent: ({ day, disabled }) => (
<span style={{ display: "grid", justifyItems: "center", lineHeight: 1.05 }}>
<span>{day.day}</span>
{day.outside || disabled ? null : (
<span dir="ltr" style={{ fontSize: "0.5625rem" }}>
${fare(day.date)}
</span>
)}
</span>
),
};
/** Taller cells and a wider popup, so the price fits under the date; nights under $90 are bold. */
const slotProps = {
root: { style: { "--sdp-cell": "2.5rem" } as CSSProperties },
popup: { style: { width: "21rem" } },
// Per-day DOM props for the day button.
day: (day: CalendarDay) => (fare(day.date) < 90 ? { style: { fontWeight: 700 } } : {}),
};
export default function DayContent() {
const today = useToday();
const [stay, setStay] = useState<DateRange | null>(null);
return (
<div style={{ display: "grid", gap: "0.5rem", maxWidth: 288 }}>
<DatePicker
mode="range"
// A stay is counted in calendar nights, so the value is the day alone.
valueFormat="YYYY-MM-DD"
value={stay}
onChange={setStay}
minDate={today}
components={components}
slotProps={slotProps}
placeholder="Pick your dates"
aria-label="Stay"
/>
<p>{stay?.from && stay.to ? `Total: $${total(stay.from, stay.to)}` : "Pick two dates to see the total."}</p>
</div>
);
}import { useSyncExternalStore } from "react";
import { today, type ISODate } from "slotsmith/date-picker";
/** The date a prerendered page is built with, so its HTML is the same on every build. */
export const PRERENDER_TODAY: ISODate = "2026-03-16";
// Today does not change while the page is open, so there is nothing to subscribe to.
const subscribe = () => () => {};
/**
* Today as `YYYY-MM-DD`, safe to prerender: the fixed date on the server and
* while hydrating, so the markup matches, then the visitor's real date.
* An app that renders only in the browser can call `today()` directly.
*/
export function useToday(): ISODate {
return useSyncExternalStore(subscribe, today, () => PRERENDER_TODAY);
}Open the picker: each day you can pick has a price under its number. Pick two dates and the line under the picker adds up the nights.
The DayContent slot
DayContent receives:
day: the date asday.date, the number asday.day, andoutside(it belongs to a neighbouring month),isTodayandweekend(a Saturday or Sunday).selected,inRange,inPreviewanddisabled: the day’s state.
The demo hides the price on days outside the month and on days that cannot be picked. Whatever the slot renders, the button keeps its accessible name, the full date (“Monday, March 16, 2026”), so put anything a screen reader user needs somewhere other than inside the day alone.
Why not the Day slot
Day is the button itself. It is an element part: it receives DOM props only, with the state as data-* attributes, so a design system’s button drops straight in. It is not told which day it is. DayContent is, which makes it the place for content that depends on the date.
Room for the content
A day is 2rem square by default. The demo makes room with two slotProps: the --sdp-cell variable on the root for taller cells, and a wider popup. Other tokens are on the API page.
Props for one day
To mark a day without replacing anything, slotProps.day is a function that receives the day and returns DOM props for its button: a class, a style or a data-* attribute. The demo uses it to make the nights under $90 bold; marking public holidays with a class works the same way.