KKUONIDesign System

Components

Search Bar

Stable

The SearchBar is a three-field holiday search widget — destination, departure date and traveller count — used at the top of search and results pages.

Purpose

The SearchBar is the primary entry point for holiday discovery. It collects the three key parameters a Kuoni search requires — where, when, and how many — and submits them via the onSearch callback. The consuming page or route handles navigation to search results.

It appears:

  • In the homepage hero section (the most prominent placement)
  • At the top of the /offers/ listing page
  • Potentially stickied above search results on scroll

The SearchBar is a client component with internal state for field values and the traveller picker dropdown. Pass defaultDestination, defaultDate, defaultAdults, and defaultChildren to pre-fill it for returning users or for contextual placements (e.g. pre-fill "Maldives" on the Maldives destination page).

Usage

Reach for SearchBar as the entry point into holiday discovery — it's for starting a new search, not for narrowing results already on screen. Once a user has landed on a results page, use Quick Filter Bar to refine results and Sort Dropdown to reorder them; SearchBar itself is not meant to be repeated as an in-page filter control.

It appears once per page, in the highest-prominence position: the homepage hero, the top of the /offers/ listing page, and optionally stickied above results on scroll.

Anatomy

  1. 1
    ContainerWhite rounded-xl card with shadow and border. Flex row on desktop (≥768px), stacked column on mobile.
  2. 2
    Destination panelMapPin icon + "Destination" label + free-text input. Placeholder: "Where would you like to go?"
  3. 3
    Date panelCalendar icon + "Departure date" label + native date input. Shows the browser date picker on focus.
  4. 4
    Travellers panelUsers icon + "Travellers" label + button showing current count. Clicking opens the traveller picker dropdown.
  5. 5
    Traveller pickerAbsolute-positioned dropdown with Adults and Children counters (− N +). Closes on outside click or Escape.
  6. 6
    Search buttonTeal button, full height on the right. Calls the onSearch callback with current field values.

Variants

Default — three panels

Destination, departure date, and travellers. Use this for all primary search placements.


Pre-filled for context

Pre-fill the destination when the search bar appears on a destination page. The user still sees the value and can modify it.

States

Idle

All fields show their placeholder text or default values. The traveller picker is closed.

Destination focused

The destination text input has browser focus. The cursor appears. The field label is always visible — it does not collapse into the placeholder on focus.

Traveller picker open

Clicking the Travellers panel toggles the picker dropdown. The dropdown shows Adults (min 1) and Children (min 0, under 18) counters with − and + buttons. A "Done" button closes the picker.

The picker closes on:

  • Clicking "Done"
  • Clicking outside the travellers panel and picker
  • Pressing Escape

Filled

All fields have values. The summary line in the Travellers panel updates to reflect the count: "2 Adults" → "2 Adults, 1 Child".

Mobile layout

On screens below 768px (md breakpoint), the three panels stack vertically with a border between each. The Search button spans the full width at the bottom.

Best practices

Do

Pre-fill defaultDestination with the current region when the SearchBar appears on a destination page.

Pre-filled destination creates a faster path to results on destination pages.

Don't

Clear the destination field when navigating between pages if the user already filled it.

Resetting all fields on every page mount ignores the user's stated intent.

Do

Pass an onSearch handler that navigates to your results route with the search parameters.

The onSearch callback receives all field values — use them to build the query URL.

Don't

Render SearchBar without an onSearch prop in a production placement.

Without an onSearch handler the Search button silently does nothing.

Do

Use the native date input for date selection unless your design system requires a custom calendar picker.

The native date input is accessible and familiar — prefer it over a custom calendar.

Don't

Hide the date and travellers panels to save space — use a compact text input instead.

Showing only the destination field removes the context a traveller needs to search meaningfully.

Do

Let the traveller summary label update reactively as the user adjusts counts.

'1 Adult, 2 Children' in the travellers summary is more informative than a number alone.

Don't

Show only a number in the travellers field without the 'Adults' / 'Children' labels.

A count of '3' without context is ambiguous — is it adults, or total people?

Props

PropTypeDefaultDescription
defaultDestinationstring''Initial value for the destination text field. Shown on mount; user can edit.
defaultDatestring''Initial value for the date field in ISO format (YYYY-MM-DD).
defaultAdultsnumber2Initial adult count. Minimum 1, maximum 9.
defaultChildrennumber0Initial children count (under 18). Minimum 0, maximum 9.
onSearch({ destination, date, adults, children }: SearchParams) => voidCalled when the Search button is clicked. Receives all current field values. Use to navigate to results.
classNamestringAdditional Tailwind classes on the root container element.

Accessibility

Form landmark

The root element has role="search" and aria-label="Holiday search". This exposes it as a search landmark in the accessibility tree — screen reader users can jump directly to it using landmark navigation.

Field labels

Each panel has a visible label (not a floating placeholder). Labels are associated with their inputs:

  • Destination: <label htmlFor="sb-destination">
  • Departure date: <label htmlFor="sb-date">
  • Travellers: a <p> label with the Travellers button below

This means a screen reader user hears "Destination — text input" and "Departure date — date input" without needing to guess from placeholder text alone.

Traveller picker

The Travellers toggle button has:

  • aria-expanded={travellersOpen} — announces open/closed state
  • aria-haspopup="dialog" — signals a popup will appear

Each counter button has an aria-label like "Increase Adults count" and "Decrease Children count". The count value has aria-live="polite" so screen readers announce it when it changes.

Keyboard interaction

KeyAction
TabMove between destination, date, travellers button, search button
Enter / SpaceOpen travellers picker (when travellers button focused)
EscapeClose travellers picker
Tab within pickerMove between − and + buttons and Done button

Search button

The Search button has aria-label="Search holidays" in addition to the visible "Search" label, so the icon is not the sole accessible name.

  • Quick Filter Bar — refines results already returned by a search; used together with SearchBar in a typical search-to-results flow.
  • Sort Dropdown — reorders results after a search; commonly sits alongside the results grid that SearchBar's query populates.