@xen-orchestra/web-core 0.4.0 → 0.5.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 (124) hide show
  1. package/lib/assets/css/_colors.pcss +56 -24
  2. package/lib/assets/css/_context.pcss +9 -9
  3. package/lib/assets/css/base.pcss +6 -6
  4. package/lib/components/backup-item/VtsBackupItem.vue +47 -0
  5. package/lib/components/backup-state/{BackupState.vue → VtsBackupState.vue} +4 -4
  6. package/lib/components/{button/ButtonGroup.vue → button-group/VtsButtonGroup.vue} +7 -6
  7. package/lib/components/cell-object/{CellObject.vue → VtsCellObject.vue} +14 -14
  8. package/lib/components/cell-text/{CellText.vue → VtsCellText.vue} +11 -11
  9. package/lib/components/console/{RemoteConsole.vue → VtsRemoteConsole.vue} +12 -18
  10. package/lib/components/donut-chart-with-legend/{DonutChartWithLegend.vue → VtsDonutChartWithLegend.vue} +6 -6
  11. package/lib/components/dropdown/DropdownItem.vue +8 -14
  12. package/lib/components/dropdown/DropdownTitle.vue +3 -3
  13. package/lib/components/icon/VtsIcon.vue +38 -42
  14. package/lib/components/layout/{LayoutSidebar.vue → VtsLayoutSidebar.vue} +31 -30
  15. package/lib/components/legend-group/VtsLegendGroup.vue +44 -0
  16. package/lib/components/{legend/LegendList.vue → legend-list/VtsLegendList.vue} +2 -2
  17. package/lib/components/menu/MenuTrigger.vue +2 -2
  18. package/lib/components/stacked-bar-with-legend/{StackedBarWithLegend.vue → VtsStackedBarWithLegend.vue} +14 -14
  19. package/lib/components/state-hero/VtsComingSoonHero.vue +13 -0
  20. package/lib/components/state-hero/VtsLoadingHero.vue +15 -0
  21. package/lib/components/state-hero/VtsNoDataHero.vue +11 -0
  22. package/lib/components/state-hero/VtsObjectNotFoundHero.vue +13 -0
  23. package/lib/components/state-hero/{StateHero.vue → VtsStateHero.vue} +42 -35
  24. package/lib/components/tab/TabItem.vue +6 -6
  25. package/lib/components/table/ColumnTitle.vue +7 -7
  26. package/lib/components/table/{UiTable.vue → VtsTable.vue} +7 -3
  27. package/lib/components/task/{QuickTaskButton.vue → VtsQuickTaskButton.vue} +8 -7
  28. package/lib/components/task/{QuickTaskList.vue → VtsQuickTaskList.vue} +10 -11
  29. package/lib/components/task/{QuickTaskTabBar.vue → VtsQuickTaskTabBar.vue} +9 -13
  30. package/lib/components/{tooltip/TooltipList.vue → tooltip-list/VtsTooltipList.vue} +2 -3
  31. package/lib/components/tree/{TreeItem.vue → VtsTreeItem.vue} +3 -4
  32. package/lib/components/tree/VtsTreeItemError.vue +18 -0
  33. package/lib/components/tree/{TreeLine.vue → VtsTreeLine.vue} +9 -11
  34. package/lib/components/tree/{TreeList.vue → VtsTreeList.vue} +5 -2
  35. package/lib/components/tree/VtsTreeLoadingItem.vue +61 -0
  36. package/lib/components/ui/account-menu-button/UiAccountMenuButton.vue +64 -0
  37. package/lib/components/ui/actions-title/UiActionsTitle.vue +2 -2
  38. package/lib/components/ui/button/UiButton.vue +532 -0
  39. package/lib/components/ui/button-icon/UiButtonIcon.vue +248 -0
  40. package/lib/components/{UiCard.vue → ui/card/UiCard.vue} +8 -6
  41. package/lib/components/ui/card-numbers/UiCardNumbers.vue +103 -0
  42. package/lib/components/ui/card-subtitle/UiCardSubtitle.vue +24 -0
  43. package/lib/components/ui/card-title/UiCardTitle.vue +56 -0
  44. package/lib/components/ui/checkbox/UiCheckbox.vue +410 -0
  45. package/lib/components/ui/checkbox-group/UiCheckboxGroup.vue +57 -0
  46. package/lib/components/ui/chip/ChipIcon.vue +21 -0
  47. package/lib/components/ui/chip/ChipRemoveIcon.vue +13 -0
  48. package/lib/components/ui/chip/UiChip.vue +135 -0
  49. package/lib/components/{icon/ComplexIcon.vue → ui/complex-icon/UiComplexIcon.vue} +21 -27
  50. package/lib/components/ui/counter/UiCounter.vue +134 -0
  51. package/lib/components/{donut-chart/DonutChart.vue → ui/donut-chart/UiDonutChart.vue} +28 -30
  52. package/lib/components/{head-bar/HeadBar.vue → ui/head-bar/UiHeadBar.vue} +31 -31
  53. package/lib/components/{info/VtsInfo.vue → ui/info/UiInfo.vue} +13 -11
  54. package/lib/components/{input → ui/input}/UiInput.vue +9 -7
  55. package/lib/components/ui/input/UiTextarea.vue +120 -0
  56. package/lib/components/{input/VtsLabel.vue → ui/label/UiLabel.vue} +25 -25
  57. package/lib/components/ui/legend/UiLegend.vue +98 -0
  58. package/lib/components/{LegendTitle.vue → ui/legend-title/UiLegendTitle.vue} +4 -4
  59. package/lib/components/{UiSpinner.vue → ui/loader/UiLoader.vue} +3 -3
  60. package/lib/components/{icon/ObjectIcon.vue → ui/object-icon/UiObjectIcon.vue} +44 -36
  61. package/lib/components/ui/object-link/UiObjectLink.vue +83 -0
  62. package/lib/components/ui/panel/UiPanel.vue +57 -0
  63. package/lib/components/{query-search-bar/QuerySearchBar.vue → ui/query-search-bar/UiQuerySearchBar.vue} +16 -16
  64. package/lib/components/{task/QuickTaskItem.vue → ui/quick-task-item/UiQuickTaskItem.vue} +46 -34
  65. package/lib/components/{task/QuickTaskPanel.vue → ui/quick-task-panel/UiQuickTaskPanel.vue} +8 -7
  66. package/lib/components/ui/radio-button/UiRadioButton.vue +196 -0
  67. package/lib/components/ui/radio-button-group/UiRadioButtonGroup.vue +56 -0
  68. package/lib/components/{stacked-bar → ui/stacked-bar}/StackedBarSegment.vue +23 -26
  69. package/lib/components/{stacked-bar/StackedBar.vue → ui/stacked-bar/UiStackedBar.vue} +6 -6
  70. package/lib/components/ui/table-actions/UiTableActions.vue +46 -0
  71. package/lib/components/ui/tag/UiTag.vue +118 -0
  72. package/lib/components/ui/title/UiTitle.vue +2 -2
  73. package/lib/components/ui/toaster/UiToaster.vue +100 -0
  74. package/lib/components/ui/toggle/UiToggle.vue +117 -0
  75. package/lib/components/{tooltip/TooltipItem.vue → ui/tooltip/UiTooltip.vue} +15 -15
  76. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +64 -0
  77. package/lib/components/{tree/TreeItemLabel.vue → ui/tree-item-label/UiTreeItemLabel.vue} +60 -59
  78. package/lib/components/ui/user-link/UiUserLink.vue +76 -0
  79. package/lib/components/ui/user-logo/UiUserLogo.vue +50 -0
  80. package/lib/composables/route-query.composable.md +136 -0
  81. package/lib/composables/table.composable.md +159 -0
  82. package/lib/composables/tree/define-tree.ts +1 -1
  83. package/lib/composables/tree/tree-node-base.ts +6 -6
  84. package/lib/composables/tree.composable.md +536 -0
  85. package/lib/layouts/CoreLayout.vue +8 -6
  86. package/lib/locales/de.json +2 -2
  87. package/lib/locales/en.json +6 -3
  88. package/lib/locales/fa.json +2 -2
  89. package/lib/locales/fr.json +6 -3
  90. package/lib/types/color.type.ts +0 -2
  91. package/lib/types/subscribable-store.type.ts +2 -2
  92. package/lib/utils/create-subscribable-store-context.util.ts +1 -1
  93. package/lib/utils/if-else.utils.md +23 -0
  94. package/lib/utils/if-else.utils.ts +2 -2
  95. package/lib/utils/to-variants.util.md +62 -0
  96. package/package.json +7 -7
  97. package/lib/components/CardNumbers.vue +0 -101
  98. package/lib/components/PowerStateIcon.vue +0 -46
  99. package/lib/components/UiTag.vue +0 -101
  100. package/lib/components/backup-item/BackupItem.vue +0 -40
  101. package/lib/components/button/ButtonIcon.vue +0 -220
  102. package/lib/components/button/UiButton.vue +0 -470
  103. package/lib/components/card/CardSubtitle.vue +0 -24
  104. package/lib/components/card/CardTitle.vue +0 -57
  105. package/lib/components/chip/ChipIcon.vue +0 -30
  106. package/lib/components/chip/ChipRemoveIcon.vue +0 -13
  107. package/lib/components/chip/UiChip.vue +0 -137
  108. package/lib/components/counter/VtsCounter.vue +0 -147
  109. package/lib/components/legend/LegendGroup.vue +0 -44
  110. package/lib/components/legend/LegendItem.vue +0 -86
  111. package/lib/components/object-link/ObjectLink.vue +0 -87
  112. package/lib/components/state-hero/ComingSoonHero.vue +0 -13
  113. package/lib/components/state-hero/LoadingHero.vue +0 -15
  114. package/lib/components/state-hero/NoDataHero.vue +0 -11
  115. package/lib/components/state-hero/ObjectNotFoundHero.vue +0 -13
  116. package/lib/components/tree/TreeItemError.vue +0 -13
  117. package/lib/components/tree/TreeLoadingItem.vue +0 -60
  118. package/lib/components/user/UserLink.vue +0 -72
  119. package/lib/components/user/UserLogo.vue +0 -57
  120. package/lib/types/backup.type.ts +0 -11
  121. package/lib/types/size.type.ts +0 -1
  122. package/lib/types/task.type.ts +0 -13
  123. /package/lib/components/backdrop/{Backdrop.vue → VtsBackdrop.vue} +0 -0
  124. /package/lib/components/divider/{Divider.vue → VtsDivider.vue} +0 -0
