KKUONIDesign System

Components

Banner

Beta

A full-width announcement strip displayed at the top of the page to communicate promotions, system information, warnings, or announcements.

Save up to 30% on selected Maldives holidays — book by 31 JulyView offers

Purpose

The Banner is a full-width strip that sits at the very top of the page, above the navigation, to convey a single high-priority message. It is designed for content that affects the entire site or session — a time-limited promotion, a service notice, a security warning, or a product announcement.

Usage

Use a Banner for:

  • Sitewide promotional offers with a deadline (e.g. "Save 30% — book by 31 July")
  • Informational notices affecting all visitors (e.g. booking line opening hours)
  • Urgent warnings such as travel advisories or payment gateway issues
  • Product and feature announcements relevant to all users

Do not use a Banner for:

  • Page-specific inline messages — use an Alert instead
  • Persistent legal notices — use a Cookie/GDPR bar component
  • Errors resulting from a user action — show an inline error near the failing field
  • Content that competes with the primary CTA on the page

A Banner sits above the site header and navigation, so it is the very first thing a visitor sees on any page — reserve it for messages important enough to occupy that position sitewide.

Anatomy

🏷Save up to 30% on selected Maldives holidays — book by 31 JulyView offers
  1. 1
    ContainerFull-width strip spanning the viewport. Background colour is determined by the variant prop. Renders above the site header.
  2. 2
    IconDecorative icon that reinforces the tone — Tag (promotional), Info (informational), AlertTriangle (warning), Megaphone (announcement). Always aria-hidden.
  3. 3
    MessageThe primary text content. Keep to a single sentence. Rendered as a span inside the ARIA live region.
  4. 4
    CTA linkOptional inline anchor rendered immediately after the message. Styled as an underlined link in the banner text colour.
  5. 5
    Dismiss buttonOptional X icon button, right-aligned. Only rendered when dismissible={true}. Calls onDismiss when clicked.

Variants

Promotional

Teal background with white text. Used for offers, discounts, and sales. The default variant. Pairs with a Tag icon.

Save up to 30% on selected Maldives holidays — book by 31 JulyView offers

Informational

Light teal background (teal-50) with teal text and a bottom border. Used for neutral notices that do not require urgent attention. Pairs with an Info icon.

Our booking lines are open Monday to Friday, 9am to 6pm.

Warning

Warning background with warning text and a bottom border. Used for time-sensitive or high-impact notices such as travel advisories or payment issues. Pairs with an AlertTriangle icon. Rendered with role="alert" and aria-live="assertive".

Do

Use the warning variant for time-sensitive or safety-critical messages. It automatically sets aria-live='assertive'.

Warnings need to be read immediately — assertive live regions interrupt the current announcement.

Don't

Set variant='warning' for non-urgent informational messages just to attract attention.

Assertive announcements interrupt screen reader users mid-sentence — overusing them is disruptive.


Announcement

Kuoni yellow background with dark text. Used for product or feature announcements that feel celebratory. Pairs with a Megaphone icon.

Introducing Kuoni Private — bespoke itineraries crafted by our top travel experts.Find out more

States

Default (persistent)

When dismissible={false} (the default), the Banner is always visible. Use for notices that the user should not be able to hide — mandatory travel advisories, sitewide outages.

Dismissible

When dismissible={true}, an X button appears on the right. Clicking it calls onDismiss. The parent is responsible for removing the Banner from the DOM (e.g. by setting a state flag). The Banner does not manage its own visibility.

const [showBanner, setShowBanner] = useState(true);

{showBanner && (
  <Banner
    variant="promotional"
    message="Save up to 30% — book by 31 July"
    dismissible
    onDismiss={() => setShowBanner(false)}
  />
)}

With CTA

When cta is provided, an inline anchor renders immediately after the message text. Keep the CTA label short (2–4 words). The href should be an absolute path or a full URL — relative fragment links (#) are for documentation examples only.

Best practices

Do

Keep the message to a single sentence. If a CTA is needed, add it via the cta prop rather than embedding a link in the message string.

One focused message keeps the banner scannable and actionable.

Don't

Stack two or more Banners simultaneously. Show the highest-priority one and queue others.

Multiple messages compete for attention and reduce the impact of each.

Do

Match the variant to the intent: promotional for offers, warning for advisories, announcement for feature reveals.

Variants are colour-coded — users learn to associate yellow with announcements and teal with promotions.

Don't

Use the promotional variant for anything other than discount or sales messaging.

A promotional-coloured banner carrying a travel warning undercuts its urgency.

Do

Persist the dismissed state in localStorage or a session cookie so the banner does not reappear on every page load.

Dismissible banners respect users who have seen the message and do not want to see it again.

Don't

Reset the dismissed state without user intent — the banner should stay hidden until the session or preference is cleared.

Re-showing a dismissed banner on every navigation undermines user trust.

Props

PropTypeDefaultDescription
variant'promotional' | 'informational' | 'warning' | 'announcement''promotional'Visual style and semantic tone of the banner. Controls background colour, text colour, icon, and ARIA live region behaviour.
message*stringThe primary text content. Keep to a single sentence. Do not include HTML — use the cta prop for links.
cta{ label: string; href: string }Optional inline call-to-action rendered as an anchor after the message. label is the link text; href is the destination URL.
dismissiblebooleanfalseWhen true, renders an X button on the right. Clicking it calls onDismiss. The parent controls whether the banner is removed from the DOM.
onDismiss() => voidCallback fired when the dismiss button is clicked. Required if dismissible is true.
idstringHTML id attribute on the root element. Useful for aria-describedby references from other elements on the page.
classNamestringAdditional CSS classes applied to the root element. Use sparingly — variant styles should not be overridden.

Accessibility

ARIA live regions

The Banner uses a live region so that screen readers announce the message when it appears dynamically:

{/* Warning */}
<div role="alert" aria-live="assertive">
  ...
</div>

{/* All other variants */}
<div role="status" aria-live="polite">
  ...
</div>
  • role="alert" + aria-live="assertive" (warning): the message interrupts the current screen reader announcement. Reserve for genuinely urgent content.
  • role="status" + aria-live="polite" (all others): the message is read after the current announcement finishes. Suitable for promotions and informational notices.

Icon accessibility

The decorative icon is always aria-hidden="true". The meaning must be conveyed through the message text alone — do not rely on the icon to communicate tone.

Dismiss button

<button type="button" aria-label="Dismiss banner">
  <XIcon aria-hidden="true" />
</button>

The dismiss button has a visible icon and an aria-label that names the action. The icon itself is aria-hidden.

Keyboard interaction

KeyAction
TabMoves focus to the CTA link or dismiss button (if present)
Enter / SpaceActivates the focused CTA link or dismiss button

Colour contrast

All Banner variants meet WCAG AA contrast ratios (4.5:1 for normal text). Do not customise the text or background colours of Banner variants — overriding them may break contrast compliance.

  • Alert — use for page-specific, content-tied messages instead of sitewide ones.
  • Callout — use for a passive inline note rather than a full-width sitewide strip.