@tui/design-system 1.13.0 → 1.14.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.14.0
4
+
5
+ ### Added
6
+
7
+ #### [Card with list](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/patterns-cards-card-with-list--docs)
8
+
9
+ - New pattern for presenting categorised label and value information, with a basic card variant and a collapsible highlight panel variant. The list
10
+ reflows into two columns from a card width of 580px, driven by a container query so it responds to the width of the card rather than the viewport.
11
+
12
+ #### [Holiday summary](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/patterns-holiday-summary--docs)
13
+
14
+ - New pattern for summarising a booking — party, dates, board, room, extras and flights — alongside the price and primary call to action.
15
+
16
+ ### Updated
17
+
18
+ #### [Grid](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/globals-grid--docs)
19
+
20
+ - Added grid content alignment modifiers. Container-level `.uilib-grid--align-[align]` / `.uilib-grid--justify-[align]` align all cells; column-level
21
+ `.uilib-grid__col--align-self-[align]` / `.uilib-grid__col--justify-self-[align]` (with responsive `[res]` variants) align individual cells.
22
+ Available values: `start`, `center`, `end`, `stretch`.
23
+
24
+ #### [Input slider](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/components-forms-input-slider--docs)
25
+
26
+ - Added a `uilib-slider-commit` event that fires once user interaction completes (pointer/mouse release or blur after keyboard adjustment). The
27
+ committed value is available on `event.detail.value`.
28
+ - Added a `valuetext-template` attribute for a custom `aria-valuetext`. Use `{value}` as the placeholder.
29
+
30
+ #### [List](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/components-list--docs)
31
+
32
+ - Added density modifiers (`uilib-list--compact`, `uilib-list--spacious`) to change the vertical spacing between list items. Default spacing is
33
+ unchanged and still needs no class. The row spacing is now set through the `--uilib-list-row-gap` custom property, so components that lay list items
34
+ out without a flex gap can apply the same density.
35
+ - Updated the multiline title (`uilib-list__title`) font from the label style to `body-medium-strong`, matching the Figma update to the List
36
+ component's text styles.
37
+
38
+ ### Fixed
39
+
40
+ #### [Global colours](https://mwa.tui.com/browse/mwa/uilib-production/storybook/index.html?path=/docs/globals-colors--docs)
41
+
42
+ - Darkened the First Choice link colour from `color-pink-70` (`#d61d5f`) to a new `color-pink-75` (`#b8194d`) primitive so it passes colour contrast
43
+ requirements on background colours.
44
+
3
45
  ## v1.13.0
4
46
 
5
47
  ### Updated
@@ -37,7 +37,7 @@
37
37
  --uilib-color-core-neutral: #fff;
38
38
  --uilib-color-text-strong: #002f17;
39
39
  --uilib-color-text-body: #002f17;
40
- --uilib-color-text-link: #d61d5f;
40
+ --uilib-color-text-link: #b8194d;
41
41
  --uilib-color-text-link-visited: #6c69b7;
42
42
  --uilib-color-text-link-visited-inverse: #9996f1;
43
43
  --uilib-color-text-inverse: #fffefe;
@@ -438,7 +438,7 @@
438
438
  --uilib-list-bullet-icon: url("https://mwa.tui.com/shared/mwa/assets/v3/icons/tui/standard/list-item.svg");
439
439
  --uilib-list-image-radius: var(--uilib-border-radius-100);
440
440
  --uilib-list-image-alt-radius: var(--uilib-border-radius-circle);
441
- --uilib-list-multiline-title-font: var(--uilib-typography-label-medium);
441
+ --uilib-list-multiline-title-font: var(--uilib-typography-body-medium-strong);
442
442
  --uilib-list-highlight-color: var(--uilib-color-text-promotion);
443
443
  --uilib-loader-image: url("https://mwa.tui.com/shared/mwa/assets/v3/motion/tui/loader.svg");
444
444
  --uilib-loader-small: 3.75rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tui/design-system",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "TUI Design System",
5
5
  "author": "TUI Group",
