@tui/design-system 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +94 -3
  2. package/dist/themes/crystalski/index.css +15 -4
  3. package/dist/themes/crystalski/index.css.map +1 -1
  4. package/dist/themes/firstchoice/index.css +15 -4
  5. package/dist/themes/firstchoice/index.css.map +1 -1
  6. package/dist/themes/tui/index.css +15 -4
  7. package/dist/themes/tui/index.css.map +1 -1
  8. package/package.json +5 -5
  9. package/scss/lib/cards/selectable/_mixins.scss +2 -2
  10. package/scss/lib/forms/form-row/_mixins.scss +1 -0
  11. package/scss/lib/forms/input-checkbox/_mixins.scss +2 -0
  12. package/scss/lib/forms/input-chip/_mixins.scss +14 -10
  13. package/scss/lib/forms/input-count/_mixins.scss +2 -0
  14. package/scss/lib/forms/input-radio/_mixins.scss +2 -0
  15. package/scss/lib/forms/input-radio-scroll/_index.scss +3 -0
  16. package/scss/lib/forms/input-radio-scroll/_mixins.scss +185 -0
  17. package/scss/lib/forms/input-radio-scroll/_variables.scss +7 -0
  18. package/scss/lib/grid/_mixins.scss +1 -1
  19. package/scss/lib/ratings-reviews/range-bar/_mixins.scss +81 -22
  20. package/scss/lib/ratings-reviews/range-bar/_variables.scss +6 -6
  21. package/scss/lib/ratings-reviews/range-icons/_mixins.scss +62 -13
  22. package/scss/lib/ratings-reviews/range-icons/_variables.scss +7 -0
  23. package/scss/lib/ratings-reviews/range-icons-group/_mixins.scss +7 -1
  24. package/scss/lib/scroller/_mixins.scss +7 -6
  25. package/scss/lib/tabs/_mixins.scss +2 -2
  26. package/scss/lib/tabs/anchor/_mixins.scss +1 -1
  27. package/scss/lib/travel-aware-banner/_index.scss +3 -0
  28. package/scss/lib/travel-aware-banner/_mixins.scss +58 -0
  29. package/scss/lib/travel-aware-banner/_variables.scss +4 -0
  30. package/scss/lib/utility/_mixins.scss +1 -0
  31. package/scss/mixins.scss +2 -0
  32. package/scss/themes/crystalski/_overrides.scss +9 -0
  33. package/scss/themes/crystalski/index.scss +6 -0
  34. package/scss/themes/firstchoice/_overrides.scss +9 -0
  35. package/scss/themes/firstchoice/index.scss +6 -0
  36. package/scss/themes/tui/index.scss +6 -0
  37. package/scss/variables/_border-radius.scss +2 -0
  38. package/scss/variables/base-theme.json +88 -27
  39. package/scss/variables.scss +2 -0
  40. package/types/components.ts +461 -435
@@ -7,114 +7,24 @@ export type IconPosition = 'none' | 'leading' | 'trailing';
7
7
  export type ButtonVariantBase = 'primary' | 'secondary' | 'promotion' | 'search';
8
8
  export type HeadingLevel = '2' | '3' | '4' | '5' | '6';
9
9
 
