- 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
Transport
Add transportation from
Top cities
Other cities
Opt for Club Med transportation:
Assistance and support in case of unforeseen events. Comfort guaranteed from departure to arrival.
'use client';
import { useState } from 'react';
import { CriteriaTransports } from '@/ui/criteria/CriteriaTransports';
import type { CriteriaTransportsProps } from '@/ui/criteria/CriteriaTransports';
const labels: CriteriaTransportsProps['labels'] = {
toggleLabel: 'Add transportation from',
topCitiesLabel: 'Top cities',
otherCitiesLabel: 'Other cities',
clubMedTransportTitle: 'Opt for Club Med transportation:',
clubMedTransportDescription:
'Assistance and support in case of unforeseen events. Comfort guaranteed from departure to arrival.',
reset: 'Reset',
apply: 'Continue',
};
const topCities = [
{ code: 'BOS', name: 'Boston Logan International (BOS)' },
{ code: 'NYC', name: 'New York all airports (NYC)' },
{ code: 'MIA', name: 'Miami International (MIA)' },
{ code: 'LAX', name: 'Los Angeles International (LAX)' },
{ code: 'SFO', name: 'San Francisco International (SFO)' },
];
const otherCities = [
{ code: 'ABQ', name: 'Albuquerque (ABQ)' },
{ code: 'ANC', name: 'Anchorage International (ANC)' },
{ code: 'ATL', name: 'Atlanta Hartsfield-Jackson (ATL)' },
{ code: 'AUS', name: 'Austin-Bergstrom International (AUS)' },
{ code: 'BNA', name: 'Nashville International (BNA)' },
{ code: 'BUF', name: 'Buffalo Niagara International (BUF)' },
{ code: 'CLT', name: 'Charlotte Douglas International (CLT)' },
{ code: 'CMH', name: 'John Glenn Columbus International (CMH)' },
{ code: 'DAL', name: 'Dallas Love Field (DAL)' },
{ code: 'DEN', name: 'Denver International (DEN)' },
{ code: 'DTW', name: 'Detroit Metropolitan Wayne County (DTW)' },
{ code: 'HNL', name: 'Daniel K. Inouye International (HNL)' },
{ code: 'IAD', name: 'Washington Dulles International (IAD)' },
{ code: 'IND', name: 'Indianapolis International (IND)' },
{ code: 'JAX', name: 'Jacksonville International (JAX)' },
{ code: 'LAS', name: 'Harry Reid International (LAS)' },
{ code: 'MCI', name: 'Kansas City International (MCI)' },
{ code: 'MCO', name: 'Orlando International (MCO)' },
{ code: 'MDW', name: 'Chicago Midway International (MDW)' },
{ code: 'MEM', name: 'Memphis International (MEM)' },
{ code: 'MSP', name: 'Minneapolis-Saint Paul International (MSP)' },
{ code: 'MSY', name: 'Louis Armstrong New Orleans International (MSY)' },
{ code: 'OAK', name: 'Oakland Metropolitan International (OAK)' },
{ code: 'ORD', name: "Chicago O'Hare International (ORD)" },
{ code: 'PHL', name: 'Philadelphia International (PHL)' },
{ code: 'PHX', name: 'Phoenix Sky Harbor International (PHX)' },
{ code: 'PIT', name: 'Pittsburgh International (PIT)' },
{ code: 'PDX', name: 'Portland International (PDX)' },
{ code: 'RDU', name: 'Raleigh-Durham International (RDU)' },
{ code: 'RSW', name: 'Southwest Florida International (RSW)' },
{ code: 'SAN', name: 'San Diego International (SAN)' },
{ code: 'SAT', name: 'San Antonio International (SAT)' },
{ code: 'SEA', name: 'Seattle-Tacoma International (SEA)' },
{ code: 'SJC', name: 'Norman Y. Mineta San José International (SJC)' },
{ code: 'SLC', name: 'Salt Lake City International (SLC)' },
{ code: 'SMF', name: 'Sacramento International (SMF)' },
{ code: 'SNA', name: 'John Wayne Airport Orange County (SNA)' },
{ code: 'STL', name: 'St. Louis Lambert International (STL)' },
{ code: 'TPA', name: 'Tampa International (TPA)' },
{ code: 'TUL', name: 'Tulsa International (TUL)' },
];
export function CriteriaTransportsDemo() {
const [enabled, setEnabled] = useState(false);
const [selected, setSelected] = useState<string | null>(null);
return (
<div className="w-[380px] space-y-24">
<CriteriaTransports
labels={labels}
title="Transport"
enabled={enabled}
topCities={topCities}
otherCities={otherCities}
selectedAirportCode={selected}
onToggle={setEnabled}
onSelect={setSelected}
onReset={() => {
setEnabled(false);
setSelected(null);
}}
onApply={() => {}}
/>
{selected && (
<p className="text-b4">
Selected: <strong>{selected}</strong>
</p>
)}
</div>
);
}
Installation
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/criteria-transports.json
Usage
import { CriteriaTransports } from '@/ui/criteria/CriteriaTransports';
export function Component() {
const [enabled, setEnabled] = useState(false);
const [selected, setSelected] = useState<string | null>(null);
return (
<CriteriaTransports
labels={{
toggleLabel: 'Add transportation from',
topCitiesLabel: 'Top cities',
otherCitiesLabel: 'Other cities',
clubMedTransportTitle: 'Opt for Club Med transportation:',
clubMedTransportDescription:
'Assistance and support in case of unforeseen events.',
reset: 'Reset',
apply: 'Continue',
}}
title="Transport"
enabled={enabled}
topCities={[
{ code: 'BOS', name: 'Boston Logan International (BOS)' },
{ code: 'NYC', name: 'New York all airports (NYC)' },
]}
otherCities={[
{ code: 'ABQ', name: 'Albuquerque (ABQ)' },
]}
selectedAirportCode={selected}
onToggle={setEnabled}
onSelect={setSelected}
onReset={() => { setEnabled(false); setSelected(null); }}
onApply={() => {}}
/>
);
}B2B Mode
The component supports a B2B booking flow via the mode="b2b" prop. In this mode, additional flight configuration fields (flight type, cabin class, and departure) appear above the airport list when transport is enabled. A single error prop covers the case where a prerequisite — such as resort selection — has not been met.
Transport
Add transportation from
Top cities
Other cities
Opt for Club Med transportation:
Assistance and support in case of unforeseen events. Comfort guaranteed from departure to arrival.
'use client';
import { useState } from 'react';
import { CriteriaTransports } from '@/ui/criteria/CriteriaTransports';
import type {
CriteriaTransportsProps,
CriteriaTransportsB2BLabels,
} from '@/ui/criteria/CriteriaTransports';
import type { RadioSelectOption } from '@/ui/forms/RadioSelect';
const labels: CriteriaTransportsProps['labels'] = {
toggleLabel: 'Add transportation from',
topCitiesLabel: 'Top cities',
otherCitiesLabel: 'Other cities',
clubMedTransportTitle: 'Opt for Club Med transportation:',
clubMedTransportDescription:
'Assistance and support in case of unforeseen events. Comfort guaranteed from departure to arrival.',
reset: 'Reset',
apply: 'Confirm',
};
const b2bLabels: CriteriaTransportsB2BLabels = {
roundTripLabel: 'Round trip',
oneWayLabel: 'One way',
cabinClassLabel: 'Class',
departureDateLabel: 'From',
};
const cabinClassOptions: RadioSelectOption<string>[] = [
{ value: 'all', label: 'All classes' },
{ value: 'economy', label: 'Economy' },
{ value: 'business', label: 'Business' },
{ value: 'first', label: 'First class' },
];
const topCities = [
{ code: 'BOS', name: 'Boston Logan International (BOS)' },
{ code: 'NYC', name: 'New York all airports (NYC)' },
{ code: 'MIA', name: 'Miami International (MIA)' },
];
const otherCities = [
{ code: 'ABQ', name: 'Albuquerque (ABQ)' },
{ code: 'ANC', name: 'Anchorage International (ANC)' },
{ code: 'ATL', name: 'Atlanta Hartsfield-Jackson (ATL)' },
{ code: 'AUS', name: 'Austin-Bergstrom International (AUS)' },
{ code: 'DEN', name: 'Denver International (DEN)' },
{ code: 'LAX', name: 'Los Angeles International (LAX)' },
{ code: 'SEA', name: 'Seattle-Tacoma International (SEA)' },
{ code: 'SFO', name: 'San Francisco International (SFO)' },
];
export function CriteriaTransportsB2BDemo() {
const [enabled, setEnabled] = useState(false);
const [selected, setSelected] = useState<string | null>(null);
const [flightType, setFlightType] = useState<'roundtrip' | 'oneway'>('roundtrip');
const [cabinClass, setCabinClass] = useState<string | undefined>(undefined);
const [departureQuery, setDepartureQuery] = useState('');
return (
<div className="w-[380px] space-y-24">
<CriteriaTransports
mode="b2b"
labels={labels}
b2bLabels={b2bLabels}
title="Transport"
enabled={enabled}
topCities={topCities}
otherCities={otherCities}
selectedAirportCode={selected}
flightType={flightType}
cabinClass={cabinClass}
cabinClassOptions={cabinClassOptions}
departureQuery={departureQuery}
onToggle={setEnabled}
onSelect={setSelected}
onFlightTypeChange={setFlightType}
onCabinClassChange={(_event, value) => setCabinClass(value)}
onDepartureQueryChange={(_event, value) => setDepartureQuery(value)}
onReset={() => {
setEnabled(false);
setSelected(null);
setFlightType('roundtrip');
setCabinClass(undefined);
setDepartureQuery('');
}}
onApply={() => {}}
/>
{selected && (
<p className="text-b4">
Selected: <strong>{selected}</strong>
</p>
)}
</div>
);
}
Error state
Pass an error string to display an error card instead of the B2B form. This is used when a prerequisite (e.g. selecting a resort) has not been completed.
<CriteriaTransports
mode="b2b"
enabled
error="Please select a resort before choosing transport."
{/* ...other required props */}
/>API Reference
CriteriaTransports
| Prop | Type | Default | Description |
|---|---|---|---|
labels | CriteriaTransportsLabels | — | Required. Localized strings for all visible text. |
title | string | — | Optional section heading rendered above the toggle. |
variant | 'card' | 'flat' | 'card' | card wraps content in a white bordered card with a sand inner panel. flat renders fields without any card background. |
mode | 'b2c' | 'b2b' | 'b2c' | Switches between B2C and B2B layouts. B2B adds flight type, cabin class, and departure selectors above the airport list. |
enabled | boolean | — | Controls whether transport selection is active (toggle on/off). |
topCities | Airport[] | — | Promoted airports shown under the "Top cities" heading. |
otherCities | Airport[] | — | Full airport list shown under the "Other cities" heading. |
selectedAirportCode | string | null | — | Code of the currently selected airport, or null for no selection. |
className | string | — | Extra CSS classes applied to the root element. |
onToggle | (enabled: boolean) => void | — | Called when the user flips the transport toggle. |
onSelect | (code: string | null) => void | — | Called with the airport code on selection, or null when deselecting. |
onReset | () => void | — | When provided, renders a "Reset" link in the footer. |
onApply | () => void | — | When provided, renders a "Continue/Confirm" button in the footer. |
b2bLabels | CriteriaTransportsB2BLabels | — | Required in B2B mode. Localized strings for the B2B-specific fields. |
flightType | 'roundtrip' | 'oneway' | 'roundtrip' | Currently selected flight type (B2B mode). |
onFlightTypeChange | (type: 'roundtrip' | 'oneway') => void | — | Called when the user changes the flight type radio (B2B mode). |
cabinClass | string | — | Currently selected cabin class value. Passed to the RadioSelect trigger (B2B mode). |
cabinClassOptions | RadioSelectOption<string>[] | — | Options list for the cabin class RadioSelect dropdown (B2B mode). |
onCabinClassChange | (event: Event, value: string) => void | — | Called when the user picks a cabin class from the dropdown (B2B mode). |
departureQuery | string | — | Controlled value for the departure TextField; also filters the airport list below (B2B mode). |
onDepartureQueryChange | (event: Event, value: string) => void | — | Called as the user types in the departure field (B2B mode). |
error | string | — | Error message shown in B2B mode instead of the flight form when a prerequisite is missing. |
Airport
| Field | Type | Description |
|---|---|---|
code | string | IATA airport code (e.g. "BOS"). Used as the selection key. |
name | string | Full display label (e.g. "Boston Logan International (BOS)"). |
CriteriaTransportsLabels
| Field | Type | Description |
|---|---|---|
toggleLabel | string | Label next to the on/off switch (e.g. "Add transportation from"). |
topCitiesLabel | string | Group heading for promoted airports. |
otherCitiesLabel | string | Group heading for remaining airports. |
clubMedTransportTitle | string | Title inside the Club Med transport info card (toggle off state). |
clubMedTransportDescription | string | Body text inside the Club Med transport info card. |
reset | string | Label for the reset link. Required when onReset is provided. |
apply | string | Label for the continue/confirm button. Required when onApply is provided. |
CriteriaTransportsB2BLabels
| Field | Type | Description |
|---|---|---|
roundTripLabel | string | Label for the round-trip radio option (e.g. "Round trip"). |
oneWayLabel | string | Label for the one-way radio option (e.g. "One way"). |
cabinClassLabel | string | Field label for the cabin class selector (e.g. "Class"). |
departureDateLabel | string | Field label for the departure date/city field (e.g. "From"). |
Behaviour
- Toggle off — Displays a Club Med transport info card explaining the benefits of booking transport. No airport selection is available (same in both B2C and B2B modes).
- Toggle on (B2C) — Hides the info card and reveals a scrollable airport list grouped into "Top cities" and "Other cities". Either group is omitted when its array is empty.
- Toggle on (B2B, no error) — Shows flight type radio buttons, a cabin class selector, a departure date/city field, then the airport list below.
- Toggle on (B2B, with error) — Shows an error card with the
errormessage instead of the B2B form. Use this when a prerequisite step (e.g. resort selection) must be completed first. - Flight type (B2B) — Radio group (using the
Radiocomponent) allowing single selection between round-trip and one-way. Fully controlled viaflightTypeandonFlightTypeChange. - Cabin class (B2B) — Uses the
RadioSelectcomponent. PasscabinClassOptionsto populate the dropdown andcabinClassfor the controlled value.onCabinClassChangefires(event, value)on selection. - Departure field (B2B) — Uses the
TextFieldcomponent with a calendar icon.departureQuerycontrols the input value;onDepartureQueryChangefires(event, value)on every keystroke. The same query also filters the airport list shown below the field. - Airport selection — Single select: clicking an already-selected airport calls
onSelect(null)to deselect it. The selected item is styled with a black background and white text. - Scroll — The airport list container is capped at
max-h-[420px]withoverflow-y-auto, so long lists scroll without expanding the card. - Footer — Rendered only when at least one of
onResetoronApplyis provided.
Accessibility
- The toggle uses
role="switch"via theSwitchcomponent. - The flight type selector uses a native
<input type="radio">group with visible labels, ensuring full keyboard and screen reader support. - Each airport item carries
role="option"andaria-selectedto communicate selection state. - The cabin class selector uses
RadioSelect, which renders a<button aria-haspopup="listbox">trigger and arole="listbox"dropdown with radio options — fully keyboard navigable. - The departure field uses
TextField, which renders a standard<input>with a visible label and calendar icon — supports all native keyboard interactions. - The continue and reset buttons are native
<button>elements with visible labels.