@@ -0,0 +1,196 @@
1
+ <!-- v4 -->
2
+ <template>
3
+ <label :class="variant" class="ui-radio-button typo p1-regular">
4
+ <span class="radio-container">
5
+ <input v-model="model" :value :disabled="isDisabled" class="input" type="radio" />
6
+ <VtsIcon :icon="faCircle" accent="current" class="radio-icon" />
7
+ </span>
8
+ <slot />
9
+ </label>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import VtsIcon from '@core/components/icon/VtsIcon.vue'
14
+ import { useContext } from '@core/composables/context.composable'
15
+ import { DisabledContext } from '@core/context'
16
+ import { toVariants } from '@core/utils/to-variants.util'
17
+ import { faCircle } from '@fortawesome/free-solid-svg-icons'
18
+ import { computed } from 'vue'
19
+
20
+ const props = withDefaults(
21
+ defineProps<{
22
+ accent: 'info' | 'success' | 'warning' | 'danger'
23
+ value: any
24
+ disabled?: boolean
25
+ }>(),
26
+ {
27
+ disabled: undefined,
28
+ }
29
+ )
30
+ const model = defineModel<boolean>()
31
+
32
+ defineSlots<{
33
+ default(): any
34
+ }>()
35
+
36
+ const variant = computed(() => toVariants({ accent: props.accent }))
37
+
38
+ const isDisabled = useContext(DisabledContext, () => props.disabled)
39
+ </script>
40
+
41
+ <style lang="postcss" scoped>
42
+ .ui-radio-button {
43
+ display: inline-flex;
44
+ align-items: center;
45
+ gap: 0.8rem;
46
+
47
+ .radio-container {
48
+ display: inline-flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ border: 0.2rem solid var(--accent-color);
52
+ background-color: transparent;
53
+ border-radius: 0.8rem;
54
+ width: 1.6rem;
55
+ height: 1.6rem;
56
+ position: relative;
57
+ transition:
58
+ border-color 0.125s ease-in-out,
59
+ background-color 0.125s ease-in-out;
60
+
61
+ &:has(input:focus-visible) {
62
+ outline: none;
63
+ &::after {
64
+ position: absolute;
65
+ content: '';
66
+ inset: -0.5rem;
67
+ border: 0.2rem solid var(--color-info-txt-base);
68
+ border-radius: 0.4rem;
69
+ }
70
+ }
71
+ &:has(.input:disabled) {
72
+ cursor: not-allowed;
73
+
74
+ /*
75
+ TODO: To be removed or kept after a decision has been taken
76
+ See https://www.figma.com/design/l2O2VvzJRnOCvqxhM7d124?node-id=8-1940#1021964394
77
+ */
78
+
79
+ &:not(:has(.input:checked)) {
80
+ --accent-color: var(--color-neutral-txt-secondary);
81
+ }
82
+ }
83
+
84
+ &:has(.input:checked) {
85
+ background-color: var(--accent-color);
86
+ }
87
+
88
+ /* INPUT */
89
+
90
+ .input {
91
+ opacity: 0;
92
+ position: absolute;
93
+ pointer-events: none;
94
+ }
95
+
96
+ /* ICON */
97
+
98
+ .radio-icon {
99
+ font-size: 0.8rem;
100
+ position: absolute;
101
+ opacity: 0;
102
+ transition: opacity 0.125s ease-in-out;
103
+ }
104
+
105
+ .input:disabled + .radio-icon {
106
+ color: var(--color-neutral-txt-secondary);
107
+ }
108
+
109
+ .input:checked + .radio-icon {
110
+ opacity: 1;
111
+ }
112
+ }
113
+
114
+ /* ACCENT */
115
+
116
+ &.accent--info {
117
+ --accent-color: var(--color-info-item-base);
118
+
119
+ &:hover {
120
+ --accent-color: var(--color-info-item-hover);
121
+ }
122
+
123
+ &:active {
124
+ --accent-color: var(--color-info-item-active);
125
+ }
126
+
127
+ &:has(.input:disabled) {
128
+ --accent-color: var(--color-info-item-disabled);
129
+ }
130
+
131
+ .radio-icon {
132
+ color: var(--color-info-txt-item);
133
+ }
134
+ }
135
+
136
+ &.accent--success {
137
+ --accent-color: var(--color-success-item-base);
138
+
139
+ &:hover {
140
+ --accent-color: var(--color-success-item-hover);
141
+ }
142
+
143
+ &:active {
144
+ --accent-color: var(--color-success-item-active);
145
+ }
146
+
147
+ &:has(.input:disabled) {
148
+ --accent-color: var(--color-success-item-disabled);
149
+ }
150
+
151
+ .radio-icon {
152
+ color: var(--color-success-txt-item);
153
+ }
154
+ }
155
+
156
+ &.accent--warning {
157
+ --accent-color: var(--color-warning-item-base);
158
+
159
+ &:hover {
160
+ --accent-color: var(--color-warning-item-hover);
161
+ }
162
+
163
+ &:active {
164
+ --accent-color: var(--color-warning-item-active);
165
+ }
166
+
167
+ &:has(.input:disabled) {
168
+ --accent-color: var(--color-warning-item-disabled);
169
+ }
170
+
171
+ .radio-icon {
172
+ color: var(--color-warning-txt-item);
173
+ }
174
+ }
175
+
176
+ &.accent--danger {
177
+ --accent-color: var(--color-danger-item-base);
178
+
179
+ &:hover {
180
+ --accent-color: var(--color-danger-item-hover);
181
+ }
182
+
183
+ &:active {
184
+ --accent-color: var(--color-danger-item-active);
185
+ }
186
+
187
+ &:has(.input:disabled) {
188
+ --accent-color: var(--color-danger-item-disabled);
189
+ }
190
+
191
+ .radio-icon {
192
+ color: var(--color-danger-txt-item);
193
+ }
194
+ }
195
+ }
196
+ </style>
@@ -0,0 +1,56 @@
1
+ <!-- v1 -->
2
+ <template>
3
+ <div class="ui-radio-button-group">
4
+ <slot v-if="slots.label || label !== undefined" name="label">
5
+ <UiLabel :accent="labelAccent">
6
+ {{ label }}
7
+ </UiLabel>
8
+ </slot>
9
+ <div class="group" :class="{ vertical }">
10
+ <slot />
11
+ </div>
12
+ <slot v-if="slots.info || info !== undefined" name="info">
13
+ <UiInfo :accent>
14
+ {{ info }}
15
+ </UiInfo>
16
+ </slot>
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import UiInfo from '@core/components/ui/info/UiInfo.vue'
22
+ import UiLabel from '@core/components/ui/label/UiLabel.vue'
23
+ import { computed } from 'vue'
24
+
25
+ const props = defineProps<{
26
+ accent: 'info' | 'warning' | 'danger'
27
+ label?: string
28
+ info?: string
29
+ vertical?: boolean
30
+ }>()
31
+
32
+ const slots = defineSlots<{
33
+ default(): any
34
+ label?(): any
35
+ info?(): any
36
+ }>()
37
+ const labelAccent = computed(() => (props.accent === 'info' ? 'neutral' : props.accent))
38
+ </script>
39
+
40
+ <style scoped lang="postcss">
41
+ .ui-radio-button-group {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: 0.4rem;
45
+
46
+ .group {
47
+ display: flex;
48
+ gap: 6.4rem;
49
+
50
+ &.vertical {
51
+ flex-direction: column;
52
+ gap: 0.8rem;
53
+ }
54
+ }
55
+ }
56
+ </style>
@@ -2,7 +2,7 @@
2
2
  <div
