@tui/design-system 1.2.0 → 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 (34) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/dist/themes/crystalski/index.css +4 -0
  3. package/dist/themes/crystalski/index.css.map +1 -1
  4. package/dist/themes/firstchoice/index.css +4 -0
  5. package/dist/themes/firstchoice/index.css.map +1 -1
  6. package/dist/themes/tui/index.css +4 -0
  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/scroller/_mixins.scss +7 -6
  19. package/scss/lib/tabs/_mixins.scss +2 -2
  20. package/scss/lib/tabs/anchor/_mixins.scss +1 -1
  21. package/scss/lib/travel-aware-banner/_index.scss +3 -0
  22. package/scss/lib/travel-aware-banner/_mixins.scss +58 -0
  23. package/scss/lib/travel-aware-banner/_variables.scss +4 -0
  24. package/scss/lib/utility/_mixins.scss +1 -0
  25. package/scss/mixins.scss +2 -0
  26. package/scss/themes/crystalski/_overrides.scss +9 -0
  27. package/scss/themes/crystalski/index.scss +6 -0
  28. package/scss/themes/firstchoice/_overrides.scss +9 -0
  29. package/scss/themes/firstchoice/index.scss +6 -0
  30. package/scss/themes/tui/index.scss +6 -0
  31. package/scss/variables/_border-radius.scss +2 -0
  32. package/scss/variables/base-theme.json +32 -2
  33. package/scss/variables.scss +2 -0
  34. package/types/components.ts +460 -442
@@ -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,217 +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' | 'customer';
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
- score?: number;
319
- /** @deprecated Use `score` instead */
320
- scoreTripadvisor?: number;
321
- /** @deprecated Use `score` instead */
322
- scoreCustomerReview?: number;
323
- /** @deprecated Icon is no longer supported */
324
- icon?: string;
325
- hasSchema?: boolean;
326
- additionalSchemaProps?: SchemaProps;
327
- /** @deprecated Theme is no longer supported for this component */
328
- theme?: Theme;
329
- isGroup?: boolean;
164
+ primaryButtonLabel?: string;
165
+ secondaryButtonLabel?: string;
166
+ closeButtonLabel?: string;
167
+ scrollerAriaLabel?: string;
330
168
  }
331
169
 
332
- // ─── Ratings: Range icons (Sun/Star/TUI/TripAdvisor/TUI-T) ─
333
- export interface RangeIconsProps {
334
- variant?: RangeIconsVariant;
335
- size?: RangeIconsSize;
336
- label?: string;
337
- linkLabel?: string;
338
- scoreT?: number;
339
- scoreCustomer?: number;
340
- scoreSun?: number;
341
- scoreStar?: number;
342
- scoreTripadvisor?: number;
343
- hasLink?: boolean;
344
- hasPlus?: boolean;
345
- hasTooltip?: boolean;
346
- tooltipText?: string;
347
- hasLeadingImage?: boolean;
348
- isInverse?: boolean;
349
- hasSchema?: boolean;
350
- 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;
351
179
  theme?: Theme;
352
180
  }
353
181
 
354
- // ─── Ratings: Range icons group ────────────────────────
355
- export interface RangeIconsGroupItem {
356
- categoryLabel: string;
357
- score: number;
358
- hasPlus?: boolean;
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;
359
194
  }
360
195
 
361
- export interface RangeIconsGroupProps {
362
- variant?: RangeIconsVariant;
363
- size?: RangeIconsSize;
364
- 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;
365
204
  theme?: Theme;
366
205
  }
367
206
 
368
- // ─── Accordion ─────────────────────────────────────────
369
- export interface AccordionProps {
370
- hasImage?: 'none' | 'logo' | 'icon';
371
- logoUrl?: string;
372
- icon?: string;
373
- headingLevel?: number;
374
- headingText: string;
375
- subTitle?: string;
376
- content: string;
377
- openState?: boolean;
378
- }
379
-
380
- export interface AccordionGroupProps extends AccordionProps {
381
- group?: 'none' | 'default' | 'divider';
382
- groupLength?: number;
383
- intro?: string;
384
- toggleOpen?: string;
385
- toggleClose?: string;
386
- }
387
-
388
- // ─── Breadcrumb ────────────────────────────────────────
389
- export interface BreadcrumbItem {
390
- label: string;
391
- href: string;
392
- isCurrent?: boolean;
393
- }
394
-
395
- export interface BreadcrumbProps {
396
- breadcrumbItems: BreadcrumbItem[];
397
- 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;
398
217
  }