10
- // ─── Form Row ────────────────────────────────────────────
11
- export interface FormRowProps {
12
- labelText?: string;
13
- reduced?: boolean;
14
- hint?: boolean;
15
- hintText?: string;
16
- error?: boolean;
17
- errorText?: string;
18
- group?: boolean;
19
- theme?: Theme;
20
- }
21
-
22
- // ─── Icon ────────────────────────────────────────────────
23
- export interface IconProps {
24
- type?: 'standard' | 'color' | 'bullet';
25
- nameStandard?: string;
26
- nameColor?: string;
27
- nameBullet?: string;
28
- size?: IconSize;
29
- color?: string;
30
- theme?: Theme;
31
- }
32
-
33
- // ─── Icon Button ─────────────────────────────────────────
34
- export interface IconButtonProps {
35
- element?: 'a' | 'button';
36
- variant?: ButtonVariantBase | 'ghost' | 'control' | 'shortlist';
37
- size?: 'small' | 'medium' | 'large';
38
- isDisabled?: boolean;
39
- label?: string;
40
- iconAsset?: string;
41
- selected?: boolean;
42
- theme?: Theme;
43
- }
44
-
45
- // ─── Button ──────────────────────────────────────────────
46
- export interface ButtonProps {
47
- element?: 'a' | 'button' | 'span';
48
- variant?: ButtonVariantBase | 'tertiary';
49
- size?: 'medium' | 'large';
50
- isDisabled?: boolean;
51
- label?: string;
52
- accessibleLabel?: string;
53
- widthRestrict?: boolean;
54
- icon?: IconPosition;
55
- iconAsset?: string;
56
- theme?: Theme;
57
- }
58
-
59
- // ─── Link ────────────────────────────────────────────────
60
- export interface LinkProps {
61
- href?: string;
62
- label?: string;
63
- accessibleLabel?: string;
64
- headingLink?: 'none' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
65
- isButtonLink?: boolean;
66
- isInverse?: boolean;
67
- icon?: IconPosition;
68
- iconAsset?: string;
69
- isExternal?: boolean;
70
- theme?: Theme;
71
- }
72
-
73
- // ─── Tooltip ────────────────────────────────────────────
74
- export interface TooltipProps {
75
- variant?: 'text' | 'icon';
76
- label?: string;
77
- content?: string;
78
- isInverse?: boolean;
79
- theme?: Theme;
80
- }
81
-
82
- // ─── Skeleton ───────────────────────────────────────────
83
- export const SkeletonTypes = ['heading', 'subheading', 'text', 'circle', 'card', 'container', 'spacer'] as const;
84
- export type SkeletonType = (typeof SkeletonTypes)[number];
85
-
86
- export const SkeletonWidths = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] as const;
87
- export type SkeletonWidth = (typeof SkeletonWidths)[number];
88
-
89
- export const SkeletonHeights = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] as const;
90
- export type SkeletonHeight = (typeof SkeletonHeights)[number];
91
-
92
- export interface SkeletonProps {
93
- type?: SkeletonType;
94
- variant?: 'filled' | 'outlined';
95
- width?: SkeletonWidth;
96
- widthXs?: SkeletonWidth;
97
- height?: SkeletonHeight;
98
- roundedBottom?: boolean;
99
- theme?: Theme;
100
- }
101
-
102
- // ─── Skeleton Layout ────────────────────────────────────
103
- export interface SkeletonLayoutProps {
104
- direction?: 'row' | 'column';
105
- gap?: 'sm' | 'md';
106
- justifyBetween?: boolean;
107
- theme?: Theme;
10
+ // ─── Accordion ─────────────────────────────────────────
11
+ export interface AccordionProps {
12
+ hasImage?: 'none' | 'logo' | 'icon';
13
+ logoUrl?: string;
14
+ icon?: string;
15
+ headingLevel?: number;
16
+ headingText: string;
17
+ subTitle?: string;
18
+ content: string;
19
+ openState?: boolean;
108
20
  }
109
21
 
110
- // ─── Show More Or Less ──────────────────────────────────
111
- export interface ShowMoreOrLessProps {
112
- isOpen?: boolean;
113
- textOnly?: boolean;
22
+ export interface AccordionGroupProps extends AccordionProps {
23
+ group?: 'none' | 'default' | 'divider';
24
+ groupLength?: number;
25
+ intro?: string;
114
26
  toggleOpen?: string;
115
27
  toggleClose?: string;
116
- isInverse?: boolean;
117
- theme?: Theme;
118
28
  }
119
29
 
120
30
  // ─── Active Tag ─────────────────────────────────────────
@@ -128,46 +38,6 @@ export interface ActiveTagProps {
128
38
  theme?: Theme;
129
39
  }
130
40
 
131
- // ─── Info Tag ───────────────────────────────────────────
132
- export interface InfoTagProps {
133
- variant?: 'info' | 'neutral' | 'scarcity' | 'local-product';
134
- size?: 'small' | 'medium';
135
- label?: string;
136
- leadingIcon?: boolean;
137
- leadingIconAsset?: string;
138
- theme?: Theme;
139
- }
140
-
141
- // ─── Promo Tag ──────────────────────────────────────────
142
- export const PromoTagSizes = ['xsmall', 'small', 'medium', 'large', 'xlarge', 'xxlarge'] as const;
143
- export type PromoTagSize = (typeof PromoTagSizes)[number];
144
-
145
- export interface PromoTagProps {
146
- icon?: string;
147
- label?: string;
148
- circleIcon?: boolean;
149
- filled?: boolean;
150
- size?: PromoTagSize;
151
- theme?: Theme;
152
- }
153
-
154
- // ─── Divider ───────────────────────────────────────────
155
- export interface DividerProps {
156
- variant?: 'horizontal' | 'vertical';
157
- weight?: 'light' | 'medium' | 'heavy';
158
- style?: 'solid' | 'dashed';
159
- color?: 'default' | 'strong' | 'inverse';
160
- theme?: Theme;
161
- }
162
-
163
- // ─── Loader ────────────────────────────────────────────
164
- export interface LoaderProps {
165
- size?: 'small' | 'medium' | 'large';
166
- message?: string;
167
- messageVisible?: boolean;
168
- theme?: Theme;
169
- }
170
-
171
41
  // ─── Alert ─────────────────────────────────────────────
172
42
  export interface AlertProps {
173
43
  variant?: 'info' | 'error' | 'warning' | 'success';
@@ -184,209 +54,166 @@ export interface AlertProps {
184
54
  theme?: Theme;
185
55
  }
186
56
 
187
- // ─── List ──────────────────────────────────────────────
188
- export type ListVariant = 'bulleted' | 'numbered' | 'icon' | 'image';
189
- export type ListTextVariant = 'default' | 'strong' | 'label';
190
- export type ListIconSize = 'small' | 'medium' | 'large';
191
-
192
- export interface ListProps {
193
- variant?: ListVariant;
194
- textVariant?: ListTextVariant;
195
- iconSize?: ListIconSize;
196
- columns?: boolean;
197
- inverse?: boolean;
198
- altShape?: boolean;
199
- start?: number;
200
- theme?: Theme;
201
- }
202
-
203
- // ─── Input Chip ────────────────────────────────────────
204
- export interface InputChipOption {
57
+ // ─── Anchor Tabs ───────────────────────────────────────
58
+ export interface AnchorTab {
205
59
  label: string;
206
- value: string;
60
+ href: string;
61
+ icon?: string;
62
+ disabled?: boolean;
63
+ sectionContent?: string;
207
64
  }
208
65
 
209
- export interface InputChipProps {
210
- variant?: 'choice' | 'month-calendar';
211
- inputType?: 'radio' | 'checkbox';
212
- name?: string;
213
- options?: InputChipOption[];
214
- defaultValue?: string | string[];
215
- disabled?: boolean;
216
- theme?: Theme;
66
+ export interface AnchorTabsProps {
67
+ icon?: string;
68
+ ariaLabelledby?: string;
69
+ tabs?: AnchorTab[];
70
+ sticky?: boolean;
217
71
  }
218
72
 
219
- // ─── Input Count ───────────────────────────────────────
220
- export interface InputCountOption {
73
+ // ─── Breadcrumb ────────────────────────────────────────
74
+ export interface BreadcrumbItem {
221
75
  label: string;
222
- value: string;
76
+ href: string;
77
+ isCurrent?: boolean;
223
78
  }
224
79
 
225
- export interface InputCountProps {
226
- name?: string;
227
- options?: InputCountOption[];
228
- defaultValue?: string;
229
- disabled?: boolean;
230
- theme?: Theme;
80
+ export interface BreadcrumbProps {
81
+ breadcrumbItems: BreadcrumbItem[];
82
+ ariaLabel?: string;
231
83
  }
232
84
 
233
- // ─── Input Switch ──────────────────────────────────────
234
- export interface InputSwitchProps {
235
- labelText?: string;
236
- labelOption?: 'default' | 'title';
237
- state?: boolean;
238
- disabled?: boolean;
85
+ // ─── Button ──────────────────────────────────────────────
86
+ export interface ButtonProps {
87
+ element?: 'a' | 'button' | 'span';
88
+ variant?: ButtonVariantBase | 'tertiary';
89
+ size?: 'medium' | 'large';
90
+ isDisabled?: boolean;
91
+ label?: string;
92
+ accessibleLabel?: string;
93
+ widthRestrict?: boolean;
94
+ icon?: IconPosition;
95
+ iconAsset?: string;
239
96
  theme?: Theme;
240
97
  }
241
98
 
242
- // ─── Input Select ──────────────────────────────────────
243
- export interface InputSelectProps {
244
- inputText?: string;
245
- icon?: string;
246
- disabled?: boolean;
247
- theme?: Theme;
99
+ // ─── Card Article ──────────────────────────────────────
100
+ export interface CardArticleProps {
101
+ type?: 'static' | 'link' | 'multi-link';
102
+ elementType?: 'anchor' | 'button';
103
+ content?: 'short' | 'medium' | 'long' | 'rich';
104
+ headingText?: string;
248
105
  }
249
106
 
250
- // ─── Input Text ────────────────────────────────────────
251
- export interface InputTextProps {
252
- type?: 'text' | 'number' | 'password' | 'search' | 'date';
253
- icon?: string;
254
- disabled?: boolean;
255
- valid?: boolean;
256
- theme?: Theme;
107
+ // ─── Card Icon ─────────────────────────────────────────
108
+ export interface CardIconProps {
109
+ type?: 'static' | 'link';
110
+ size?: 'small' | 'large';
111
+ elementType?: 'anchor' | 'button';
112
+ hasLabel?: boolean;
113
+ labelText?: string;
114
+ cardText?: string;
257
115
  }
258
116
 
259
- // ─── Pagination ────────────────────────────────────────
260
- export interface PaginationProps {
261
- currentPage?: number;
262
- totalPages?: number;
263
- shouldUseLinks?: boolean;
264
- customAriaLabel?: string;
265
- theme?: Theme;
266
- }
267
-
268
- // ─── Textarea ──────────────────────────────────────────
269
- export interface TextareaProps {
270
- textareaValue?: string;
271
- charCount?: number;
117
+ // ─── Card Selectable ───────────────────────────────────
118
+ export interface CardSelectableProps {
272
119
  disabled?: boolean;
273
- theme?: Theme;
274
- }
275
-
276
- // ─── Ratings: shared ───────────────────────────────────
277
- export type RangeIconsVariant = 'sun' | 'star' | 'tripadvisor' | 'tui-t';
278
- export type RangeIconsSize = 'medium' | 'large';
279
-
280
- export interface SchemaProps {
281
- reviewCount?: number;
282
- itemName?: string;
283
- author?: string;
284
- reviewAspect?: string;
120
+ dashed?: boolean;
121
+ cardType?: 'card' | 'radio' | 'checkbox';
122
+ cardCount?: number;
123
+ showVisibleInput?: boolean;
124
+ visibleInputLocation?: 'top' | 'bottom';
125
+ cardLabelText?: string;
126
+ cardContentText?: string;
127
+ contentLayout?: 'content only' | 'title only' | 'title and content';
128
+ selectedIndex?: number;
129
+ clickableArea?: 'input' | 'card';
130
+ includeImage?: boolean;
285
131
  }
286
132
 
287
- // ─── Ratings: Numerical (9/10) ─────────────────────────
288
- export type NumericalType = 'rating' | 'filter';
289
- export type NumericalVariant = 'brand' | 'alt';
290
-
291
- export interface NumericalProps {
292
- type?: NumericalType;
293
- variant?: NumericalVariant;
294
- score?: number;
295
- word?: boolean;
296
- link?: boolean;
297
- inverse?: boolean;
298
- theme?: Theme;
133
+ // ─── Datepicker ────────────────────────────────────────
134
+ export interface DatepickerProps {
135
+ rangeSelection?: boolean;
136
+ dualView?: boolean;
137
+ scrollableMobile?: boolean;
138
+ weekNumbers?: boolean;
139
+ weekLabel?: string;
140
+ weekLabelFull?: string;
141
+ hideInput?: boolean;
142
+ separateCal?: boolean;
143
+ value?: string;
144
+ minDate?: string;
145
+ maxDate?: string;
146
+ previousLabel?: string;
147
+ nextLabel?: string;
148
+ locale?: string;
299
149
  }
300
150
 
301
- // ─── Ratings: Percentage (HolidayCheck) ────────────────
302
- export type RatingPercentageVariant = 'default' | 'compact';
303
-
304
- export interface RatingPercentageProps {
305
- variant?: RatingPercentageVariant;
306
- rating?: number;
307
- reviews?: number;
308
- link?: boolean;
151
+ // ─── Divider ───────────────────────────────────────────
152
+ export interface DividerProps {
153
+ variant?: 'horizontal' | 'vertical';
154
+ weight?: 'light' | 'medium' | 'heavy';
155
+ style?: 'solid' | 'dashed';
156
+ color?: 'default' | 'strong' | 'inverse';
309
157
  theme?: Theme;
310
158
  }
311
159
 
312
- // ─── Ratings: Range bar ────────────────────────────────
313
- export type RangeBarVariant = 'customer-review' | 'tripadvisor';
314
-
315
- export interface RangeBarProps {
316
- variant?: RangeBarVariant;
160
+ // ─── Flyout Dropdown ───────────────────────────────────
161
+ export interface FlyoutDropdownProps {
162
+ variant?: 'default' | 'menu-flyout';
317
163
  label?: string;
318
- scoreTripadvisor?: number;
319
- scoreCustomerReview?: number;
320
- icon?: string;
321
- hasSchema?: boolean;
322
- additionalSchemaProps?: SchemaProps;
323
- theme?: Theme;
164
+ primaryButtonLabel?: string;
165
+ secondaryButtonLabel?: string;
166
+ closeButtonLabel?: string;
167
+ scrollerAriaLabel?: string;
324
168
  }
325
169
 
326
- // ─── Ratings: Range icons (Sun/Star/Tripadvisor/TUI-T) ─
327
- export interface RangeIconsProps {
328
- variant?: RangeIconsVariant;
329
- size?: RangeIconsSize;
330
- label?: string;
331
- linkLabel?: string;
332
- scoreT?: number;
333
- scoreSun?: number;
334
- scoreStar?: number;
335
- scoreTripadvisor?: number;
336
- hasLink?: boolean;
337
- hasPlus?: boolean;
338
- hasTooltip?: boolean;
339
- tooltipText?: string;
340
- hasLeadingImage?: boolean;
341
- isInverse?: boolean;
342
- hasSchema?: boolean;
343
- additionalSchemaProps?: SchemaProps;
170
+ // ─── Form Row ────────────────────────────────────────────
171
+ export interface FormRowProps {
172
+ labelText?: string;
173
+ reduced?: boolean;
174
+ hint?: boolean;
175
+ hintText?: string;
176
+ error?: boolean;
177
+ errorText?: string;
178
+ group?: boolean;
344
179
  theme?: Theme;
345
180
  }
346
181
 
347
- // ─── Ratings: Range icons group ────────────────────────
348
- export interface RangeIconsGroupItem {
349
- categoryLabel: string;
350
- score: number;
182
+ // ─── Hero ──────────────────────────────────────────────
183
+ export interface HeroProps {
184
+ alignment?: 'left' | 'right' | 'center';
185
+ reduced?: boolean;
186
+ variant?: 'default' | 'default slim' | 'flagship' | 'flagship slim' | 'illustration';
187
+ heading?: string;
188
+ content?: string;
189
+ hideButton?: boolean;
190
+ buttonLabel?: string;
191
+ caveat?: string;
192
+ imageUrl?: string;
193
+ altText?: string;
351
194
  }
352
195
 
353
- export interface RangeIconsGroupProps {
354
- variant?: RangeIconsVariant;
355
- size?: RangeIconsSize;
356
- items?: RangeIconsGroupItem[];
196
+ // ─── Icon ────────────────────────────────────────────────
197
+ export interface IconProps {
198
+ type?: 'standard' | 'color' | 'bullet';
199
+ nameStandard?: string;
200
+ nameColor?: string;
201
+ nameBullet?: string;
202
+ size?: IconSize;
203
+ color?: string;
357
204
  theme?: Theme;
358
205
  }
359
206
 
360
- // ─── Accordion ─────────────────────────────────────────
361
- export interface AccordionProps {
362
- hasImage?: 'none' | 'logo' | 'icon';
363
- logoUrl?: string;
364
- icon?: string;
365
- headingLevel?: number;
366
- headingText: string;
367
- subTitle?: string;
368
- content: string;
369
- openState?: boolean;
370
- }
371
-
372
- export interface AccordionGroupProps extends AccordionProps {
373
- group?: 'none' | 'default' | 'divider';
374
- groupLength?: number;
375
- intro?: string;
376
- toggleOpen?: string;
377
- toggleClose?: string;
378
- }
379
-
380
- // ─── Breadcrumb ────────────────────────────────────────
381
- export interface BreadcrumbItem {
382
- label: string;
383
- href: string;
384
- isCurrent?: boolean;
385
- }
386
-
387
- export interface BreadcrumbProps {
388
- breadcrumbItems: BreadcrumbItem[];
389
- ariaLabel?: string;
207
+ // ─── Icon Button ─────────────────────────────────────────
208
+ export interface IconButtonProps {
209
+ element?: 'a' | 'button';
210
+ variant?: ButtonVariantBase | 'ghost' | 'control' | 'shortlist';
211
+ size?: 'small' | 'medium' | 'large';
212
+ isDisabled?: boolean;
213
+ label?: string;
214
+ iconAsset?: string;
215
+ selected?: boolean;
216
+ theme?: Theme;
390
217
  }
391
218
 
392
219
  // ─── Image ─────────────────────────────────────────────
@@ -415,37 +242,30 @@ export interface ImageProps {
415
242
  focalPoint?: ImageFocalPoint;
416
243
  }
417
244
 
418
- // ─── Rich Text ─────────────────────────────────────────
419
- export interface RichTextProps {
245
+ // ─── In-Page Tabs ──────────────────────────────────────
246
+ export interface InPageTab {
247
+ label: string;
420
248
  content?: string;
421
- isComponent?: boolean;
422
- isInverse?: boolean;
249
+ icon?: string;
250
+ disabled?: boolean;
423
251
  }
424
252
 
425
- // ─── Media Button ──────────────────────────────────────
426
- export interface MediaButtonProps {
427
- element?: 'a' | 'button';
428
- label?: string;
429
- accessibleLabel?: string;
430
- icon?: IconPosition;
431
- iconAsset?: string;
432
- isDisabled?: boolean;
253
+ export interface InPageTabsProps {
254
+ variant?: 'left-aligned' | 'full-width';
255
+ icon?: string;
256
+ active?: string;
257
+ ariaLabelledby?: string;
258
+ tabs?: InPageTab[];
433
259
  }
434
260
 
435
- // ─── Price ─────────────────────────────────────────────
436
- export interface PriceProps {
437
- size?: 'small' | 'medium' | 'large';
438
- currency?: 'GBP' | 'EUR' | 'USD' | 'SEK' | 'NOK' | 'DKK';
439
- mainUnit?: string;
440
- subUnit?: string;
441
- suffix?: string;
442
- prefix?: boolean;
443
- totalPrice?: boolean;
444
- totalPriceValue?: string;
445
- promo?: boolean;
446
- originalPrice?: string;
447
- discount?: string;
448
- showDecimal?: boolean;
261
+ // ─── Info Tag ───────────────────────────────────────────
262
+ export interface InfoTagProps {
263
+ variant?: 'info' | 'neutral' | 'scarcity' | 'local-product';
264
+ size?: 'small' | 'medium';
265
+ label?: string;
266
+ leadingIcon?: boolean;
267
+ leadingIconAsset?: string;
268
+ theme?: Theme;
449
269
  }
450
270
 
451
271
  // ─── Input Checkbox ────────────────────────────────────
@@ -456,16 +276,61 @@ export interface InputCheckboxProps {
456
276
  disabled?: boolean;
457
277
  }
458
278
 
459
- // ─── Input Radio ───────────────────────────────────────
460
- export interface InputRadioProps {
461
- variant?: 'default' | 'strong' | 'title';
279
+ // ─── Input Chip ────────────────────────────────────────
280
+ export interface InputChipOption {
281
+ label: string;
282
+ value: string;
283
+ }
284
+
285
+ export interface InputChipProps {
286
+ variant?: 'choice' | 'month-calendar';
287
+ inputType?: 'radio' | 'checkbox';
288
+ name?: string;
289
+ options?: InputChipOption[];
290
+ defaultValue?: string | string[];
462
291
  disabled?: boolean;
292
+ theme?: Theme;
463
293
  }
464
294
 
465
- // ─── Input Slider ──────────────────────────────────────
466
- export interface InputSliderProps {
467
- min?: number;
468
- max?: number;
295
+ // ─── Input Count ───────────────────────────────────────
296
+ export interface InputCountOption {
297
+ label?: string;
298
+ value?: string;
299
+ }
300
+
301
+ export interface InputCountProps {
302
+ name?: string;
303
+ options?: InputCountOption[];
304
+ defaultValue?: string;
305
+ disabled?: boolean;
306
+ theme?: Theme;
307
+ }
308
+
309
+ // ─── Input Radio ───────────────────────────────────────
310
+ export interface InputRadioProps {
311
+ variant?: 'default' | 'strong' | 'title';
312
+ disabled?: boolean;
313
+ }
314
+
315
+ // ─── Input Radio Scroll ────────────────────────────────
316
+ export interface InputRadioScrollProps {
317
+ instructionText?: string;
318
+ previousText?: string;
319
+ nextText?: string;
320
+ }
321
+
322
+ // ─── Input Select ──────────────────────────────────────
323
+ export interface InputSelectProps {
324
+ inputText?: string;
325
+ icon?: string;
326
+ disabled?: boolean;
327
+ theme?: Theme;
328
+ }
329
+
330
+ // ─── Input Slider ──────────────────────────────────────
331
+ export interface InputSliderProps {
332
+ min?: number;
333
+ max?: number;
469
334
  step?: number;
470
335
  value?: number | null;
471
336
  minLabel?: string;
@@ -484,22 +349,70 @@ export interface InputStepperProps {
484
349
  disabled?: boolean;
485
350
  }
486
351
 
487
- // ─── Datepicker ────────────────────────────────────────
488
- export interface DatepickerProps {
489
- rangeSelection?: boolean;
490
- dualView?: boolean;
491
- scrollableMobile?: boolean;
492
- weekNumbers?: boolean;
493
- weekLabel?: string;
494
- weekLabelFull?: string;
495
- hideInput?: boolean;
496
- separateCal?: boolean;
497
- value?: string;
498
- minDate?: string;
499
- maxDate?: string;
500
- previousLabel?: string;
501
- nextLabel?: string;
502
- locale?: string;
352
+ // ─── Input Switch ──────────────────────────────────────
353
+ export interface InputSwitchProps {
354
+ labelText?: string;
355
+ labelOption?: 'default' | 'title';
356
+ state?: boolean;
357
+ disabled?: boolean;
358
+ theme?: Theme;
359
+ }
360
+
361
+ // ─── Input Text ────────────────────────────────────────
362
+ export interface InputTextProps {
363
+ type?: 'text' | 'number' | 'password' | 'search' | 'date';
364
+ icon?: string;
365
+ disabled?: boolean;
366
+ valid?: boolean;
367
+ theme?: Theme;
368
+ }
369
+
370
+ // ─── Link ────────────────────────────────────────────────
371
+ export interface LinkProps {
372
+ href?: string;
373
+ label?: string;
374
+ accessibleLabel?: string;
375
+ headingLink?: 'none' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
376
+ isButtonLink?: boolean;
377
+ isInverse?: boolean;
378
+ icon?: IconPosition;
379
+ iconAsset?: string;
380
+ isExternal?: boolean;
381
+ theme?: Theme;
382
+ }
383
+
384
+ // ─── List ──────────────────────────────────────────────
385
+ export type ListVariant = 'bulleted' | 'numbered' | 'icon' | 'image';
386
+ export type ListTextVariant = 'default' | 'strong' | 'label';
387
+ export type ListIconSize = 'small' | 'medium' | 'large';
388
+
389
+ export interface ListProps {
390
+ variant?: ListVariant;
391
+ textVariant?: ListTextVariant;
392
+ iconSize?: ListIconSize;
393
+ columns?: boolean;
394
+ inverse?: boolean;
395
+ altShape?: boolean;
396
+ start?: number;
397
+ theme?: Theme;
398
+ }
399
+
400
+ // ─── Loader ────────────────────────────────────────────
401
+ export interface LoaderProps {
402
+ size?: 'small' | 'medium' | 'large';
403
+ message?: string;
404
+ messageVisible?: boolean;
405
+ theme?: Theme;
406
+ }
407
+
408
+ // ─── Media Button ──────────────────────────────────────
409
+ export interface MediaButtonProps {
410
+ element?: 'a' | 'button';
411
+ label?: string;
412
+ accessibleLabel?: string;
413
+ icon?: IconPosition;
414
+ iconAsset?: string;
415
+ isDisabled?: boolean;
503
416
  }
504
417
 
505
418
  // ─── Modal ─────────────────────────────────────────────
@@ -512,70 +425,149 @@ export interface ModalProps {
512
425
  scrollerAriaLabel?: string;
513
426
  }
514
427
 
515
- // ─── Hero ──────────────────────────────────────────────
516
- export interface HeroProps {
517
- alignment?: 'left' | 'right' | 'center';
518
- reduced?: boolean;
519
- variant?: 'default' | 'default slim' | 'flagship' | 'flagship slim' | 'illustration';
520
- heading?: string;
521
- content?: string;
522
- hideButton?: boolean;
523
- buttonLabel?: string;
524
- caveat?: string;
525
- imageUrl?: string;
526
- altText?: string;
428
+ // ─── Pagination ────────────────────────────────────────
429
+ export interface PaginationProps {
430
+ currentPage?: number;
431
+ totalPages?: number;
432
+ shouldUseLinks?: boolean;
433
+ customAriaLabel?: string;
434
+ theme?: Theme;
527
435
  }
528
436
 
529
- // ─── Scroller ──────────────────────────────────────────
530
- export interface ScrollerProps {
531
- isHorizontal?: boolean;
532
- hasFade?: boolean;
533
- isInverse?: boolean;
437
+ // ─── Price ─────────────────────────────────────────────
438
+ export interface PriceProps {
439
+ size?: 'small' | 'medium' | 'large';
440
+ currency?: 'GBP' | 'EUR' | 'USD' | 'SEK' | 'NOK' | 'DKK';
441
+ mainUnit?: string;
442
+ subUnit?: string;
443
+ suffix?: string;
444
+ prefix?: boolean;
445
+ totalPrice?: boolean;
446
+ totalPriceValue?: string;
447
+ promo?: boolean;
448
+ originalPrice?: string;
449
+ discount?: string;
450
+ showDecimal?: boolean;
451
+ }
452
+
453
+ // ─── Promo Tag ──────────────────────────────────────────
454
+ export const PromoTagSizes = ['xsmall', 'small', 'medium', 'large', 'xlarge', 'xxlarge'] as const;
455
+ export type PromoTagSize = (typeof PromoTagSizes)[number];
456
+
457
+ export interface PromoTagProps {
458
+ icon?: string;
534
459
  label?: string;
460
+ circleIcon?: boolean;
461
+ filled?: boolean;
462
+ size?: PromoTagSize;
463
+ theme?: Theme;
535
464
  }
536
465
 
537
- // ─── Flyout Dropdown ───────────────────────────────────
538
- export interface FlyoutDropdownProps {
539
- variant?: 'default' | 'menu-flyout';
466
+ // ─── Ratings: Numerical (9/10) ─────────────────────────
467
+ export type NumericalType = 'rating' | 'filter';
468
+ export type NumericalVariant = 'brand' | 'alt';
469
+
470
+ export interface NumericalProps {
471
+ type?: NumericalType;
472
+ variant?: NumericalVariant;
473
+ score?: number;
474
+ word?: boolean;
475
+ link?: boolean;
476
+ inverse?: boolean;
477
+ theme?: Theme;
478
+ }
479
+
480
+ // ─── Ratings: Percentage (HolidayCheck) ────────────────
481
+ export type RatingPercentageVariant = 'default' | 'compact';
482
+
483
+ export interface RatingPercentageProps {
484
+ variant?: RatingPercentageVariant;
485
+ rating?: number;
486
+ reviews?: number;
487
+ link?: boolean;
488
+ theme?: Theme;
489
+ }
490
+
491
+ // ─── Ratings: Range bar ────────────────────────────────
492
+ export type RangeBarVariant = 'customer-review' | 'tripadvisor';
493
+
494
+ export interface RangeBarProps {
495
+ variant?: RangeBarVariant;
540
496
  label?: string;
541
- primaryButtonLabel?: string;
542
- secondaryButtonLabel?: string;
543
- closeButtonLabel?: string;
544
- scrollerAriaLabel?: string;
497
+ score?: number;
498
+ /** @deprecated Use `score` instead */
499
+ scoreTripadvisor?: number;
500
+ /** @deprecated Use `score` instead */
501
+ scoreCustomerReview?: number;
502
+ /** @deprecated Icon is no longer supported */
503
+ icon?: string;
504
+ hasSchema?: boolean;
505
+ additionalSchemaProps?: SchemaProps;
506
+ /** @deprecated Theme is no longer supported for this component */
507
+ theme?: Theme;
508
+ isGroup?: boolean;
545
509
  }
546
510
 
547
- // ─── Card Article ──────────────────────────────────────
548
- export interface CardArticleProps {
549
- type?: 'static' | 'link' | 'multi-link';
550
- elementType?: 'anchor' | 'button';
551
- content?: 'short' | 'medium' | 'long' | 'rich';
552
- headingText?: string;
511
+ // ─── Ratings: Range icons (Sun/Star/TUI/TripAdvisor/TUI-T) ─
512
+ export interface RangeIconsProps {
513
+ variant?: RangeIconsVariant;
514
+ size?: RangeIconsSize;
515
+ label?: string;
516
+ linkLabel?: string;
517
+ scoreT?: number;
518
+ scoreCustomer?: number;
519
+ scoreSun?: number;
520
+ scoreStar?: number;
521
+ scoreTripadvisor?: number;
522
+ hasLink?: boolean;
523
+ hasPlus?: boolean;
524
+ hasTooltip?: boolean;
525
+ tooltipText?: string;
526
+ hasLeadingImage?: boolean;
527
+ isInverse?: boolean;
528
+ hasSchema?: boolean;
529
+ additionalSchemaProps?: SchemaProps;
530
+ theme?: Theme;
553
531
  }
554
532
 
555
- // ─── Card Icon ─────────────────────────────────────────
556
- export interface CardIconProps {
557
- type?: 'static' | 'link';
558
- size?: 'small' | 'large';
559
- elementType?: 'anchor' | 'button';
560
- hasLabel?: boolean;
561
- labelText?: string;
562
- cardText?: string;
533
+ // ─── Ratings: Range icons group ────────────────────────
534
+ export interface RangeIconsGroupItem {
535
+ categoryLabel: string;
536
+ score: number;
537
+ hasPlus?: boolean;
563
538
  }
564
539
 
565
- // ─── Card Selectable ───────────────────────────────────
566
- export interface CardSelectableProps {
567
- disabled?: boolean;
568
- dashed?: boolean;
569
- cardType?: 'card' | 'radio' | 'checkbox';
570
- cardCount?: number;
571
- showVisibleInput?: boolean;
572
- visibleInputLocation?: 'top' | 'bottom';
573
- cardLabelText?: string;
574
- cardContentText?: string;
575
- contentLayout?: 'content only' | 'title only' | 'title and content';
576
- selectedIndex?: number;
577
- clickableArea?: 'input' | 'card';
578
- includeImage?: boolean;
540
+ export interface RangeIconsGroupProps {
541
+ variant?: RangeIconsVariant;
542
+ size?: RangeIconsSize;
543
+ items?: RangeIconsGroupItem[];
544
+ theme?: Theme;
545
+ }
546
+
547
+ // ─── Ratings: shared ───────────────────────────────────
548
+ export type RangeIconsVariant = 'sun' | 'star' | 'tripadvisor' | 'tui-t' | 'customer';
549
+ export type RangeIconsSize = 'medium' | 'large';
550
+
551
+ export interface SchemaProps {
552
+ reviewCount?: number;
553
+ itemName?: string;
554
+ author?: string;
555
+ reviewAspect?: string;
556
+ }
557
+
558
+ // ─── Rich Text ─────────────────────────────────────────
559
+ export interface RichTextProps {
560
+ content?: string;
561
+ isComponent?: boolean;
562
+ isInverse?: boolean;
563
+ }
564
+
565
+ // ─── Scroller ──────────────────────────────────────────
566
+ export interface ScrollerProps {
567
+ isHorizontal?: boolean;
568
+ hasFade?: boolean;
569
+ isInverse?: boolean;
570
+ label?: string;
579
571
  }
580
572
 
581
573
  // ─── Search Card ───────────────────────────────────────
@@ -590,34 +582,68 @@ export interface SearchCardProps {
590
582
  toggleClose?: string;
591
583
  }
592
584
 
593
- // ─── In-Page Tabs ──────────────────────────────────────
594
- export interface InPageTab {
595
- label: string;
596
- content?: string;
597
- icon?: string;
598
- disabled?: boolean;
585
+ // ─── Show More Or Less ──────────────────────────────────
586
+ export interface ShowMoreOrLessProps {
587
+ isOpen?: boolean;
588
+ textOnly?: boolean;
589
+ toggleOpen?: string;
590
+ toggleClose?: string;
591
+ isInverse?: boolean;
592
+ theme?: Theme;
599
593
  }
600
594
 
601
- export interface InPageTabsProps {
602
- variant?: 'left-aligned' | 'full-width';
603
- icon?: string;
604
- active?: string;
605
- ariaLabelledby?: string;
606
- tabs?: InPageTab[];
595
+ // ─── Skeleton ───────────────────────────────────────────
596
+ export const SkeletonTypes = ['heading', 'subheading', 'text', 'circle', 'card', 'container', 'spacer'] as const;
597
+ export type SkeletonType = (typeof SkeletonTypes)[number];
598
+
599
+ export const SkeletonWidths = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] as const;
600
+ export type SkeletonWidth = (typeof SkeletonWidths)[number];
601
+
602
+ export const SkeletonHeights = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] as const;
603
+ export type SkeletonHeight = (typeof SkeletonHeights)[number];
604
+
605
+ export interface SkeletonProps {
606
+ type?: SkeletonType;
607
+ variant?: 'filled' | 'outlined';
608
+ width?: SkeletonWidth;
609
+ widthXs?: SkeletonWidth;
610
+ height?: SkeletonHeight;
611
+ roundedBottom?: boolean;
612
+ theme?: Theme;
607
613
  }
608
614
 
609
- // ─── Anchor Tabs ───────────────────────────────────────
610
- export interface AnchorTab {
611
- label: string;
612
- href: string;
613
- icon?: string;
615
+ // ─── Skeleton Layout ────────────────────────────────────
616
+ export interface SkeletonLayoutProps {
617
+ direction?: 'row' | 'column';
618
+ gap?: 'sm' | 'md';
619
+ justifyBetween?: boolean;
620
+ theme?: Theme;
621
+ }
622
+
623
+ // ─── Textarea ──────────────────────────────────────────
624
+ export interface TextareaProps {
625
+ textareaValue?: string;
626
+ charCount?: number;
614
627
  disabled?: boolean;
615
- sectionContent?: string;
628
+ theme?: Theme;
616
629
  }
617
630
 
618
- export interface AnchorTabsProps {
619
- icon?: string;
620
- ariaLabelledby?: string;
621
- tabs?: AnchorTab[];
622
- sticky?: boolean;
631
+ // ─── Tooltip ────────────────────────────────────────────
632
+ export interface TooltipProps {
633
+ variant?: 'text' | 'icon';
634
+ label?: string;
635
+ content?: string;
636
+ isInverse?: boolean;
637
+ theme?: Theme;
638
+ }
639
+
640
+ // ─── Travel Aware Banner ─────────────────────────────────────────────
641
+ export interface TravelAwareBannerProps {
642
+ imageUrl?: string;
643
+ imageText?: string;
644
+ heading?: string;
645
+ linkUrl?: string;
646
+ linkText?: string;
647
+ linkAccessibilityLabel?: string;
648
+ isExternal?: boolean;
623
649
  }