- Accordion
- Advanced Toast
- AlertMessage
- ArrowButton
- Arrows
- Avatar
- Backdrop
- Basic Toast
- Breadcrumb
- Button
- CardBackground
- Card
- Carousel
- Chapters
- ChatBody
- ChatButton
- ChatHeader
- ChatInput
- ChatMessageActions
- ChatMessageEditor
- ChatMessage
- ChatTypingIndicator
- ChatWindowCsatPrompt
- ChatWindowQuote
- ChatWindow
- CheckboxSelect
- Checkbox
- Checkboxes
- Chip
- ChoiceExpander
- Clickable
- ContentReview
- Countdown
- CriteriaDates
- CriteriaParticipants
- CriteriaTransports
- Date Field
- Datepicker
- Dropdown
- ElasticHeight
- ExpandableCard
- ExpandableText
- Filter
- FloatingLabelTextField
- Form Control
- Form Label
- Frame
- HamburgerIcon
- Heading
- Image
- JourneyCard
- LayerHeader
- Layer
- Link
- Loader
- Number Field
- PageNavigation
- Pagination
- Paragraph
- Password
- Phone Field
- Popin
- Portal
- ProductThumbnail
- Promises
- Prose
- Radio Group
- RadioSelect
- Radio
- Range
- Scrollbar
- Select
- SidebarLayout
- SliderFrame
- SparkleWrapper
- Spinner
- Switch
- Table
- Tabs
- Tag
- TextField
- Toggle
- Tooltip
- ValidationMessage
Select your dates
Price legend
Best price
Last availabilities
Not available
Nov 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Dec 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jan 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Feb 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Mar 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Apr 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
May 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jun 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jul 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Aug 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Sep 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Oct 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
New! Flexible booking now available.
'use client';
import { useState } from 'react';
import type { DateRange } from 'react-day-picker';
import { DeviceProvider } from '@/ui/contexts/devices/Device';
import { CriteriaDates, CriteriaDatesReinsurance } from '@/ui/criteria/CriteriaDates';
export function CriteriaDatesDemo() {
const [selected, setSelected] = useState<DateRange | undefined>();
const labels = {
seeNextMonth: 'Next month',
seePreviousMonth: 'Previous month',
bestPrice: 'Best price',
lastAvailabilities: 'Last availabilities',
notAvailable: 'Not available',
priceLegend: 'Price legend',
};
return (
<DeviceProvider device="all">
<div className="w-[340px] space-y-24">
<CriteriaDates
labels={labels}
showPriceLegend
selected={selected}
onSelect={setSelected}
title="Select your dates"
>
<CriteriaDatesReinsurance
labels={{ disclaimer: 'New! Flexible booking now available.' }}
/>
</CriteriaDates>
{selected?.from && (
<p className="text-b4">
From: {selected.from.toLocaleDateString()}
{selected.to ? ` — To: ${selected.to.toLocaleDateString()}` : ''}
</p>
)}
</div>
</DeviceProvider>
);
}
Installation
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/criteria-dates.json
Dependencies
CriteriaDates wraps Datepicker internally, which reads the current breakpoint via useDevice. Place DeviceProvider above it in the tree:
import { DeviceProvider } from '@/ui/contexts/devices/Device';
<DeviceProvider device="all">
<CriteriaDates ... />
</DeviceProvider>Install the peer dependencies used by Datepicker:
npm install react-day-picker date-fns
See the Datepicker documentation for the full DeviceProvider setup guide.
Usage
Basic range selection
CriteriaDates is controlled the same way as Datepicker — you own the DateRange state and pass it back via onSelect. The labels object must always contain seeNextMonth and seePreviousMonth for the accessible navigation button labels.
'use client';
import { useState } from 'react';
import type { DateRange } from 'react-day-picker';
import { DeviceProvider } from '@/ui/contexts/devices/Device';
import { CriteriaDates } from '@/ui/criteria/CriteriaDates';
export function Component() {
const [selected, setSelected] = useState<DateRange | undefined>();
return (
<DeviceProvider device="all">
<CriteriaDates
fromMonth={new Date()}
labels={{
seeNextMonth: 'Next month',
seePreviousMonth: 'Previous month',
}}
selected={selected}
onSelect={setSelected}
title="Select your dates"
/>
</DeviceProvider>
);
}With price legend
Pass showPriceLegend and include the extra legend keys in labels to render a colour-coded legend above the calendar. The type system enforces that the extra keys must be present when the legend is enabled — TypeScript will raise an error if showPriceLegend is true but the price keys are missing from labels.
Select your dates
Price legend
Best price
Last availabilities
Not available
Nov 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Dec 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jan 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Feb 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Mar 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Apr 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
May 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jun 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Jul 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Aug 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Sep 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Oct 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
New! Flexible booking now available.
'use client';
import { useState } from 'react';
import type { DateRange } from 'react-day-picker';
import { DeviceProvider } from '@/ui/contexts/devices/Device';
import { CriteriaDates, CriteriaDatesReinsurance } from '@/ui/criteria/CriteriaDates';
export function CriteriaDatesDemo() {
const [selected, setSelected] = useState<DateRange | undefined>();
const labels = {
seeNextMonth: 'Next month',
seePreviousMonth: 'Previous month',
bestPrice: 'Best price',
lastAvailabilities: 'Last availabilities',
notAvailable: 'Not available',
priceLegend: 'Price legend',
};
return (
<DeviceProvider device="all">
<div className="w-[340px] space-y-24">
<CriteriaDates
labels={labels}
showPriceLegend
selected={selected}
onSelect={setSelected}
title="Select your dates"
>
<CriteriaDatesReinsurance
labels={{ disclaimer: 'New! Flexible booking now available.' }}
/>
</CriteriaDates>
{selected?.from && (
<p className="text-b4">
From: {selected.from.toLocaleDateString()}
{selected.to ? ` — To: ${selected.to.toLocaleDateString()}` : ''}
</p>
)}
</div>
</DeviceProvider>
);
}
With reinsurance message
Place <CriteriaDatesReinsurance> as a child of <CriteriaDates> to render a disclaimer below the calendar. The block renders nothing when labels.disclaimer is an empty string, so you can conditionally suppress it by toggling the string value.
import { CriteriaDates, CriteriaDatesReinsurance } from '@/ui/criteria/CriteriaDates';
<CriteriaDates
fromMonth={new Date()}
labels={{ seeNextMonth: 'Next month', seePreviousMonth: 'Previous month' }}
selected={selected}
onSelect={setSelected}
>
<CriteriaDatesReinsurance
labels={{ disclaimer: 'New! Flexible booking now available on all resorts.' }}
/>
</CriteriaDates>With date annotations and disabled days
All Datepicker props are forwarded unchanged, including dates for per-day price and status annotations and disabledDays for blocking unavailable dates. When showPriceLegend is enabled, statusLabels are derived automatically from the legend text — screen readers will announce the status of each annotated day without any extra configuration.
<CriteriaDates
fromMonth={new Date()}
labels={{
seeNextMonth: 'Next month',
seePreviousMonth: 'Previous month',
bestPrice: 'Best price',
lastAvailabilities: 'Last availabilities',
notAvailable: 'Not available',
priceLegend: 'Price legend',
}}
showPriceLegend
selected={selected}
onSelect={setSelected}
disabledDays={{ before: new Date() }}
dates={[
{ id: '2025-08-10', price: '890 €', status: 'green' },
{ id: '2025-08-15', price: '1 450 €', status: 'orange' },
{ id: '2025-08-20', price: '720 €', status: 'outline' },
]}
/>API Reference
CriteriaDates
| Prop | Type | Default | Description |
|---|---|---|---|
labels | CriteriaDatesLabels | CriteriaDatesLabelsWithPriceLegend | — | Required. Text labels for navigation buttons and, when showPriceLegend is true, the legend items. See CriteriaDatesLabels and CriteriaDatesLabelsWithPriceLegend. |
showPriceLegend | boolean | false | When true, renders the colour-coded price legend above the calendar. Requires priceLegend, bestPrice, lastAvailabilities, and notAvailable to be present in labels. |
title | string | undefined | Optional heading displayed at the top of the section card. |
className | string | undefined | Additional CSS class on the section card wrapper. |
children | ReactNode | undefined | Slot rendered below the calendar. Intended for CriteriaDatesReinsurance. |
...datepickerProps | DatepickerProps | — | All remaining props are forwarded to the inner Datepicker — selected, onSelect, fromMonth, defaultMonth, maxNumberOfMonths, dates, disabledDays, locale, formatDurationsLabel. |
CriteriaDatesLabels
Base labels required for all configurations.
| Field | Type | Description |
|---|---|---|
seeNextMonth | string | Accessible label for the next-month navigation button. Supports {currentMonth} and {nextMonth} token interpolation. |
seePreviousMonth | string | Accessible label for the previous-month navigation button. Supports {previousMonth} and {currentMonth} token interpolation. |
availableSeason | string? | Optional label for the season-availability legend item (outline square). Omit to hide the swatch. |
CriteriaDatesLabelsWithPriceLegend
Extends CriteriaDatesLabels with the following fields. Must be provided when showPriceLegend is true.
| Field | Type | Description |
|---|---|---|
priceLegend | string | Title of the legend region; also its aria-label. |
bestPrice | string | Label for the green (best price) swatch. |
lastAvailabilities | string | Label for the orange (high-demand) swatch. |
notAvailable | string | Label for the diagonal-strikethrough (unavailable) swatch. |
availableSeason | string? | Inherited from CriteriaDatesLabels. |
CriteriaDatesReinsurance
A companion component rendered as a child of CriteriaDates.
| Prop | Type | Default | Description |
|---|---|---|---|
labels.disclaimer | string | — | Required. The disclaimer text. The component renders nothing when this string is empty. |
className | string | undefined | Additional CSS class on the paragraph element. |
Price legend
When showPriceLegend is enabled a legend is rendered above the calendar with colour-coded swatches that mirror the Datepicker day statuses:
| Swatch | Day status | Meaning |
|---|---|---|
Green pill (bg-green) | green | Best price of the period |
Orange rounded square (bg-orange) | orange | High-demand / last available dates |
Strikethrough square (diagonal-line) | Disabled day | Date not available |
| Outline square (white + black border) | outline | Season availability (optional) |
The statusLabels passed to the inner Datepicker are derived automatically from the legend labels — no extra configuration needed for screen-reader announcements.
Notes
Labels union type
The labels prop is a union of CriteriaDatesLabels and CriteriaDatesLabelsWithPriceLegend. TypeScript raises a type error if you pass showPriceLegend={true} without the legend keys. Provide the full object to keep the type narrow, even if you conditionally hide the legend at runtime.
All Datepicker props are forwarded
CriteriaDates spreads any prop it does not recognise directly onto the inner Datepicker. labels.seeNextMonth and labels.seePreviousMonth are extracted and passed to Datepicker's own labels prop automatically — do not duplicate them.
Controlled-only
Like the underlying Datepicker, CriteriaDates holds no selection state. Always pass both selected and onSelect, otherwise clicks have no visible effect.
Client component
CriteriaDates uses React hooks internally. Add 'use client' at the top of any file that renders it in a Next.js App Router project.
Accessibility
- The price legend region uses
role="region"witharia-labelledbypointing to its title element, so screen readers announce the landmark when entering it. - Legend items are grouped in
role="list"withrole="listitem"on each entry. - Navigation button labels support month-name token interpolation, producing a fully spoken sentence (e.g. "See August 2025 and September 2025").
- When
showPriceLegendis enabled,statusLabelsare derived from the legend text and injected as visually-hidden<span class="sr-only">elements inside annotated day buttons, so each day's status is announced by screen readers. - The reinsurance disclaimer is a plain
<p>element; no additional ARIA attributes are required.
On This Page
InstallationDependenciesUsageBasic range selectionWith price legendWith reinsurance messageWith date annotations and disabled daysAPI ReferenceCriteriaDatesCriteriaDatesLabelsCriteriaDatesLabelsWithPriceLegendCriteriaDatesReinsurancePrice legendNotesLabels union typeAll Datepicker props are forwardedControlled-onlyClient componentAccessibility