@energie360/ui-library 0.1.17 → 0.1.19

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 (100) hide show
  1. package/base/_input-resets.scss +3 -0
  2. package/components/badge/badge.scss +56 -0
  3. package/components/badge/u-badge.vue +47 -0
  4. package/components/card-contact/card-contact.scss +39 -0
  5. package/components/card-contact/u-card-contact.vue +44 -0
  6. package/components/card-cta-bar/card-cta-bar.scss +4 -0
  7. package/components/card-cta-bar/u-card-cta-bar.vue +24 -0
  8. package/components/card-cta-header/u-card-cta-header.vue +10 -7
  9. package/components/card-footer/u-card-footer.vue +5 -3
  10. package/components/card-group/u-card-group.vue +1 -1
  11. package/components/card-header/card-header.scss +29 -4
  12. package/components/card-header/u-card-header.vue +22 -3
  13. package/components/card-highlight/card-highlight.scss +87 -0
  14. package/components/card-highlight/u-card-highlight.vue +54 -0
  15. package/components/card-price-list/card-price-list.scss +39 -0
  16. package/components/card-price-list/u-card-price-list.vue +37 -0
  17. package/components/card-section/card-section.scss +21 -1
  18. package/components/card-section/u-card-section.vue +9 -1
  19. package/components/chip/chip.scss +25 -0
  20. package/components/chip/u-chip.vue +31 -0
  21. package/components/data-card/data-card.scss +34 -0
  22. package/components/data-card/u-data-card.vue +49 -0
  23. package/components/data-card-group/data-card-group.scss +12 -0
  24. package/components/data-card-group/u-data-card-group.vue +7 -0
  25. package/components/download-list/download-list.scss +58 -0
  26. package/components/download-list/u-download-list.vue +44 -0
  27. package/components/download-list-item/download-list-item.scss +267 -0
  28. package/components/download-list-item/u-download-list-item.vue +65 -0
  29. package/components/file-upload/file-list.scss +68 -0
  30. package/components/file-upload/file-upload.scss +119 -0
  31. package/components/file-upload/u-file-list.vue +55 -0
  32. package/components/file-upload/u-file-upload.vue +220 -0
  33. package/components/hint/hint.scss +67 -6
  34. package/components/hint/u-hint.vue +11 -1
  35. package/components/index.js +16 -0
  36. package/components/progress-avatar/u-progress-avatar.vue +27 -3
  37. package/components/rating/rating.scss +76 -0
  38. package/components/rating/u-rating.vue +79 -0
  39. package/components/search-group/search-group.scss +59 -0
  40. package/components/search-group/u-search-group.vue +32 -0
  41. package/components/skeleton-loader/skeleton-loader.scss +39 -0
  42. package/components/skeleton-loader/u-skeleton-loader.vue +28 -0
  43. package/components/table/cell-ctas.scss +1 -7
  44. package/components/table/cell-icon-text.scss +15 -4
  45. package/components/table/table-cell.mixins.scss +3 -2
  46. package/components/table/table-cell.scss +5 -0
  47. package/components/table/table-heading.scss +7 -0
  48. package/components/table/u-cell-ctas.vue +15 -6
  49. package/components/table/u-cell-icon-text.vue +13 -5
  50. package/components/table/u-table-cell.vue +3 -1
  51. package/components/table/u-table-heading.vue +2 -1
  52. package/components/tabs/tabs.scss +10 -1
  53. package/components/tabs/u-tabs.vue +64 -25
  54. package/dist/base-style.css +3 -0
  55. package/dist/base-style.css.map +1 -1
  56. package/dist/layout/split.css.map +1 -1
  57. package/elements/button/_button-plain-small-spaceless.scss +10 -0
  58. package/elements/button/button.scss +32 -0
  59. package/elements/button/u-button.vue +47 -4
  60. package/elements/form-field/form-field-base.scss +4 -0
  61. package/elements/numeric-stepper/u-numeric-stepper.vue +35 -12
  62. package/elements/select/u-select.vue +6 -6
  63. package/elements/text-field/text-field.scss +15 -0
  64. package/elements/text-field/text-field.types.ts +1 -0
  65. package/elements/text-field/u-text-field.vue +27 -6
  66. package/elements/toggle-switch/toggle-switch-small.scss +10 -0
  67. package/elements/toggle-switch/toggle-switch.scss +25 -21
  68. package/elements/toggle-switch/u-toggle-switch.vue +22 -12
  69. package/i18n/i18n.ts +40 -0
  70. package/layout/container/container.scss +18 -0
  71. package/layout/index.js +4 -1
  72. package/layout/portal/portal.scss +35 -7
  73. package/layout/portal/u-portal.vue +33 -4
  74. package/layout/portal-content-aside/portal-content-aside.scss +35 -0
  75. package/layout/portal-content-aside/u-portal-content-aside.vue +15 -0
  76. package/layout/responsive-container/u-responsive-container.vue +35 -0
  77. package/layout/tile-grid/tile-grid.scss +13 -0
  78. package/layout/tile-grid/tile-item.scss +31 -0
  79. package/layout/tile-grid/u-tile-grid.vue +7 -0
  80. package/layout/tile-grid/u-tile-item.vue +15 -0
  81. package/modules/content-title/content-title.scss +43 -0
  82. package/modules/content-title/u-content-title.vue +19 -0
  83. package/modules/dialog/dialog.scss +11 -3
  84. package/modules/dialog/u-dialog.vue +8 -2
  85. package/modules/footer/footer.scss +8 -1
  86. package/modules/footer/u-footer.vue +1 -1
  87. package/modules/index.js +2 -0
  88. package/modules/search-filter/search-filter.scss +106 -0
  89. package/modules/search-filter/u-search-filter.vue +54 -0
  90. package/package.json +2 -1
  91. package/utils/array/intersect.js +7 -0
  92. package/utils/functions/breakpoint.js +4 -9
  93. package/utils/functions/format-bytes.js +17 -0
  94. package/utils/global/mime-types.js +8 -0
  95. package/utils/translations/translate.js +10 -2
  96. package/wizard/index.js +1 -0
  97. package/wizard/wizard-top-bar/u-wizard-top-bar.vue +31 -0
  98. package/wizard/wizard-top-bar/wizard-top-bar.scss +35 -0
  99. package/layout/settings/settings.scss +0 -33
  100. package/layout/settings/u-settings-layout.vue +0 -19