6
6
  "//dependencies": {
@@ -35,8 +35,8 @@
35
35
  "lint:styles": "npm run lint:styles:ci && npm run lint:styles:fix",
36
36
  "lint:styles:fix": "stylelint \"src/**/*.{scss,css}\" --fix --config .stylelintrc.fix.json",
37
37
  "lint:styles:ci": "stylelint \"src/**/*.{scss,css}\"",
38
- "lint:standard": "eslint \"storybook/**/*.{js,ts}\" \"cli/*.mjs\" --cache --config eslint.config.mjs --fix --ignore-pattern \"storybook/.storybook/**\" --no-warn-ignored",
39
- "lint:standard:ci": "eslint \"storybook/**/*.{js,ts}\" \"cli/*.mjs\" --config eslint.config.mjs --ignore-pattern \"storybook/.storybook/**\" --no-warn-ignored",
38
+ "lint:standard": "eslint \"storybook/**/*.{js,ts}\" \"cli/*.mjs\" \"figma/**/*.figma.ts\" --cache --config eslint.config.mjs --fix --ignore-pattern \"storybook/.storybook/**\" --no-warn-ignored",
39
+ "lint:standard:ci": "eslint \"storybook/**/*.{js,ts}\" \"cli/*.mjs\" \"figma/**/*.figma.ts\" --config eslint.config.mjs --ignore-pattern \"storybook/.storybook/**\" --no-warn-ignored",
40
40
  "lint:storybook": "eslint storybook/.storybook --config eslint.storybook.config.mjs --no-error-on-unmatched-pattern --fix",
41
41
  "lint:storybook:ci": "eslint storybook/.storybook --config eslint.storybook.config.mjs --no-error-on-unmatched-pattern --fix",
42
42
  "lint": "npm run lint:standard && npm run lint:storybook",
@@ -53,7 +53,8 @@
53
53
  "ci:deploy:testing": "bash ./ci-scripts/deploy/deploy-testing.sh",
54
54
  "ci:destroy:feat": " bash ./ci-scripts/destroy/destroy-feature.sh",
55
55
  "scss:compile": "sass --no-source-map --style=expanded utils/scss/input:utils/scss/output",
56
- "test:sass": "node --experimental-vm-modules node_modules/.bin/jest --verbose ./test/sass-true"
56
+ "test:sass": "node --experimental-vm-modules node_modules/.bin/jest --verbose ./test/sass-true",
57
+ "test:mcp": "node --experimental-vm-modules node_modules/.bin/jest --config jest.config.mcp.mjs"
57
58
  },
58
59
  "files": [
59
60
  "dist",
@@ -85,7 +86,7 @@
85
86
  "@storybook/addon-themes": "^10.4.5",
86
87
  "@storybook/html-vite": "^10.4.5",
87
88
  "@stylistic/eslint-plugin": "^3.1.0",
88
- "@tui/cally": "1.1.1",
89
+ "@tui/cally": "^1.1.2",
89
90
  "@types/js-beautify": "^1.14.3",
90
91
  "@types/node": "^24.0.0",
91
92
  "@typescript-eslint/eslint-plugin": "^8.46.2",
@@ -32,6 +32,17 @@
32
32
  }
33
33
  }
34
34
 
35
+ // Alignment (per cell)
36
+ @each $value in $uilib-grid-align-values {
37
+ #{$uilib-grid-selector-column}--align-self#{$prefix}-#{$value} {
38
+ @include uilib-grid-col-align-self($value);
39
+ }
40
+
41
+ #{$uilib-grid-selector-column}--justify-self#{$prefix}-#{$value} {
42
+ @include uilib-grid-col-justify-self($value);
43
+ }
44
+ }
45
+
35
46
  #{$uilib-grid-selector-column}--offset#{$prefix}-reset {
36
47
  @include uilib-grid-col-offset-reset;
37
48
  }
@@ -19,3 +19,14 @@ $axes: '', 'x', 'y';
19
19
  }
20
20
  }
21
21
  }
22
+
23
+ // Container-level alignment: applies to every cell in the grid.
24
+ @each $value in $uilib-grid-align-values {
25
+ #{$uilib-grid-selector}--align-#{$value} {
26
+ @include uilib-grid-align-items($value);
27
+ }
28
+
29
+ #{$uilib-grid-selector}--justify-#{$value} {
30
+ @include uilib-grid-justify-items($value);
31
+ }
32
+ }
@@ -219,3 +219,33 @@
219
219
  content: none;