399
218
 
400
219
  // ─── Image ─────────────────────────────────────────────
@@ -423,37 +242,30 @@ export interface ImageProps {
423
242
  focalPoint?: ImageFocalPoint;
424
243
  }
425
244
 
426
- // ─── Rich Text ─────────────────────────────────────────
427
- export interface RichTextProps {
245
+ // ─── In-Page Tabs ──────────────────────────────────────
246
+ export interface InPageTab {
247
+ label: string;
428
248
  content?: string;
429
- isComponent?: boolean;
430
- isInverse?: boolean;
249
+ icon?: string;
250
+ disabled?: boolean;
431
251
  }
432
252
 
433
- // ─── Media Button ──────────────────────────────────────
434
- export interface MediaButtonProps {
435
- element?: 'a' | 'button';
436
- label?: string;
437
- accessibleLabel?: string;
438
- icon?: IconPosition;
439
- iconAsset?: string;
440
- isDisabled?: boolean;
253
+ export interface InPageTabsProps {
254
+ variant?: 'left-aligned' | 'full-width';
255
+ icon?: string;
256
+ active?: string;
257
+ ariaLabelledby?: string;
258
+ tabs?: InPageTab[];
441
259
  }
442
260
 
443
- // ─── Price ─────────────────────────────────────────────
444
- export interface PriceProps {
445
- size?: 'small' | 'medium' | 'large';
446
- currency?: 'GBP' | 'EUR' | 'USD' | 'SEK' | 'NOK' | 'DKK';
447
- mainUnit?: string;
448
- subUnit?: string;
449
- suffix?: string;
450
- prefix?: boolean;
451
- totalPrice?: boolean;
452
- totalPriceValue?: string;
453
- promo?: boolean;
454
- originalPrice?: string;
455
- discount?: string;
456
- 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;
457
269
  }
458
270
 
459
271
  // ─── Input Checkbox ────────────────────────────────────
@@ -464,14 +276,59 @@ export interface InputCheckboxProps {
464
276
  disabled?: boolean;
465
277
  }
466
278
 
467
- // ─── Input Radio ───────────────────────────────────────
468
- export interface InputRadioProps {
469
- variant?: 'default' | 'strong' | 'title';
470
- disabled?: boolean;
279
+ // ─── Input Chip ────────────────────────────────────────
280
+ export interface InputChipOption {
281
+ label: string;
282
+ value: string;
471
283
  }
472
284
 
473
- // ─── Input Slider ──────────────────────────────────────
474
- export interface InputSliderProps {
285
+ export interface InputChipProps {
286
+ variant?: 'choice' | 'month-calendar';
287
+ inputType?: 'radio' | 'checkbox';
288
+ name?: string;
289
+ options?: InputChipOption[];
290
+ defaultValue?: string | string[];
291
+ disabled?: boolean;
292
+ theme?: Theme;
293
+ }
294
+
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 {
475
332
  min?: number;
476
333
  max?: number;
477
334
  step?: number;
@@ -492,22 +349,70 @@ export interface InputStepperProps {
492
349
  disabled?: boolean;
493
350
  }
494
351
 
495
- // ─── Datepicker ────────────────────────────────────────
496
- export interface DatepickerProps {
497
- rangeSelection?: boolean;
498
- dualView?: boolean;
499
- scrollableMobile?: boolean;
500
- weekNumbers?: boolean;
501
- weekLabel?: string;
502
- weekLabelFull?: string;
503
- hideInput?: boolean;
504
- separateCal?: boolean;
505
- value?: string;
506
- minDate?: string;
507
- maxDate?: string;
508
- previousLabel?: string;
509
- nextLabel?: string;
510
- 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;
511
416
  }
512
417
 
513
418
  // ─── Modal ─────────────────────────────────────────────
@@ -520,70 +425,149 @@ export interface ModalProps {
520
425
  scrollerAriaLabel?: string;
521
426
  }
522
427
 
523
- // ─── Hero ──────────────────────────────────────────────
524
- export interface HeroProps {
525
- alignment?: 'left' | 'right' | 'center';
526
- reduced?: boolean;
527
- variant?: 'default' | 'default slim' | 'flagship' | 'flagship slim' | 'illustration';
528
- heading?: string;
529
- content?: string;
530
- hideButton?: boolean;
531
- buttonLabel?: string;
532
- caveat?: string;
533
- imageUrl?: string;
534
- altText?: string;
428
+ // ─── Pagination ────────────────────────────────────────
429
+ export interface PaginationProps {
430
+ currentPage?: number;
431
+ totalPages?: number;
432
+ shouldUseLinks?: boolean;
433
+ customAriaLabel?: string;
434
+ theme?: Theme;
535
435
  }
536
436
 
537
- // ─── Scroller ──────────────────────────────────────────
538
- export interface ScrollerProps {
539
- isHorizontal?: boolean;
540
- hasFade?: boolean;
541
- 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;
542
459
  label?: string;
460
+ circleIcon?: boolean;
461
+ filled?: boolean;
462
+ size?: PromoTagSize;
463
+ theme?: Theme;
543
464
  }
544
465
 
545
- // ─── Flyout Dropdown ───────────────────────────────────
546
- export interface FlyoutDropdownProps {
547
- 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;
548
496
  label?: string;
549
- primaryButtonLabel?: string;
550
- secondaryButtonLabel?: string;
551
- closeButtonLabel?: string;
552
- 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;
553
509
  }
554
510
 
555
- // ─── Card Article ──────────────────────────────────────
556
- export interface CardArticleProps {
557
- type?: 'static' | 'link' | 'multi-link';
558
- elementType?: 'anchor' | 'button';
559
- content?: 'short' | 'medium' | 'long' | 'rich';
560
- 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;
561
531
  }
562
532
 
563
- // ─── Card Icon ─────────────────────────────────────────
564
- export interface CardIconProps {
565
- type?: 'static' | 'link';
566
- size?: 'small' | 'large';
567
- elementType?: 'anchor' | 'button';
568
- hasLabel?: boolean;
569
- labelText?: string;
570
- cardText?: string;
533
+ // ─── Ratings: Range icons group ────────────────────────
534
+ export interface RangeIconsGroupItem {
535
+ categoryLabel: string;
536
+ score: number;
537
+ hasPlus?: boolean;
571
538
  }
572
539
 
573
- // ─── Card Selectable ───────────────────────────────────
574
- export interface CardSelectableProps {
575
- disabled?: boolean;
576
- dashed?: boolean;
577
- cardType?: 'card' | 'radio' | 'checkbox';
578
- cardCount?: number;
579
- showVisibleInput?: boolean;
580
- visibleInputLocation?: 'top' | 'bottom';
581
- cardLabelText?: string;
582
- cardContentText?: string;
583
- contentLayout?: 'content only' | 'title only' | 'title and content';
584
- selectedIndex?: number;
585
- clickableArea?: 'input' | 'card';
586
- 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;
587
571
  }
588
572
 
589
573
  // ─── Search Card ───────────────────────────────────────
@@ -598,34 +582,68 @@ export interface SearchCardProps {
598
582
  toggleClose?: string;
599
583
  }
600
584
 
601
- // ─── In-Page Tabs ──────────────────────────────────────
602
- export interface InPageTab {
603
- label: string;
604
- content?: string;
605
- icon?: string;
606
- 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;
607
593
  }
608
594
 
609
- export interface InPageTabsProps {
610
- variant?: 'left-aligned' | 'full-width';
611
- icon?: string;
612
- active?: string;
613
- ariaLabelledby?: string;
614
- 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;
615
613
  }
616
614
 
617
- // ─── Anchor Tabs ───────────────────────────────────────
618
- export interface AnchorTab {
619
- label: string;
620
- href: string;
621
- 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;
622
627
  disabled?: boolean;
623
- sectionContent?: string;
628
+ theme?: Theme;
624
629
  }
625
630
 
626
- export interface AnchorTabsProps {
627
- icon?: string;
628
- ariaLabelledby?: string;
629
- tabs?: AnchorTab[];
630
- 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;
631
649
  }