@@ -47,6 +47,9 @@ textarea {
47
47
  }
48
48
 
49
49
  input[type='number'] {
50
+ // stylelint-disable
51
+ -moz-appearance: textfield;
52
+
50
53
  &::-webkit-inner-spin-button,
51
54
  &::-webkit-outer-spin-button {
52
55
  appearance: none;
@@ -0,0 +1,56 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ $ease-out-bounce: cubic-bezier(0.674, 1.901, 0.651, 0.744);
4
+
5
+ .badge {
6
+ display: inline-flex;
7
+ position: relative;
8
+ vertical-align: middle;
9
+
10
+ &.show {
11
+ .badge__sup {
12
+ opacity: 1;
13
+ }
14
+ }
15
+ }
16
+
17
+ .badge__sup {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ position: absolute;
22
+ color: var(--e-c-mono-00);
23
+ border-radius: 100%;
24
+ top: var(--top, -6px);
25
+ right: var(--right, -6px);
26
+ opacity: 0;
27
+
28
+ &.border {
29
+ box-shadow: 0 0 0 2px var(--e-c-mono-00);
30
+ }
31
+ }
32
+
33
+ .badge__sup.number {
34
+ width: 16px;
35
+ height: 16px;
36
+ font-size: 10px;
37
+ font-weight: bold;
38
+ line-height: 1;
39
+ }
40
+
41
+ .badge__sup.state {
42
+ width: 13px;
43
+ height: 13px;
44
+
45
+ &.inactive {
46
+ background-image: url("data:image/svg+xml,%3Csvg width='13' height='13' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='6.5' cy='6.5' r='6.5' fill='%23333'/%3E%3Cpath d='m4.414 3 2.12 2.121L8.658 3l1.414 1.414-2.122 2.122 2.122 2.121-1.414 1.414-2.122-2.12-2.12 2.12L3 8.656l2.12-2.12L3 4.412 4.414 3Z' fill='%23fff'/%3E%3C/svg%3E");
47
+ }
48
+ }
49
+
50
+ .badge__sup.dot {
51
+ top: var(--top, -3px);
52
+ right: var(--right, -3px);
53
+ width: 8px;
54
+ height: 8px;
55
+ border-radius: 100%;
56
+ }
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ color?: string
4
+ dot?: boolean
5
+ type?: 'default' | 'success' | 'error' | 'warning' | 'info'
6
+ value?: number
7
+ state?: '' | 'inactive'
8
+ show?: boolean
9
+ border?: boolean
10
+ top?: number
11
+ right?: number
12
+ }
13
+
14
+ const { color = 'var(--e-c-mono-900)', type = 'default', show = true } = defineProps<Props>()
15
+ </script>
16
+
17
+ <template>
18
+ <span
19
+ :class="['badge', { show }]"
20
+ :style="{
21
+ '--top': top ? `${top}px` : undefined,
22
+ '--right': right ? `${right}px` : undefined,
23
+ }"
24
+ >
25
+ <slot></slot>
26
+
27
+ <sup
28
+ v-if="dot"
29
+ class="badge__sup dot"
30
+ :class="[`type-${type}`, { border }]"
31
+ :style="{ backgroundColor: color }"
32
+ ></sup>
33
+
34
+ <sup
35
+ v-else-if="state"
36
+ class="badge__sup state"
37
+ :class="[state, { border }]"
38
+ :style="{ backgroundColor: color }"
39
+ ></sup>
40
+
41
+ <sup v-else class="badge__sup number" :class="{ border }" :style="{ backgroundColor: color }">{{
42
+ value
43
+ }}</sup>
44
+ </span>
45
+ </template>
46
+
47
+ <style scoped lang="scss" src="./badge.scss"></style>
@@ -0,0 +1,39 @@
1
+ @use '../../base/abstracts' as a;
2
+ @use '../../elements/text-link/text-link' as t;
3
+
4
+ .card-contact {
5
+ display: flex;
6
+ justify-content: space-between;
7
+ column-gap: var(--e-space-4);
8
+ height: 100%;
9
+ }
10
+
11
+ .card-contact__left-column {
12
+ display: flex;
13
+ flex-direction: column;
14
+ }
15
+
16
+ .card-contact__name {
17
+ @include a.type(700, strong);
18
+ }
19
+
20
+ .card-contact__role {
21
+ @include a.type(200);
22
+
23
+ margin-top: var(--e-space-1);
24
+ }
25
+
26
+ .card-contact__tel {
27
+ @include t.text-link;
28
+
29
+ margin-top: auto;
30
+ }
31
+
32
+ .card-contact__image {
33
+ margin: auto 0;
34
+ width: a.rem(112);
35
+ height: a.rem(112);
36
+ border-radius: 100%;
37
+ overflow: hidden;
38
+ flex: 0 0 auto;
39
+ }
@@ -0,0 +1,44 @@
1
+ <script setup lang="ts">
2
+ import { Image, Cta } from '../../elements/types'
3
+
4
+ type Tel = Omit<Cta, 'target'>
5
+
6
+ interface Props {
7
+ name?: string
8
+ role?: string
9
+ tel?: Tel
10
+ image?: Image
11
+ }
12
+
13
+ defineProps<Props>()
14
+ </script>
15
+
16
+ <template>
17
+ <div class="card-contact">
18
+ <div class="card-contact__left-column">
19
+ <p class="card-contact__name">
20
+ <slot name="name">{{ name }}</slot>
21
+ </p>
22
+
23
+ <p class="card-contact__role">
24
+ <slot name="role">{{ role }}</slot>
25
+ </p>
26
+
27
+ <div v-if="$slots.tel || tel" class="card-contact__tel">
28
+ <slot name="tel">
29
+ <a :href="tel.href">
30
+ {{ tel.label }}
31
+ </a>
32
+ </slot>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="card-contact__image">
37
+ <slot name="image">
38
+ <img v-bind="image" />
39
+ </slot>
40
+ </div>
41
+ </div>
42
+ </template>
43
+
44
+ <style scoped lang="scss" src="./card-contact.scss"></style>
@@ -0,0 +1,4 @@
1
+ .card-cta-bar {
2
+ display: flex;
3
+ gap: var(--e-space-2);
4
+ }
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { Cta } from '../../elements/types'
3
+ import { UButton } from '../../elements'
4
+
5
+ interface CtaItem extends Cta {
6
+ icon?: string
7
+ }
8
+
9
+ interface Props {
10
+ ctas?: CtaItem[]
11
+ }
12
+
13
+ defineProps<Props>()
14
+ </script>
15
+
16
+ <template>
17
+ <div class="card-cta-bar">
18
+ <slot>
19
+ <UButton v-for="(cta, idx) in ctas" :key="idx" v-bind="cta" variant="plain-spaceless" />
20
+ </slot>
21
+ </div>
22
+ </template>
23
+
24
+ <style scoped lang="scss" src="./card-cta-bar.scss"></style>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  interface Props {
3
- title: string
4
- subtitle: string
3
+ title?: string
4
+ subtitle?: string
5
5
  disabled?: boolean
6
6
  }