220
220
  }
221
221
  }
222
+
223
+ /* --- Grid Alignment ------- */
224
+
225
+ /// Vertical alignment of all grid items within their cells (container-level).
226
+ /// @param {String} $value - start | center | end | stretch
227
+
228
+ @mixin uilib-grid-align-items($value) {
229
+ align-items: $value;
230
+ }
231
+
232
+ /// Horizontal alignment of all grid items within their cells (container-level).
233
+ /// @param {String} $value - start | center | end | stretch
234
+
235
+ @mixin uilib-grid-justify-items($value) {
236
+ justify-items: $value;
237
+ }
238
+
239
+ /// Vertical alignment of a single grid item within its cell (column-level).
240
+ /// @param {String} $value - start | center | end | stretch
241
+
242
+ @mixin uilib-grid-col-align-self($value) {
243
+ align-self: $value;
244
+ }
245
+
246
+ /// Horizontal alignment of a single grid item within its cell (column-level).
247
+ /// @param {String} $value - start | center | end | stretch
248
+
249
+ @mixin uilib-grid-col-justify-self($value) {
250
+ justify-self: $value;
251
+ }
@@ -9,3 +9,4 @@ $uilib-grid-selectors-custom: () !default;
9
9
  $uilib-grid-selectors-config: map.merge($uilib-grid-selectors-default, $uilib-grid-selectors-custom);
10
10
  $uilib-grid-selector: map.get($uilib-grid-selectors-config, 'grid');
11
11
  $uilib-grid-selector-column: map.get($uilib-grid-selectors-config, 'column');
12
+ $uilib-grid-align-values: start, center, end, stretch !default;
@@ -142,7 +142,15 @@ $uilib-list-included: false !default;
142
142
  &--horizontal {
143
143
  display: flex;
144
144
  flex-flow: row wrap;
145
- gap: var(--uilib-spacing-200) var(--uilib-spacing-400);
145
+ gap: var(--uilib-list-row-gap) var(--uilib-spacing-400);
146
+ }
147
+
148
+ &--compact {
149
+ --uilib-list-row-gap: 0;
150
+ }
151
+
152
+ &--spacious {
153
+ --uilib-list-row-gap: var(--uilib-spacing-400);
146
154
  }
147
155
 
