Components
Rating
StableDisplays a read-only star rating for hotel quality classification or Feefo customer review scores on offer cards and destination pages.
Purpose
The Rating component renders a read-only star display in two distinct contexts found across kuoni.co.uk:
Hotel rating shows the official star classification (1–5) of a property. It communicates the tier of the hotel at a glance — this is industry classification, not a user-generated score. Supports half-star increments (e.g. 3.5★) to reflect how some rating bodies award grades.
Feefo review rating shows the aggregated customer satisfaction score sourced from verified Feefo reviews. It displays a numeric score (e.g. "4.9/5") alongside gold stars and the "Feefo reviews" label to distinguish it clearly from hotel classification stars.
Both variants are read-only — there is no interactive selection. Do not use this component where a user needs to submit a rating.
Usage
Reach for Rating whenever a card or detail page needs to show hotel star classification or an aggregated Feefo review score — never build a custom star row from icons. If you need a user to submit their own rating (e.g. a post-holiday review form), this component is the wrong choice; it has no interactive or selectable state.
Rating typically appears inside card components (offer cards, trip cards, resort cards) near the property name, and in the hero of hotel detail pages. When both a hotel classification and a Feefo score are shown on the same surface, always render them as two separate Rating instances with distinct source values rather than combining them into one row — see Variants.
Anatomy
- 1Numeric score — Feefo variant only. Displays "X/5" in gold to lead the eye before the stars.
- 2Star icons — Row of 5 SVG stars: filled (gold #F5A623), half-filled (clipped left 50%), or empty (#E5E5E5).
- 3Text label — Hotel variant: "X Stars" when showLabel is true. Feefo variant: "Feefo reviews" source label.
- 4Review count — Optional "(1,247 reviews)" appended after the label when reviewCount is provided.
Variants
Hotel
Official hotel star classification. Shows 1–5 stars with half-star support. No numeric prefix. Optionally shows a text label ("4 Stars").
When to use: Alongside a hotel name or property image on search results, offer cards, and hotel detail pages. Always sourced from the hotel's official classification body — never inferred from review scores.
Feefo
Aggregated customer review score from Feefo. Leads with a gold numeric score ("4.9/5"), followed by filled stars, then the "Feefo reviews" label. The source label is mandatory to avoid confusion with hotel classification stars.
When to use: On offer cards, destination overviews, and the Kuoni homepage trust bar. Always renders all stars as gold to reflect the uniformly high scores Feefo aggregates surface.
Sizes
Three sizes control the pixel dimensions of each star. The text label scales proportionally with the surrounding UI context.
| Size | Star width/height | Typical context |
|---|---|---|
sm | 12 px | Compact list rows, mobile search results |
md | 16 px | Standard offer cards, detail pages (default) |
lg | 20 px | Hero sections, large feature cards |
States
The Rating component is read-only. There are no interactive states such as hover-select or focus-ring on individual stars. The entire element is a single accessible node with an aria-label.
Full, half, and empty stars
Half stars use an SVG <clipPath> that masks the right 50% of the gold star with grey, producing a precise visual split without images or icon fonts.
Best practices
Use showLabel on hotel ratings in contexts where the star type might be ambiguous.
A label eliminates ambiguity — the user immediately knows it is hotel classification, not a review score.
Show Feefo review stars without the 'Feefo reviews' label (it renders automatically via source='feefo').
Stars alone in a Feefo context look identical to hotel stars and confuse the two data sources.
Round hotel ratings to the nearest 0.5 increment when mapping from raw data (e.g. 3.7 → 3.5).
0.5 increments accurately reflect official half-star hotel classifications used by rating bodies.
Pass arbitrary decimal values that are not multiples of 0.5 (e.g. rating=3.7).
Fractional values like 3.7 produce unpredictable SVG clip results and do not map to any official classification.
Show reviewCount alongside Feefo scores when the count is 10 or more.
Review counts provide social proof and help users calibrate how much to trust the score.
Display reviewCount for very small samples (under 10 reviews) — omit the count instead.
A rating of '4.9' from 2 reviews carries no meaningful weight and misleads users.
Use the same size prop for all Rating instances within a list or grid.
Consistent size within a card grid prevents visual noise and makes scanning easier.
Mix sizes within the same layout context (e.g. sm on one card, lg on the next).
Mixing sm and lg stars in a card row draws unequal attention to individual offers.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| rating* | number | — | Star value from 1 to 5. Supports 0.5 increments (e.g. 3.5, 4.5). Values are clamped to the 0–5 range. |
| source | 'hotel' | 'feefo' | 'hotel' | Context variant. 'hotel' renders classification stars; 'feefo' adds a numeric score prefix and the Feefo reviews label. |
| size | 'sm' | 'md' | 'lg' | 'md' | Star icon pixel size. sm=12px, md=16px, lg=20px. |
| showLabel | boolean | false | Hotel variant only. When true, appends 'X Stars' text after the star row. |
| reviewCount | number | — | Optional review count rendered as '(1,247 reviews)' after the label. Formatted with toLocaleString(). |
| className | string | — | Additional Tailwind classes merged onto the root <span>. |
Accessibility
Screen reader announcement
The root <span> carries a descriptive aria-label that summarises the full rating in plain language. All child elements (stars, numeric score, labels) are marked aria-hidden="true" so screen readers announce only the composed label — not individual SVG paths or decorative text.
{/* aria output: "4 out of 5 stars" */}
<Rating rating={4} source="hotel" />
{/* aria output: "4.9 out of 5 — Feefo customer rating, 1,247 reviews" */}
<Rating rating={4.9} source="feefo" reviewCount={1247} />
No interactive role
Because Rating is read-only, no role, tabIndex, or keyboard handlers are added. Do not add onClick to the component — if you need a "rate this" interaction, build a separate interactive component with role="radiogroup" and individual role="radio" star inputs.
Colour contrast
The gold star fill (#F5A623) on a white background produces a contrast ratio of 2.5:1 — insufficient on its own for WCAG AA text contrast. This is acceptable for decorative icon fills because the semantic information is conveyed through aria-label rather than colour alone. Empty stars (#E5E5E5) are similarly decorative and aria-hidden.
Related components
- Trip Card — commercial listing card that renders hotel star classification via its own
starRatingprop, conceptually the same data Rating displays standalone. - Resort Card — ski/walking resort card that can pair with Rating to show Feefo review scores alongside resort stats.
- Room Type Card — accommodation card where a Feefo or hotel Rating often sits near the room name.