7
7
 
@@ -10,15 +10,18 @@ const { disabled = false } = defineProps<Props>()
10
10
 
11
11
  <template>
12
12
  <div class="card-cta-header" :class="{ disabled }">
13
- <slot></slot>
14
13
  <div class="card-cta-header__header">
15
- <div class="card-cta-header__image">
14
+ <div v-if="$slots.image" class="card-cta-header__image">
16
15
  <slot name="image"></slot>
17
16
  </div>
18
17
 
19
18
  <div>
20
- <h2 class="card-cta-header__title">{{ title }}</h2>
21
- <p class="card-cta-header__subtitle">{{ subtitle }}</p>
19
+ <h2 class="card-cta-header__title">
20
+ <slot name="title">{{ title }}</slot>
21
+ </h2>
22
+ <p class="card-cta-header__subtitle">
23
+ <slot name="subtitle">{{ subtitle }}</slot>
24
+ </p>
22
25
  </div>
23
26
  </div>
24
27
 
@@ -32,7 +35,7 @@ const { disabled = false } = defineProps<Props>()
32
35
  // We add the styles directly in the component
33
36
  // because the :slotted selector won't work when styles are added via `src`.
34
37
 
35
- @use '../../base/abstracts/' as a;
38
+ @use '../../base/abstracts' as a;
36
39
 
