KKUONIDesign System

Components

Board Basis Selector

Beta

A segmented option picker for selecting a meal plan or board basis. Shows price differentials between options and highlights the current selection in teal.

Choose your board basis

Purpose

The BoardBasisSelector lets customers quickly switch between meal plan options during the booking flow. Unlike a generic Select dropdown, it lays all options out simultaneously — removing the need to open a menu to compare. This is especially valuable for board basis because price differences between options are a key decision factor.

It appears in:

  • Booking funnel — step 2 or 3, after choosing room type
  • Holiday detail page — alongside price to show what changes with board basis
  • Quote builder — where agents or customers customise a package

Usage

Reach for BoardBasisSelector when a small, fixed set of board basis options (4 or fewer) needs to be compared side by side with visible price differentials. For 5 or more options, or when price comparison isn't the primary decision driver, use a Select dropdown instead.

It sits within the booking funnel's room/board step, on the holiday detail page price panel, or inside a quote builder — always adjacent to the price it affects.

Anatomy

Board basis

  1. 1
    Label14px medium weight group label above the buttons. e.g. "Board basis".
  2. 2
    Option buttonRounded card button for each option. Unselected = white bg + grey border. Selected = teal-50 bg + teal border + teal text.
  3. 3
    Option labelBold short name. e.g. "Half Board", "All Inclusive".
  4. 4
    Option descriptionOptional secondary line. e.g. "Breakfast and evening meal included".
  5. 5
    Price differentialShown below description. +£N pp = grey, -£N pp = green, 0 = "Included" (base price).

Variants

With descriptions

Add description to each option to explain what the board basis includes.

Board basis


Without price differentials

Set showPriceDiff={false} when all options are the same price, or when price is displayed separately.

Meal plan


With a disabled option

Pass disabled: true on an option to mark it unavailable (e.g. All Inclusive not available at this property).

Board basis

States

StateAppearance
UnselectedWhite bg, grey-200 border, kuoni-dark text
SelectedTeal-50 bg, teal border, teal text
Hover (unselected)Teal border (border transitions)
Disabled option50% opacity, cursor-not-allowed
Full group disabledAll options unclickable

Best practices

Do

Always show price differentials when options have different prices — it is the primary decision driver.

Price differentials like '+£150 pp' let customers decide instantly without recalculating.

Don't

Remove price differentials to keep the UI clean — they are essential for board basis decisions.

Hiding the price differential forces users to go back and recalculate after selecting.

Do

Keep options to 4 or fewer. If a resort offers more than 4 board basis options, use a Select dropdown instead.

3-4 options lay out cleanly in a row on desktop. More wrap onto two rows.

Don't

Use BoardBasisSelector for 5 or more options — Switch to Select component.

5+ pill buttons start to wrap inconsistently and lose the at-a-glance comparison benefit.

Do

Always set a defaultValue or value — leaving all options unselected forces an unnecessary extra step.

Pre-selecting the most common option (Bed and Breakfast) reduces friction for the majority of users.

Don't

Leave the selector without a default value in the booking funnel.

No pre-selection on the board basis step means users must explicitly choose even if the default suits them.

Props

PropTypeDefaultDescription
options*Array<{ value: string; label: string; description?: string; priceDiff?: number; disabled?: boolean }>Array of board basis options. priceDiff: positive=extra cost, negative=saving, 0=base price (shows "Included").
valuestringControlled selected option value. Parent manages state when provided.
defaultValuestringfirst optionInitial selection for uncontrolled usage.
onChange(value: string, option: object) => voidCalled when a new option is selected.
disabledbooleanfalseDisables all options in the group.
labelstring'Board basis'Group label shown above the options.
showPriceDiffbooleantrueWhether to show the price differential below each option label.
classNamestringAdditional Tailwind classes on the root container.

Accessibility

Radio group semantics

BoardBasisSelector renders with role="radiogroup" on the container and role="radio" with aria-checked on each button. This matches the single-selection semantic of a radio group.

<div role="radiogroup" aria-label="Board basis">
  <button role="radio" aria-checked={false}>Bed and Breakfast</button>
  <button role="radio" aria-checked={true}>Half Board</button>
</div>

Keyboard interaction

KeyAction
TabMove focus to the group, then through each option
Enter / SpaceSelect the focused option
Arrow keysNot implemented — use Tab to navigate between options

Price differential

The price differential text (+£150 pp, -£200 pp, Included) is included in the accessible name of each button, so screen readers announce the full option including cost impact.

  • Select — use instead when there are 5 or more board basis options.