3
3
  v-if="percentage > 0"
4
4
  v-tooltip="{ selector: '.text-ellipsis' }"
5
- :class="color"
5
+ :class="`accent--${accent}`"
6
6
  :style="{ width: percentage + '%' }"
7
7
  class="stacked-bar-segment typo c4-semi-bold"
8
8
  >
@@ -18,10 +18,10 @@ import { hasEllipsis } from '@core/utils/has-ellipsis.util'
18
18
  import { useResizeObserver } from '@vueuse/core'
19
19
  import { ref } from 'vue'
20
20
 
21
- export type StackedBarSegmentColor = 'primary' | 'success' | 'warning' | 'danger'
21
+ export type StackedBarSegmentAccent = 'info' | 'success' | 'warning' | 'danger'
22
22
 
23
23
  export type StackedBarSegmentProps = {
24
- color: StackedBarSegmentColor
24
+ accent: StackedBarSegmentAccent
25
25
  percentage: number
26
26
  }
27
27
 
@@ -36,37 +36,34 @@ useResizeObserver(ellipsisElement, ([entry]) => {
36
36
  </script>
37
37
 
38
38
  <style lang="postcss" scoped>
39
- /* COLOR VARIANT */
40
39
  .stacked-bar-segment {
41
- &.primary {
42
- --background-color: var(--color-normal-item-base);
43
- }
40
+ display: flex;
41
+ justify-content: center;
42
+ align-items: center;
43
+ white-space: nowrap;
44
+ color: var(--color-info-txt-item);
45
+ padding-inline: 0.8rem;
44
46
 
45
- &.success {
46
- --background-color: var(--color-success-item-base);
47
+ .hidden {
48
+ visibility: hidden;
47
49
  }
48
50
 
49
- &.warning {
50
- --background-color: var(--color-warning-item-base);
51
+ /* ACCENT VARIANTS */
52
+
53
+ &.accent--info {
54
+ background-color: var(--color-info-item-base);
51
55
  }
52
56
 
53
- &.danger {
54
- --background-color: var(--color-danger-item-base);
57
+ &.accent--success {
58
+ background-color: var(--color-success-item-base);
55
59
  }
56
- }
57
60
 
58
- /* IMPLEMENTATION */
59
- .stacked-bar-segment {
60
- display: flex;
61
- justify-content: center;
62
- align-items: center;
63
- white-space: nowrap;
64
- color: var(--color-normal-txt-item);
65
- background-color: var(--background-color);
66
- padding-inline: 0.8rem;
67
- }
61
+ &.accent--warning {
62
+ background-color: var(--color-warning-item-base);
63
+ }
68
64
 
69
- .hidden {
70
- visibility: hidden;
65
+ &.accent--danger {
66
+ background-color: var(--color-danger-item-base);
67
+ }
71
68
  }
72
69
  </style>
@@ -1,22 +1,22 @@
1
- <!-- v1.0 -->
1
+ <!-- v2 -->
2
2
  <template>
3
- <div class="stacked-bar">
3
+ <div class="ui-stacked-bar">
4
4
  <StackedBarSegment
5
5
  v-for="(segment, index) in segments"
6
6
  :key="index"
7
- :color="segment.color"
7
+ :accent="segment.accent"
8
8
  :percentage="max === 0 ? 0 : (segment.value / max) * 100"
9
9
  />
10
10
  </div>
11
11
  </template>
12
12
 
13
13
  <script lang="ts" setup>
14
- import StackedBarSegment, { type StackedBarSegmentProps } from '@core/components/stacked-bar/StackedBarSegment.vue'
14
+ import StackedBarSegment, { type StackedBarSegmentProps } from '@core/components/ui/stacked-bar/StackedBarSegment.vue'
15
15
  import { computed } from 'vue'
16
16
 
17
17
  type Segment = {
18
18
  value: number
19
- color: StackedBarSegmentProps['color']
19
+ accent: StackedBarSegmentProps['accent']
20
20
  }
21
21
 
22
22
  export type StackedBarProps = {
@@ -32,7 +32,7 @@ const max = computed(() => Math.max(props.maxValue ?? 0, totalValue.value))
32
32
  </script>
33
33
 
34
34
  <style lang="postcss" scoped>
35
- .stacked-bar {
35
+ .ui-stacked-bar {
36
36
  width: 100%;
37
37
  display: flex;
38
38
  height: 4rem;
@@ -0,0 +1,46 @@
1
+ <!-- v2 -->
2
+ <template>
3
+ <div class="ui-table-actions">
4
+ <div class="actions">
5
+ <slot name="title">
6
+ <UiActionsTitle>
7
+ {{ title }}
8
+ </UiActionsTitle>
9
+ </slot>
10
+ <slot />
11
+ </div>
12
+ <div v-if="slots.groupedBy">
13
+ <slot name="groupedBy" />
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import UiActionsTitle from '@core/components/ui/actions-title/UiActionsTitle.vue'
20
+
21
+ defineProps<{
22
+ title?: string
23
+ }>()
24
+
25
+ const slots = defineSlots<{
26
+ default(): any
27
+ title(): any
28
+ groupedBy?(): any
29
+ }>()
30
+ </script>
31
+
32
+ <style scoped lang="postcss">
33
+ .ui-table-actions {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: space-between;
37
+ padding-block: 0.4rem;
38
+ border-bottom: 0.1rem solid var(--color-neutral-border);
39
+
40
+ .actions {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 2.4rem;
44
+ }
45
+ }
46
+ </style>
@@ -0,0 +1,118 @@
1
+ <!-- v3 -->
2
+ <!-- TODO: implement tertiary variant to bump to v4 -->
3
+ <template>
4
+ <span :class="toVariants({ accent, variant })" class="ui-tag typo p3-regular">
5
+ <slot name="icon">
6
+ <VtsIcon :icon accent="current" fixed-width />
7
+ </slot>
8
+ <span class="text-ellipsis"><slot /></span>
9
+ </span>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import VtsIcon from '@core/components/icon/VtsIcon.vue'
14
+ import { toVariants } from '@core/utils/to-variants.util'
15
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
16
+
17
+ type TagAccent = 'info' | 'neutral' | 'success' | 'warning' | 'danger' | 'muted'
18
+ type TagVariant = 'primary' | 'secondary'
19
+
20
+ defineProps<{
21
+ accent: TagAccent
22
+ variant: TagVariant
23
+ icon?: IconDefinition
24
+ }>()
25
+
26
+ defineSlots<{
27
+ default(): any
28
+ icon?(): any
29
+ }>()
30
+ </script>
31
+
32
+ <style lang="postcss" scoped>
33
+ .ui-tag {
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ gap: 0.8rem;
38
+ white-space: nowrap;
39
+ padding: 0.2rem 0.8rem;
40
+ border-radius: 0.4rem;
41
+ vertical-align: middle;
42
+ min-width: 0;
43
+
44
+ /* COLOR VARIANTS */
45
+
46
+ &.accent--info {
47
+ &.variant--primary {
48
+ background-color: var(--color-info-item-base);
49
+ color: var(--color-info-txt-item);
50
+ }
51
+
52
+ &.variant--secondary {
53
+ background-color: var(--color-info-background-selected);
54
+ color: var(--color-info-txt-base);
55
+ }
56
+ }
57
+
58
+ &.accent--neutral {
59
+ &.variant--primary {
60
+ background-color: var(--color-neutral-txt-primary);
61
+ color: var(--color-neutral-background-primary);
62
+ }
63
+
64
+ &.variant--secondary {
65
+ background-color: var(--color-neutral-background-secondary);
66
+ color: var(--color-neutral-txt-primary);
67
+ }
68
+ }
69
+
70
+ &.accent--success {
71
+ &.variant--primary {
72
+ background-color: var(--color-success-item-base);
73
+ color: var(--color-success-txt-item);
74
+ }
75
+
76
+ &.variant--secondary {
77
+ background-color: var(--color-success-background-selected);
78
+ color: var(--color-success-txt-base);
79
+ }
80
+ }
81
+
82
+ &.accent--warning {
83
+ &.variant--primary {
84
+ background-color: var(--color-warning-item-base);
85
+ color: var(--color-warning-txt-item);
86
+ }
87
+
88
+ &.variant--secondary {
89
+ background-color: var(--color-warning-background-selected);
90
+ color: var(--color-warning-txt-base);
91
+ }
92
+ }
93
+
94
+ &.accent--danger {
95
+ &.variant--primary {
96
+ background-color: var(--color-danger-item-base);
97
+ color: var(--color-danger-txt-item);
98
+ }
99
+
100
+ &.variant--secondary {
101
+ background-color: var(--color-danger-background-selected);
102
+ color: var(--color-danger-txt-base);
103
+ }
104
+ }
105
+
106
+ &.accent--muted {
107
+ &.variant--primary {
108
+ background-color: var(--color-neutral-background-disabled);
109
+ color: var(--color-neutral-txt-secondary);
110
+ }
111
+
112
+ &.variant--secondary {
113
+ background-color: var(--color-neutral-background-secondary);
114
+ color: var(--color-neutral-txt-secondary);
115
+ }
116
+ }
117
+ }
118
+ </style>
@@ -23,10 +23,10 @@ const slots = defineSlots<{
23
23
  align-items: center;
24
24
  gap: 2.4rem;
25
25
  padding-block-end: 0.4rem;
26
- border-bottom: 0.1rem solid var(--color-normal-txt-base);
26
+ border-bottom: 0.1rem solid var(--color-info-txt-base);
27
27
 
28
28
  .label {
29
- color: var(--color-normal-txt-base);
29
+ color: var(--color-info-txt-base);
30
30
  }
31
31
 
32
32
  .actions {
@@ -0,0 +1,100 @@
1
+ <!-- v3 -->
2
+ <template>
3
+ <div :class="toVariants({ accent })" class="ui-toaster">
4
+ <div class="content">
5
+ <VtsIcon class="information-icon" :accent :icon="faCircle" :overlay-icon="icon" />
6
+ <div>
7
+ <div class="typo h5-semi-bold">
8
+ <slot />
9
+ </div>
10
+ <div v-if="slots.description" class="typo p2-regular">
11
+ <slot name="description" />
12
+ </div>
13
+ </div>
14
+ <UiButtonIcon class="close-icon" :icon="faXmark" :accent size="medium" />
15
+ </div>
16
+ <div v-if="slots.actions" class="actions">
17
+ <slot name="actions" />
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import VtsIcon from '@core/components/icon/VtsIcon.vue'
24
+ import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
25
+ import { toVariants } from '@core/utils/to-variants.util'
26
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
27
+ import { faXmark, faCheck, faCircle, faInfo, faExclamation } from '@fortawesome/free-solid-svg-icons'
28
+ import { computed } from 'vue'
29
+
30
+ type ToasterAccent = 'info' | 'success' | 'warning' | 'danger'
31
+
32
+ const props = defineProps<{
33
+ accent: ToasterAccent
34
+ }>()
35
+
36
+ const slots = defineSlots<{
37
+ default(): any
38
+ description?(): any
39
+ actions?(): any
40
+ }>()
41
+
42
+ const states: Record<ToasterAccent, IconDefinition> = {
43
+ info: faInfo,
44
+ success: faCheck,
45
+ warning: faExclamation,
46
+ danger: faXmark,
47
+ }
48
+ const icon = computed(() => states[props.accent])
49
+ </script>
50
+
51
+ <style scoped lang="postcss">
52
+ .ui-toaster {
53
+ display: flex;
54
+ flex-direction: column;
55
+ justify-content: space-between;
56
+ padding: 1.6rem;
57
+ border: 0.1rem solid;
58
+ border-radius: 0.4rem;
59
+ gap: 0.8rem;
60
+
61
+ .content {
62
+ display: flex;
63
+ align-items: flex-start;
64
+ gap: 1.6rem;
65
+
66
+ .information-icon {
67
+ font-size: 2.7rem;
68
+ }
69
+
70
+ .close-icon {
71
+ margin-inline-start: auto;
72
+ flex-shrink: 0;
73
+ }
74
+ }
75
+
76
+ .actions {
77
+ align-self: flex-end;
78
+ }
79
+
80
+ &.accent--info {
81
+ background-color: var(--color-info-background-selected);
82
+ border-color: var(--color-info-item-base);
83
+ }
84
+
85
+ &.accent--success {
86
+ background-color: var(--color-success-background-selected);
87
+ border-color: var(--color-success-item-base);
88
+ }
89
+
90
+ &.accent--warning {
91
+ background-color: var(--color-warning-background-selected);
92
+ border-color: var(--color-warning-item-base);
93
+ }
94
+
95
+ &.accent--danger {
96
+ background-color: var(--color-danger-background-selected);
97
+ border-color: var(--color-danger-item-base);
98
+ }
99
+ }
100
+ </style>