148
156
  &__title {
@@ -196,9 +204,11 @@ $uilib-list-included: false !default;
196
204
 
197
205
  /* For internal use to support richText component */
198
206
  @mixin uilib-list-base() {
207
+ --uilib-list-row-gap: var(--uilib-spacing-200);
208
+
199
209
  display: flex;
200
210
  flex-flow: column;
201
- gap: var(--uilib-spacing-200) var(--uilib-spacing-500);
211
+ gap: var(--uilib-list-row-gap) var(--uilib-spacing-500);
202
212
 
203
213
  margin: 0 0 var(--uilib-spacing-400);
204
214
  padding: 0;
@@ -6,6 +6,6 @@ $uilib-list-variables: (
6
6
  bullet-icon: url('#{$uilib-assets-base-url}v3/icons/tui/standard/list-item.svg'),
7
7
  image-radius: var(--uilib-border-radius-100),
8
8
  image-alt-radius: var(--uilib-border-radius-circle),
9
- multiline-title-font: var(--uilib-typography-label-medium),
9
+ multiline-title-font: var(--uilib-typography-body-medium-strong),
10
10
  highlight-color: var(--uilib-color-text-promotion),
11
11
  ) !default;
@@ -0,0 +1,4 @@
1
+ // Card with list / index
2
+ @use 'mixins' as *;
3
+ @include uilib-card-with-list;
4
+ @include uilib-card-with-list-highlight;
@@ -0,0 +1,86 @@
1
+ // Card with list / _mixins
2
+ @use '../../cards/card/mixins' as *;
3
+ @use '../../highlight-panel/mixins' as *;
4
+ @use '../../list/mixins' as *;
5
+
6
+ $uilib-card-with-list-included: false !default;
7
+ $uilib-card-with-list-highlight-included: false !default;
8
+ $uilib-card-with-list-master-included: false !default;
9
+
10
+ // Builds card with list
11
+ @mixin uilib-card-with-list() {
12
+ @if not $uilib-card-with-list-included {
13
+ $uilib-card-with-list-included: true !global;
14
+
15
+ @include uilib-card;
16
+ @include uilib-list;
17
+ @include uilib-card-with-list-master;
18
+ }
19
+ }
20
+
21
+ @mixin uilib-card-with-list-highlight() {
22
+ @if not $uilib-card-with-list-highlight-included {
23
+ $uilib-card-with-list-highlight-included: true !global;
24
+
25
+ @include uilib-highlight-panel;
26
+ @include uilib-list;
27
+ @include uilib-card-with-list-master;
28
+ }
29
+ }
30
+
31
+ @mixin uilib-card-with-list-master() {
32
+ @if not $uilib-card-with-list-master-included {
33
+ $uilib-card-with-list-master-included: true !global;
34
+
35
+ .uilib-card-with-list {
36
+ container-name: uilib-card-with-list;
37
+ container-type: inline-size;
38
+
39
+ &__content {
40
+ display: flex;
41
+ flex-direction: column;
42
+ gap: var(--uilib-spacing-600);
43
+ }
44
+
45
+ &__heading {
46
+ margin: 0;
47
+
48
+ color: var(--uilib-color-text-strong);
49
+ font: var(--uilib-typography-component-heading-xlarge-strong);
50
+ }
51
+
52
+ &__description {
53
+ margin: 0 0 var(--uilib-spacing-200);
54
+ padding-bottom: var(--uilib-spacing-200);
55
+
56
+ border-bottom: var(--uilib-stroke-size-025) var(--uilib-stroke-style-solid) var(--uilib-color-border-divider);
57
+ }
58
+
59
+ &__value {
60
+ font: var(--uilib-typography-body-medium-strong);
61
+ }
62
+
63
+ &__list {
64
+ margin-bottom: 0;
65
+
66
+ @container uilib-card-with-list (min-width: 36.25rem) {
67
+ display: block;
68
+ column-gap: calc(var(--uilib-grid-gutter-width) * 2);
69
+
70
+ column-count: 2;
71
+ column-rule: var(--uilib-stroke-size-025) var(--uilib-stroke-style-solid) var(--uilib-color-border-divider);
72
+
73
+ > li {
74
+ margin-bottom: var(--uilib-list-row-gap);
75
+
76
+ break-inside: avoid;
77
+
78
+ &:last-child {
79
+ margin-bottom: 0;
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,3 @@
1
+ // Holiday summary / index
2
+ @use 'mixins' as *;
3
+ @include uilib-holiday-summary;
@@ -0,0 +1,94 @@
1
+ // Holiday summary / _mixins
2
+ @use '../../utility/mixins' as *;
3
+ @use '../../alert/mixins' as *;
4
+ @use '../../button/mixins' as *;
5
+ @use '../../highlight-panel/mixins' as *;
6
+ @use '../../link/mixins' as *;
7
+ @use '../../list/mixins' as *;
8
+ @use '../../price-box/mixins' as *;
9
+ @use '../../skeleton/mixins' as *;
10
+
11
+ $uilib-holiday-summary-included: false !default;
12
+ $uilib-holiday-summary-skeleton-included: false !default;
13
+
14
+ @mixin uilib-holiday-summary() {
15
+ @if not $uilib-holiday-summary-included {
16
+ $uilib-holiday-summary-included: true !global;
17
+
18
+ @include uilib-alert;
19
+ @include uilib-button;
20
+ @include uilib-highlight-panel;
21
+ @include uilib-link;
22
+ @include uilib-list;
23
+ @include uilib-price-box;
24
+ @include uilib-holiday-summary-master;
25
+ }
26
+ }
27
+
28
+ @mixin uilib-holiday-summary-skeleton() {
29
+ @if not $uilib-holiday-summary-skeleton-included {
30
+ $uilib-holiday-summary-skeleton-included: true !global;
31
+
32
+ @include uilib-skeleton;
33
+ @include uilib-holiday-summary-skeleton-master;
34
+ }
35
+ }
36
+
37
+ @mixin uilib-holiday-summary-master() {
38
+ .uilib-holiday-summary {
39
+ display: flex;
40
+ flex-direction: column;
41
+ gap: var(--uilib-spacing-300);
42
+
43
+ .uilib-list,
44
+ .uilib-alert {
45
+ margin: 0;
46
+ }
47
+
48
+ &__extras-link {
49
+ display: block;
50
+
51
+ width: max-content;
52
+ max-width: 100%;
53
+ }
54
+
55
+ &__footer {
56
+ padding-top: var(--uilib-spacing-200);
57
+
58
+ &:not(.uilib-price-box) .uilib-button {
59
+ width: 100%;
60
+ }
61
+ }
62
+ }
63
+
64
+ .uilib-highlight-panel:has(.uilib-holiday-summary) .uilib-highlight-panel__content--divider::after {
65
+ margin-top: var(--uilib-spacing-400);
66
+ }
67
+ }
68
+
69
+ @mixin uilib-holiday-summary-skeleton-master() {
70
+ .uilib-holiday-summary {
71
+ &__loading {
72
+ @include uilib-visually-hidden;
73
+ }
74
+
75
+ &__skeleton-header {
76
+ width: calc(100% + var(--uilib-spacing-400) * 2);
77
+ height: var(--uilib-spacing-1000);
78
+ margin: calc(var(--uilib-spacing-400) * -1) calc(var(--uilib-spacing-400) * -1) 0;
79
+
80
+ border-radius: 0;
81
+ }
82
+
83
+ &__skeleton-indent {
84
+ padding-left: calc(var(--uilib-icon-size-xsmall) + var(--uilib-spacing-200));
85
+ }
86
+ }
87
+
88
+ // Clips the bled header placeholder to the panel's own top corners instead of duplicating
89
+ // Highlight panel's radius token on a skeleton-owned element — stays correct even if that
90
+ // radius ever changes, since the panel's `__content` already carries it when there's no header.
91
+ .uilib-highlight-panel:has(.uilib-holiday-summary__skeleton-header) .uilib-highlight-panel__content {
92
+ overflow: hidden;
93
+ }
94
+ }
@@ -235,6 +235,8 @@ $uilib-review-card-included: false !default;
235
235
 
236
236
  .uilib-ratings-range-icons__details {
237
237
  grid-column: unset;
238
+
239
+ flex-basis: unset;
238
240
  }
239
241
 
240
242
  .uilib-card__content-container {
@@ -245,12 +247,8 @@ $uilib-review-card-included: false !default;
245
247
  }
246
248
  }
247
249
 
248
- .uilib-ratings-range-icons__details {
249
- flex-basis: unset;
250
- }
251
-
252
250
  .uilib-ratings-range-icons-group {
253
- display: none;
251
+ display: flex;
254
252
  }
255
253
 
256
254
  .uilib-ratings-range-icons__description {
@@ -259,10 +257,6 @@ $uilib-review-card-included: false !default;
259
257
  display: block;
260
258
  flex-basis: unset;
261
259
  }
262
-
263
- .uilib-ratings-range-icons-group {
264
- display: flex;
265
- }
266
260
  }
267
261
  }
268
262
  }
package/scss/mixins.scss CHANGED
@@ -62,7 +62,9 @@
62
62
  @forward 'lib/utility/mixins';
63
63
 
64
64
  // Pattern mixins
65
+ @forward 'lib/patterns/card-with-list/mixins';
65
66
  @forward 'lib/patterns/edit-search/mixins';
67
+ @forward 'lib/patterns/holiday-summary/mixins';
66
68
  @forward 'lib/patterns/reasons-to-book/mixins';
67
69
  @forward 'lib/patterns/review-card/mixins';
68
70
  @forward 'lib/patterns/review-summary/mixins';
@@ -11,7 +11,7 @@ $uilib-color-semantic-firstchoice: (
11
11
  core-neutral: map.get($uilib-firstchoice-primitives, 'color-neutral-10'),
12
12
  text-strong: map.get($uilib-firstchoice-primitives, 'color-greenpalm-100'),
13
13
  text-body: map.get($uilib-firstchoice-primitives, 'color-greenpalm-100'),
14
- text-link: map.get($uilib-firstchoice-primitives, 'color-pink-70'),
14
+ text-link: map.get($uilib-firstchoice-primitives, 'color-pink-75'),
15
15
  text-link-visited: map.get($uilib-firstchoice-primitives, 'color-purple-60'),
16
16
  text-link-visited-inverse: map.get($uilib-firstchoice-primitives, 'color-purple-30'),
17
17
  text-inverse: map.get($uilib-firstchoice-primitives, 'color-sand-10'),
@@ -7,6 +7,7 @@ $uilib-firstchoice-primitives: map.merge(
7
7
  color-pink-100: #55031b,
8
8
  color-pink-90: #770a2a,
9
9
  color-pink-80: #99143b,
10
+ color-pink-75: #b8194d,
10
11
  color-pink-70: #d61d5f,
11
12
  color-pink-60: #ff467c,
12
13
  color-pink-50: #ff7ea3,
@@ -28,7 +28,7 @@
28
28
  "primitive": "color-greenpalm-100"
29
29
  },
30
30
  "color-text-link": {
31
- "primitive": "color-pink-70"
31
+ "primitive": "color-pink-75"
32
32
  },
33
33
  "color-text-link-visited": {
34
34
  "primitive": "color-purple-60"
@@ -3,8 +3,10 @@
3
3
 
4
4
  export type Theme = 'tui' | 'firstchoice' | 'crystalski';
5
5
  export type IconSize = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'xxxlarge';
6
+ export type Size = 'small' | 'medium' | 'large';
6
7
  export type IconPosition = 'none' | 'leading' | 'trailing';
7
8
  export type ButtonVariantBase = 'primary' | 'secondary' | 'promotion' | 'search';
9
+ export type IconButtonVariant = ButtonVariantBase | 'ghost' | 'control' | 'shortlist';
8
10
  export type HeadingLevel = '2' | '3' | '4' | '5' | '6';
9
11
 
10
12
  // ═══════════════════════════════════════════════════════════
@@ -359,6 +361,7 @@ export interface InputSliderProps {
359
361
  value?: number | null;
360
362
  minLabel?: string;
361
363
  maxLabel?: string;
364
+ valueTextTemplate?: string;
362
365
  disabled?: boolean;
363
366
  }
364
367
 
@@ -441,8 +444,8 @@ export interface IconProps {
441
444
  // ─── Icon Button ─────────────────────────────────────────
442
445
  export interface IconButtonProps {
443
446
  element?: 'a' | 'button' | 'div';
444
- variant?: ButtonVariantBase | 'ghost' | 'control' | 'shortlist';
445
- size?: 'small' | 'medium' | 'large';
447
+ variant?: IconButtonVariant;
448
+ size?: Size;
446
449
  isDisabled?: boolean;
447
450
  visibleLabel?: boolean;
448
451
  labelRight?: boolean;
@@ -526,6 +529,7 @@ export type ListVariant = 'bulleted' | 'numbered' | 'icon' | 'image' | 'plain';
526
529
  export type ListTextVariant = 'default' | 'strong' | 'label';
527
530
  export type ListIconSize = 'small' | 'medium' | 'large';
528
531
  export type ListLayout = 'default' | 'columns' | 'horizontal';
532
+ export type ListDensity = 'compact' | 'default' | 'spacious';
529
533
 
530
534
  export interface ListItem {
531
535
  label?: string;
@@ -539,6 +543,7 @@ export interface ListProps {
539
543
  textVariant?: ListTextVariant;
540
544
  iconSize?: ListIconSize;
541
545
  layout?: ListLayout;
546
+ density?: ListDensity;
542
547
  /** @deprecated Use `layout: 'columns'` instead. */
543
548
  columns?: boolean;
544
549
  hint?: boolean;
@@ -553,7 +558,7 @@ export interface ListProps {
553
558
 
554
559
  // ─── Loader ────────────────────────────────────────────
555
560
  export interface LoaderProps {
556
- size?: 'small' | 'medium' | 'large';
561
+ size?: Size;
557
562
  message?: string;
558
563
  messageVisible?: boolean;
559
564
  theme?: Theme;
@@ -572,7 +577,7 @@ export interface MediaButtonProps {
572
577
  // ─── Modal ─────────────────────────────────────────────
573
578
  export interface ModalProps {
574
579
  header?: string;
575
- size?: 'small' | 'medium' | 'large';
580
+ size?: Size;
576
581
  primaryButtonLabel?: string;
577
582
  secondaryButtonLabel?: string;
578
583
  closeButtonLabel?: string;
@@ -593,7 +598,7 @@ export const Currencies = ['GBP', 'EUR', 'USD', 'SEK', 'NOK', 'DKK', 'CHF'] as c
593
598
  export type Currency = (typeof Currencies)[number];
594
599
 
595
600
  export interface PriceProps {
596
- size?: 'small' | 'medium' | 'large';
601
+ size?: Size;
597
602
  currency?: Currency;
598
603
  mainUnit?: string;
599
604
  subUnit?: string;
@@ -617,6 +622,9 @@ export interface PriceBoxProps {
617
622
  divider?: boolean;
618
623
  footer?: boolean;
619
624
  footerHtml?: string;
625
+ ctaLabel?: string;
626
+ price?: Partial<PriceProps>;
627
+ extraClasses?: string[];
620
628
  }
621
629
 
622
630
  // ─── Promo Tag ──────────────────────────────────────────
@@ -887,6 +895,26 @@ export interface TravelAwareBannerProps {
887
895
  // PATTERNS
888
896
  // ═══════════════════════════════════════════════════════════
889
897
 
898
+ // ─── Card With List ────────────────────────────────────
899
+ export interface CardWithListItem {
900
+ label?: string;
901
+ hint?: string;
902
+ hintHref?: string;
903
+ }
904
+
905
+ export interface CardWithListProps {
906
+ variant?: 'basic' | 'highlight';
907
+ heading?: string;
908
+ headingLevel?: HeadingLevel;
909
+ description?: string;
910
+ density?: ListDensity;
911
+ items?: CardWithListItem[];
912
+ collapsible?: boolean;
913
+ open?: boolean;
914
+ icon?: string;
915
+ theme?: Theme;
916
+ }
917
+
890
918
  // ─── Edit Search ────────────────────────────────────────
891
919
  export interface EditSearchProps {
892
920
  variant?: 'back' | 'list';
@@ -895,6 +923,49 @@ export interface EditSearchProps {
895
923
  uniqueId?: string;
896
924
  }
897
925
 
926
+ // ─── Holiday Summary ────────────────────────────────────
927
+ export interface HolidaySummaryRow {
928
+ icon: string;
929
+ label: string;
930
+ detail?: string | string[];
931
+ editable?: boolean;
932
+ extrasLink?: boolean;
933
+ }
934
+
935
+ export interface HolidaySummaryNote {
936
+ text: string;
937
+ strong?: boolean;
938
+ }
939
+
940
+ export interface HolidaySummaryProps {
941
+ title?: string;
942
+ open?: boolean;
943
+ collapsible?: boolean;
944
+ rows?: HolidaySummaryRow[];
945
+ extrasCount?: number;
946
+ extrasHref?: string;
947
+ extrasLabel?: string;
948
+ promoTags?: boolean;
949
+ currency?: Currency;
950
+ pricePrefix?: boolean;
951
+ priceMainUnit?: string;
952
+ priceSubUnit?: string;
953
+ priceSuffix?: string;
954
+ totalPriceValue?: string;
955
+ showPrice?: boolean;
956
+ supportingText?: HolidaySummaryNote[];
957
+ ctaLabel?: string;
958
+ footerText?: string;
959
+ footerLinkLabel?: string;
960
+ footerLinkHref?: string;
961
+ editLabel?: string;
962
+ state?: 'default' | 'skeleton';
963
+ content?: string;
964
+ loadingLabel?: string;
965
+ skeletonRows?: number;
966
+ theme?: Theme;
967
+ }
968
+
898
969
  // ─── Reasons To Book ───────────────────────────────────
899
970
  export interface ReasonToBookItem {
900
971
  pictogram: string;