Foundations
Iconography
The icon set, three standard sizes, usage rules, and every icon currently in the Kuoni component library.
Icons are the system's smallest vocabulary. A search icon needs no label in a search bar. A star needs no caption on a rating row. But when an icon appears without its meaning being truly universal — a departure plane that could mean "outbound flight" or "search for flights" — it needs a label. The rule is simple: when in doubt, add a label.
Kuoni uses Lucide as its icon library. Lucide icons are 1px-stroked SVGs drawn on a 24 × 24 grid, designed to feel neutral and considered at every size. Do not mix in icons from other libraries — the stroke weight, corner treatment and optical sizing differ in ways that are immediately visible when compared.
Sizing
Three standard sizes cover every situation in the component library. Sizes are expressed in Tailwind utility classes; do not set icon sizes ad hoc.
icon-sm · h-4 w-4
Inside compact UI — chips, badge counts, dense menus
icon-md · h-5 w-5
Default pairing with body text and button labels
icon-lg · h-6 w-6
Section headings, standalone icon buttons, empty states
Size token reference
| Token | px | Tailwind | When to use |
|---|---|---|---|
| icon-sm | 16 px | h-4 w-4 | Compact contexts: filter chips, notification badges, dense list items |
| icon-md | 20 px | h-5 w-5 | Default — pairs with text-sm and text-base body copy, button labels |
| icon-lg | 24 px | h-6 w-6 | Section headings (h2), standalone icon buttons, empty-state illustrations |
Use
h-5 w-5(20 px) whenever you are unsure. It is the default size used in the majority of Kuoni components and is the size Lucide optimises for.
Icon + label vs icon-only
Most icons should be paired with a visible text label. An icon-only button is acceptable only where the action is truly self-evident (a close × in a modal, an open-in-new-tab arrow next to a URL) or where screen space makes a label impossible (icon-only nav bars on very small viewports).
Pair a calendar icon with the label "Choose dates" on a date-picker trigger.
A label removes any ambiguity about what the icon does.
Use a lone calendar icon as the only affordance for a date-picker trigger.
Calendar could mean view, pick, or add — the user has to guess.
Use an icon-only close button at the top-right of a modal with aria-label="Close".
Close (×) is universally understood in a modal header. An aria-label covers screen readers.
Add a visible text label "Close" next to the × dismiss button in a modal.
Repeating the word “Close” beside an × is redundant and adds clutter.
Placement and alignment
Icons sit inline with text at a 4 px (gap-1) or 8 px (gap-2) gap.
They are vertically centred with their companion label using flex items-center.
| Gap | Token | When to use |
|---|---|---|
| 4 px | space.1 / gap-1 | Icon inside a compact chip or badge |
| 8 px | space.2 / gap-2 | Icon next to a button label or heading |
Colour
Icons inherit text colour (currentColor). Apply colour at the parent element
or pass a Tailwind text-* class on the icon itself.
- Primary actions:
text-kuoni-darkon yellow,text-whiteon dark - Informational:
text-grey-500for secondary/decorative icons - Semantic icons: match the semantic colour —
text-success,text-danger, etc. - Never use
text-kuoni-yellowdirectly on white — at 1.63:1 contrast it fails all WCAG levels
Accessibility
Every icon must be either decorative or labelled — never both, never neither.
- Decorative icon (label is already present nearby): add
aria-hidden="true"so screen readers skip it - Standalone icon (no visible label): add
aria-labelto the interactive element, e.g.<button aria-label="Search"> - Inline icon in prose: wrap it in
<span aria-hidden="true">so it doesn't disrupt reading flow
{/* Decorative — the button label provides the accessible name */}
<button className="flex items-center gap-2">
<Search className="h-5 w-5" aria-hidden="true" />
Search holidays
</button>
{/* Standalone — aria-label is the only accessible name */}
<button aria-label="Search" className="rounded-full p-2">
<Search className="h-5 w-5" aria-hidden="true" />
</button>
Icon library
Every icon below is actively used in the Kuoni component library. Use these before reaching for alternatives — consistency of vocabulary matters as much as consistency of style.
Human-readable names map directly to Lucide exports:
import { Search, Calendar, Star } from 'lucide-react'.