37
40
  .card-cta-header {
38
41
  display: flex;
@@ -16,7 +16,7 @@ interface Radio {
16
16
  }
17
17
 
18
18
  interface Props {
19
- cta: Radio | Link
19
+ cta?: Radio | Link
20
20
  }
21
21
 
22
22
  const { cta } = defineProps<Props>()
@@ -43,9 +43,11 @@ if (currentValue) {
43
43
 
44
44
  <template>
45
45
  <div class="card-footer">
46
- <UButton v-if="cta.href" variant="outlined" v-bind="cta" />
46
+ <slot>
47
+ <UButton v-if="cta.href" variant="outlined" v-bind="cta" />
47
48
 
48
- <USelectChip v-else provide-key="card-group" v-bind="cta" @change="onChange" />
49
+ <USelectChip v-else provide-key="card-group" v-bind="cta" @change="onChange" />
50
+ </slot>
49
51
  </div>
50
52
  </template>
51
53
 
@@ -21,7 +21,7 @@ const onResize = debounceRaf(() => {
21
21
  header.style.height = ''
22
22
  })
23
23
 
24
- if (isLarge().matches) {
24
+ if (isLarge()) {
25
25
  // Cards are stacked now. No need to set height.
26
26
  return
27
27
  }
@@ -44,13 +44,23 @@ $image-col-width-small: 100px;
44
44
  @container (max-width: 260px) {
45
45
  flex-direction: column-reverse;
46
46
  }
47
+
48
+ // Modifiers
49
+ &.loud {
50
+ .title-wrapper {
51
+ @include a.type(700, strong);
52
+ }
53
+ }
54
+ }
55
+
56
+ .caption-wrapper {
57
+ @include a.type(200);
58
+
59
+ margin-bottom: var(--e-space-1);
47
60
  }
48
61
 
49
62
  .title-wrapper {
50
- h3,
51
- h2 {
52
- @include a.type(300, strong);
53
- }
63
+ @include a.type(300, strong);
54
64
  }
55
65
 
56
66
  .text-wrapper {
@@ -96,3 +106,18 @@ $image-col-width-small: 100px;
96
106
  flex-basis: a.rem($image-col-width-small);
97
107
  }
98
108
  }
109
+
110
+ .content-col {
111
+ display: flex;
112
+ align-items: flex-start;
113
+ flex-direction: column;
114
+ }
115
+
116
+ .custom-col {
117
+ flex: 0 0 auto;
118
+ margin-left: auto;
119
+ }
120
+
121
+ .cta-wrapper {
122
+ margin-top: auto;
123
+ }
@@ -1,32 +1,47 @@
1
1
  <script setup lang="ts">
2
- import { Image } from '../../elements/types'
2
+ import { Image, Cta } from '../../elements/types'
3
3
 
4
4
  interface Props {
5
5
  title?: string
6
6
  text?: string
7
+ caption?: string
7
8
  image?: Image
8
9
  logos?: Image[]
9
10
  badge?: string
11
+ cta?: Cta
12
+ loud?: boolean
10
13
  }
11
14
 
12
15
  defineProps<Props>()
13
16
  </script>
14
17
 
15
18
  <template>
16
- <div class="card-header">
19
+ <div :class="['card-header', { loud }]">
17
20
  <div class="content-col">
21
+ <p v-if="$slots.caption || caption" class="caption-wrapper">
22
+ <slot name="caption">
23
+ {{ caption }}
24
+ </slot>
25
+ </p>
26
+
18
27
  <div class="title-wrapper">
19
28
  <slot name="title">
20
29
  <h3>{{ title }}</h3>
21
30
  </slot>
22
31
  </div>
23
32
 
24
- <div class="text-wrapper">
33
+ <div v-if="$slots.text || text" class="text-wrapper">
25
34
  <slot name="text">
26
35
  <p>{{ text }}</p>
27
36
  </slot>
28
37
  </div>
29
38
 
39
+ <div v-if="$slots.cta || cta" class="cta-wrapper">
40
+ <slot name="cta">
41
+ <a class="text-link" :href="cta.href" :target="cta.target">{{ cta.label }}</a>
42
+ </slot>
43
+ </div>
44
+
30
45
  <div v-if="logos" class="logos">
31
46
  <slot name="logos">
32
47
  <img v-for="(img, idx) in logos" :key="idx" :src="img.src" :alt="img.alt" />
@@ -40,6 +55,10 @@ defineProps<Props>()
40
55
  </div>
41
56
  </div>
42
57
 
58
+ <div v-if="$slots.custom" class="custom-col">
59
+ <slot name="custom"></slot>
60
+ </div>
61
+
43
62
  <div v-if="badge" class="badge">
44
63
  <slot name="badge">{{ badge }}</slot>
45
64
  </div>
@@ -0,0 +1,87 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ .card-highlight-container {
4
+ container: card-highlight / inline-size;
5
+ height: 100%;
6
+
7
+ @container card-highlight (width >= 900px) {
8
+ .card-highlight__image-col {
9
+ padding-right: var(--e-space-20);
10
+ }
11
+ }
12
+ }
13
+
14
+ .card-highlight {
15
+ position: relative;
16
+ display: flex;
17
+ border: 1px solid var(--e-c-primary-01-100);
18
+ border-radius: var(--e-brd-radius-2);
19
+ background-color: var(--e-c-primary-01-50);
20
+ padding: var(--e-space-6);
21
+ gap: var(--e-space-4);
22
+ height: 100%;
23
+ justify-content: space-between;
24
+
25
+ @include a.bp(m) {
26
+ padding: var(--e-space-5);
27
+ }
28
+
29
+ @include a.bp(s) {
30
+ padding: var(--e-space-4);
31
+ }
32
+
33
+ @include a.bp(m) {
34
+ flex-direction: column;
35
+ align-items: flex-start;
36
+ }
37
+ }
38
+
39
+ .card-highlight__content-col {
40
+ display: flex;
41
+ flex-direction: column;
42
+ align-items: flex-start;
43
+ row-gap: var(--e-space-4);
44
+
45
+ @include a.bp(m) {
46
+ width: calc(100% - 40px);
47
+ }
48
+ }
49
+
50
+ .card-highlight__title {
51
+ @include a.type(300, strong);
52
+
53
+ color: var(--e-c-secondary-01-950);
54
+ }
55
+
56
+ .card-highlight__text {
57
+ @include a.type(200);
58
+
59
+ margin-top: auto;
60
+ color: var(--e-c-secondary-01-900);
61
+ }
62
+
63
+ .card-highlight__image-col {
64
+ flex: 1 1 auto;
65
+ max-width: 60%;
66
+ align-self: center;
67
+ display: flex;
68
+ justify-content: flex-end;
69
+
70
+ img {
71
+ max-height: a.rem(225);
72
+ }
73
+
74
+ @include a.bp(m) {
75
+ max-width: none;
76
+ }
77
+ }
78
+
79
+ .card-highlight__badge-icon {
80
+ position: absolute;
81
+ padding: 5px;
82
+ top: var(--e-space-4);
83
+ right: var(--e-space-4);
84
+ background-color: var(--e-c-mono-00);
85
+ color: var(--e-c-secondary-01-950);
86
+ border-radius: 100%;
87
+ }
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import { Image } from '../../elements/types'
3
+ import { UIcon } from '../../elements'
4
+
5
+ interface Props {
6
+ title?: string
7
+ text?: string
8
+ image?: Image
9
+ badgeIcon?: string
10
+ }
11
+
12
+ defineProps<Props>()
13
+ </script>
14
+
15
+ <template>
16
+ <div class="card-highlight-container">
17
+ <div class="card-highlight">
18
+ <div class="card-highlight__content-col">
19
+ <h3 v-if="$slots.title || title" class="card-highlight__title">
20
+ <slot name="title">{{ title }}</slot>
21
+ </h3>
22
+
23
+ <div v-if="$slots.text || text" class="card-highlight__text">
24
+ <slot name="text">
25
+ <div v-html="text"></div>
26
+ </slot>
27
+ </div>
28
+ </div>
29
+
30
+ <div v-if="$slots.image || image" class="card-highlight__image-col">
31
+ <div>
32
+ <slot name="image">
33
+ <img v-bind="image" />
34
+ </slot>
35
+ </div>
36
+ </div>
37
+
38
+ <div v-if="badgeIcon" class="card-highlight__badge-icon">
39
+ <UIcon :name="badgeIcon" />
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <style scoped lang="scss" src="./card-highlight.scss"></style>
46
+ <style scoped lang="scss">
47
+ @use '../../base/abstracts' as a;
48
+
49
+ .card-highlight__image-col {
50
+ :slotted(img) {
51
+ max-height: a.rem(225);
52
+ }
53
+ }
54
+ </style>
@@ -0,0 +1,39 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ .card-price-list {
4
+ display: grid;
5
+ row-gap: var(--e-space-1);
6
+ }
7
+
8
+ .card-price-list__row {
9
+ display: flex;
10
+ column-gap: var(--e-space-1);
11
+ justify-content: space-between;
12
+ }
13
+
14
+ .card-price-list__name {
15
+ @include a.type(200);
16
+ }
17
+
18
+ .card-price-list__right-col {
19
+ white-space: nowrap;
20
+ }
21
+
22
+ .card-price-list__value {
23
+ @include a.type(300, strong);
24
+
25
+ margin-right: var(--e-space-1);
26
+ }
27
+
28
+ .card-price-list__unit {
29
+ @include a.type(50, strong);
30
+
31
+ color: var(--e-c-mono-700);
32
+ }
33
+
34
+ .card-price-list__info {
35
+ display: inline-block;
36
+ margin-left: var(--e-space-2_5);
37
+ vertical-align: middle;
38
+ color: var(--e-c-secondary-05-500);
39
+ }
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ import { UIcon } from '../../elements'
3
+ import { UTooltip } from '../'
4
+
5
+ interface PriceItem {
6
+ name: string
7
+ value: string
8
+ unit: string
9
+ info?: string
10
+ }
11
+
12
+ interface Props {
13
+ items?: PriceItem[]
14
+ }
15
+
16
+ defineProps<Props>()
17
+ </script>
18
+
19
+ <template>
20
+ <dl class="card-price-list">
21
+ <div v-for="(item, idx) in items" :key="idx" class="card-price-list__row">
22
+ <dt class="card-price-list__name">{{ item.name }}</dt>
23
+ <dd class="card-price-list__right-col">
24
+ <span class="card-price-list__value">{{ item.value }}</span>
25
+ <span class="card-price-list__unit">{{ item.unit }}</span>
26
+
27
+ <span class="card-price-list__info">
28
+ <UTooltip v-if="item.info" :title="item.info">
29
+ <UIcon name="info-circle"></UIcon>
30
+ </UTooltip>
31
+ </span>
32
+ </dd>
33
+ </div>
34
+ </dl>
35
+ </template>
36
+
37
+ <style scoped lang="scss" src="./card-price-list.scss"></style>
@@ -1,4 +1,4 @@
1
- @use '../../base/abstracts/' as a;
1
+ @use '../../base/abstracts' as a;
2
2
 
3
3
  .card-section {
4
4
  padding: var(--e-space-6);
@@ -10,4 +10,24 @@
10
10
  @include a.bp(s) {
11
11
  padding: var(--e-space-4);
12
12
  }
13
+
14
+ // Modifiers
15
+ &.full-height {
16
+ height: 100%;
17
+ }
18
+
19
+ // Handle special case
20
+ &:has(.card-cta-bar) {
21
+ margin-top: auto; // We assume it is the bottom section, like in a card-tile configuration.
22
+ flex: 0; // Force this section to keep minimal height.
23
+ padding: var(--e-space-4) var(--e-space-6);
24
+
25
+ @include a.bp(m) {
26
+ padding: var(--e-space-4) var(--e-space-5);
27
+ }
28
+
29
+ @include a.bp(s) {
30
+ padding: var(--e-space-4);
31
+ }
32
+ }
13
33
  }
@@ -1,5 +1,13 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ fullHeight?: boolean
4
+ }
5
+
6
+ defineProps<Props>()
7
+ </script>
8
+
1
9
  <template>
2
- <div class="card-section">
10
+ <div :class="['card-section', { 'full-height': fullHeight }]">
3
11
  <slot></slot>
4
12
  </div>
5
13
  </template>