@xen-orchestra/web-core 0.15.0 → 0.17.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 (29) hide show
  1. package/lib/components/connection-status/VtsConnectionStatus.vue +3 -0
  2. package/lib/components/console/VtsClipboardConsole.vue +2 -2
  3. package/lib/components/console/VtsRemoteConsole.vue +1 -1
  4. package/lib/components/data-table/VtsDataTable.vue +13 -14
  5. package/lib/components/input-wrapper/VtsInputWrapper.vue +94 -0
  6. package/lib/components/menu/MenuList.vue +1 -0
  7. package/lib/components/state-hero/VtsLoadingHero.vue +1 -3
  8. package/lib/components/ui/character-limit/UiCharacterLimit.vue +35 -0
  9. package/lib/components/ui/dropdown/UiDropdown.vue +214 -0
  10. package/lib/components/ui/dropdown/UiDropdownList.vue +16 -0
  11. package/lib/components/ui/input/UiInput.vue +7 -8
  12. package/lib/components/ui/label/UiLabel.vue +3 -1
  13. package/lib/components/ui/progress-bar/UiProgressBar.vue +108 -0
  14. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +1 -1
  15. package/lib/components/ui/table-pagination/UiTablePagination.vue +23 -57
  16. package/lib/components/ui/{input → text-area}/UiTextarea.vue +54 -12
  17. package/lib/composables/mapper.composable.md +74 -0
  18. package/lib/composables/mapper.composable.ts +18 -0
  19. package/lib/composables/pagination.composable.md +32 -0
  20. package/lib/composables/pagination.composable.ts +91 -0
  21. package/lib/composables/ranked.composable.md +118 -0
  22. package/lib/composables/ranked.composable.ts +37 -0
  23. package/lib/locales/en.json +23 -1
  24. package/lib/locales/fr.json +22 -0
  25. package/lib/utils/if-else.utils.ts +1 -1
  26. package/lib/utils/injection-keys.util.ts +3 -2
  27. package/package.json +22 -22
  28. package/lib/components/dropdown/DropdownItem.vue +0 -163
  29. package/lib/components/dropdown/DropdownList.vue +0 -31
@@ -14,6 +14,7 @@ export type ConnectionStatus =
14
14
  | 'disconnected'
15
15
  | 'partially-connected'
16
16
  | 'disconnected-from-physical-device'
17
+ | 'physically-disconnected'
17
18
  type ConnectionStatusesMap = Record<ConnectionStatus, { text: string; accent: InfoAccent }>
18
19
 
19
20
  const { status } = defineProps<{
@@ -27,6 +28,8 @@ const statuses: ComputedRef<ConnectionStatusesMap> = computed(() => ({
27
28
  disconnected: { text: t('disconnected'), accent: 'danger' },
28
29
  'partially-connected': { text: t('partially-connected'), accent: 'warning' },
29
30
  'disconnected-from-physical-device': { text: t('disconnected-from-physical-device'), accent: 'warning' },
31
+ // This status is used in host pif side panel
32
+ 'physically-disconnected': { text: t('disconnected-from-physical-device'), accent: 'danger' },
30
33
  }))
31
34
 
32
35
  const currentStatus = computed(() => statuses.value[status])
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="vts-clipboard-console">
3
3
  <UiCardTitle>{{ $t('console-clipboard') }}</UiCardTitle>
4
- <UiTextarea v-tooltip="$t('coming-soon')" accent="info" disabled :model-value="modelValue" />
4
+ <UiTextarea v-tooltip="$t('coming-soon')" accent="brand" disabled :model-value="modelValue" />
5
5
  <div class="buttons-container">
6
6
  <UiButton v-tooltip="$t('coming-soon')" accent="brand" variant="primary" size="medium" disabled>
7
7
  {{ $t('send') }}
@@ -16,7 +16,7 @@
16
16
  <script setup lang="ts">
17
17
  import UiButton from '@core/components/ui/button/UiButton.vue'
18
18
  import UiCardTitle from '@core/components/ui/card-title/UiCardTitle.vue'
19
- import UiTextarea from '@core/components/ui/input/UiTextarea.vue'
19
+ import UiTextarea from '@core/components/ui/text-area/UiTextarea.vue'
20
20
  import { vTooltip } from '@core/directives/tooltip.directive'
21
21
  import { ref } from 'vue'
22
22
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :class="uiStore.isMobile ? 'mobile' : undefined" class="vts-remote-console">
3
- <VtsLoadingHero :disabled="isReady" type="panel" />
3
+ <VtsLoadingHero v-if="!isReady" type="panel" />
4
4
  <div ref="console-container" class="console" />
5
5
  </div>
6
6
  </template>
@@ -1,24 +1,23 @@
1
1
  <template>
2
2
  <div class="table-container">
3
- <VtsLoadingHero :disabled="isReady" type="table">
4
- <VtsTable vertical-border>
5
- <thead>
6
- <slot name="thead" />
7
- </thead>
8
- <tbody>
9
- <slot name="tbody" />
10
- </tbody>
11
- </VtsTable>
12
- </VtsLoadingHero>
13
- <VtsErrorNoDataHero v-if="isReady && hasError" type="table" />
14
- <VtsStateHero v-if="isReady && noDataMessage" type="table" image="no-data" />
3
+ <VtsLoadingHero v-if="!isReady" type="table" />
4
+ <VtsErrorNoDataHero v-else-if="hasError" type="table" />
5
+ <VtsNoDataHero v-else-if="noDataMessage" type="table" />
6
+ <VtsTable v-else vertical-border>
7
+ <thead>
8
+ <slot name="thead" />
9
+ </thead>
10
+ <tbody>
11
+ <slot name="tbody" />
12
+ </tbody>
13
+ </VtsTable>
15
14
  </div>
16
15
  </template>
17
16
 
18
- <script setup lang="ts">
17
+ <script lang="ts" setup>
19
18
  import VtsErrorNoDataHero from '@core/components/state-hero/VtsErrorNoDataHero.vue'
20
19
  import VtsLoadingHero from '@core/components/state-hero/VtsLoadingHero.vue'
21
- import VtsStateHero from '@core/components/state-hero/VtsStateHero.vue'
20
+ import VtsNoDataHero from '@core/components/state-hero/VtsNoDataHero.vue'
22
21
  import VtsTable from '@core/components/table/VtsTable.vue'
23
22
 
24
23
  defineProps<{
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <div class="vts-input-wrapper">
3
+ <UiLabel
4
+ :accent="labelAccent"
5
+ :for="id"
6
+ :href="learnMoreUrl"
7
+ :icon
8
+ :required="wrapperController.required"
9
+ class="label"
10
+ >
11
+ <slot name="label">{{ label }}</slot>
12
+ </UiLabel>
13
+ <slot />
14
+ <UiInfo v-for="{ content, accent } of messages" :key="content" :accent>
15
+ {{ content }}
16
+ </UiInfo>
17
+ </div>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import UiInfo, { type InfoAccent } from '@core/components/ui/info/UiInfo.vue'
22
+ import UiLabel, { type LabelAccent } from '@core/components/ui/label/UiLabel.vue'
23
+ import { useMapper } from '@core/composables/mapper.composable'
24
+ import { useRanked } from '@core/composables/ranked.composable.ts'
25
+ import type { MaybeArray } from '@core/types/utility.type'
26
+ import { IK_INPUT_WRAPPER_CONTROLLER } from '@core/utils/injection-keys.util'
27
+ import { toArray } from '@core/utils/to-array.utils'
28
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
29
+ import { useArrayMap } from '@vueuse/core'
30
+ import { provide, reactive, useId } from 'vue'
31
+
32
+ export type InputWrapperMessage = MaybeArray<string | { content: string; accent?: InfoAccent }>
33
+
34
+ export type InputWrapperController = {
35
+ id: string
36
+ labelAccent: LabelAccent
37
+ required: boolean
38
+ }
39
+
40
+ const { message: _message } = defineProps<{
41
+ label?: string
42
+ learnMoreUrl?: string
43
+ icon?: IconDefinition
44
+ message?: InputWrapperMessage
45
+ }>()
46
+
47
+ defineSlots<{
48
+ default(): any
49
+ label?(): any
50
+ }>()
51
+
52
+ const id = useId()
53
+
54
+ const unsortedMessages = useArrayMap(
55
+ () => toArray(_message),
56
+ item => ({
57
+ content: typeof item === 'object' ? item.content : item,
58
+ accent: typeof item === 'object' ? (item.accent ?? 'info') : 'info',
59
+ })
60
+ )
61
+
62
+ const messages = useRanked(unsortedMessages, ({ accent }) => accent, ['danger', 'warning', 'success', 'info'])
63
+
64
+ const labelAccent = useMapper<InfoAccent, LabelAccent>(
65
+ () => messages.value[0]?.accent,
66
+ {
67
+ info: 'neutral',
68
+ success: 'neutral',
69
+ warning: 'warning',
70
+ danger: 'danger',
71
+ },
72
+ 'neutral'
73
+ )
74
+
75
+ const wrapperController = reactive({
76
+ id,
77
+ labelAccent,
78
+ required: false,
79
+ }) satisfies InputWrapperController
80
+
81
+ provide(IK_INPUT_WRAPPER_CONTROLLER, wrapperController)
82
+ </script>
83
+
84
+ <style lang="postcss" scoped>
85
+ .vts-input-wrapper {
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 0.4rem;
89
+
90
+ .label {
91
+ min-height: 2.4rem;
92
+ }
93
+ }
94
+ </style>
@@ -74,6 +74,7 @@ const open = (event: MouseEvent) => {
74
74
  nextTick(() => {
75
75
  clearClickOutsideEvent = onClickOutside(menu, () => (isOpen.value = false), {
76
76
  ignore: [event.currentTarget as HTMLElement],
77
+ controls: false,
77
78
  })
78
79
 
79
80
  placementJs(event.currentTarget as HTMLElement, unrefElement(menu), {
@@ -1,8 +1,7 @@
1
1
  <template>
2
- <VtsStateHero v-if="!disabled" :type busy class="vts-loading-hero">
2
+ <VtsStateHero :type busy>
3
3
  {{ $t('loading-in-progress') }}
4
4
  </VtsStateHero>
5
- <slot v-else />
6
5
  </template>
7
6
 
8
7
  <script lang="ts" setup>
@@ -10,6 +9,5 @@ import VtsStateHero, { type StateHeroType } from '@core/components/state-hero/Vt
10
9
 
11
10
  defineProps<{
12
11
  type: StateHeroType
13
- disabled?: boolean
14
12
  }>()
15
13
  </script>
@@ -0,0 +1,35 @@
1
+ <!-- v1 -->
2
+ <template>
3
+ <span class="ui-character-limit" :class="classes">
4
+ {{ $t('core.character-limit', { count, max }) }}
5
+ </span>
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import { computed } from 'vue'
10
+
11
+ const { count, max } = defineProps<{
12
+ count: number
13
+ max: number
14
+ }>()
15
+
16
+ const isTooLong = computed(() => count > max)
17
+
18
+ const classes = computed(() => {
19
+ if (isTooLong.value) {
20
+ return ['has-error', 'typo-body-bold-small']
21
+ }
22
+
23
+ return 'typo-body-regular-small'
24
+ })
25
+ </script>
26
+
27
+ <style lang="postcss" scoped>
28
+ .ui-character-limit {
29
+ color: var(--color-neutral-txt-secondary);
30
+
31
+ &.has-error {
32
+ color: var(--color-danger-txt-base);
33
+ }
34
+ }
35
+ </style>
@@ -0,0 +1,214 @@
1
+ <!-- v7 -->
2
+ <template>
3
+ <div v-tooltip="{ selector: '.text-ellipsis' }" :class="className" class="ui-dropdown">
4
+ <UiCheckbox v-if="checkbox" :disabled :model-value="selected" accent="brand" />
5
+ <slot name="icon">
6
+ <VtsIcon :icon accent="current" />
7
+ </slot>
8
+ <div class="text-ellipsis typo-body-bold-small">
9
+ <slot />
10
+ </div>
11
+ <div v-if="info" class="info typo-body-regular-small">{{ info }}</div>
12
+ <VtsIcon
13
+ v-if="subMenuIcon || locked"
14
+ :accent="disabled ? 'current' : 'brand'"
15
+ :icon="locked ? faLock : faAngleRight"
16
+ class="right-icon"
17
+ fixed-width
18
+ />
19
+ </div>
20
+ </template>
21
+
22
+ <script lang="ts" setup>
23
+ import VtsIcon from '@core/components/icon/VtsIcon.vue'
24
+ import UiCheckbox from '@core/components/ui/checkbox/UiCheckbox.vue'
25
+ import { vTooltip } from '@core/directives/tooltip.directive'
26
+ import { toVariants } from '@core/utils/to-variants.util'
27
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
28
+ import { faAngleRight, faLock } from '@fortawesome/free-solid-svg-icons'
29
+ import { computed } from 'vue'
30
+
31
+ export type DropdownAccent = 'normal' | 'brand' | 'success' | 'warning' | 'danger'
32
+
33
+ const {
34
+ accent,
35
+ disabled: _disabled,
36
+ locked,
37
+ selected,
38
+ hover,
39
+ } = defineProps<{
40
+ accent: DropdownAccent
41
+ disabled?: boolean
42
+ locked?: boolean
43
+ selected?: boolean
44
+ hover?: boolean
45
+ checkbox?: boolean
46
+ subMenuIcon?: boolean
47
+ icon?: IconDefinition
48
+ info?: string
49
+ }>()
50
+
51
+ const disabled = computed(() => _disabled || locked)
52
+
53
+ const className = computed(() =>
54
+ toVariants({
55
+ accent,
56
+ disabled: disabled.value,
57
+ selected,
58
+ hover,
59
+ })
60
+ )
61
+ </script>
62
+
63
+ <style lang="postcss" scoped>
64
+ .ui-dropdown {
65
+ display: flex;
66
+ align-items: center;
67
+ padding: 1.2rem;
68
+ gap: 0.8rem;
69
+ height: 4.5rem;
70
+ cursor: default;
71
+
72
+ &.accent--normal {
73
+ color: var(--color-neutral-txt-primary);
74
+ background-color: var(--color-neutral-background-primary);
75
+
76
+ &.selected {
77
+ background-color: var(--color-brand-background-selected);
78
+ }
79
+
80
+ &:is(:hover, .hover) {
81
+ background-color: var(--color-brand-background-hover);
82
+ }
83
+
84
+ &:active {
85
+ background-color: var(--color-brand-background-active);
86
+ }
87
+
88
+ &.disabled {
89
+ color: var(--color-neutral-txt-secondary);
90
+ background-color: var(--color-neutral-background-disabled);
91
+ }
92
+ }
93
+
94
+ &.accent--brand {
95
+ color: var(--color-brand-txt-base);
96
+ background-color: var(--color-neutral-background-primary);
97
+
98
+ &.selected {
99
+ color: var(--color-brand-txt-base);
100
+ background-color: var(--color-brand-background-selected);
101
+ }
102
+
103
+ &:is(:hover, .hover) {
104
+ color: var(--color-brand-txt-hover);
105
+ background-color: var(--color-brand-background-hover);
106
+ }
107
+
108
+ &:active {
109
+ color: var(--color-brand-txt-active);
110
+ background-color: var(--color-brand-background-active);
111
+ }
112
+
113
+ &.disabled {
114
+ color: var(--color-neutral-txt-secondary);
115
+ background-color: var(--color-neutral-background-disabled);
116
+ }
117
+ }
118
+
119
+ &.accent--success {
120
+ color: var(--color-success-txt-base);
121
+ background-color: var(--color-neutral-background-primary);
122
+
123
+ &.selected {
124
+ color: var(--color-success-txt-base);
125
+ background-color: var(--color-success-background-selected);
126
+ }
127
+
128
+ &:is(:hover, .hover) {
129
+ color: var(--color-success-txt-hover);
130
+ background-color: var(--color-success-background-hover);
131
+ }
132
+
133
+ &:active {
134
+ color: var(--color-success-txt-active);
135
+ background-color: var(--color-success-background-active);
136
+ }
137
+
138
+ &.disabled {
139
+ color: var(--color-neutral-txt-secondary);
140
+ background-color: var(--color-neutral-background-disabled);
141
+ }
142
+ }
143
+
144
+ &.accent--warning {
145
+ color: var(--color-warning-txt-base);
146
+ background-color: var(--color-neutral-background-primary);
147
+
148
+ &.selected {
149
+ color: var(--color-warning-txt-base);
150
+ background-color: var(--color-warning-background-selected);
151
+ }
152
+
153
+ &:is(:hover, .hover) {
154
+ color: var(--color-warning-txt-hover);
155
+ background-color: var(--color-warning-background-hover);
156
+ }
157
+
158
+ &:active {
159
+ color: var(--color-warning-txt-active);
160
+ background-color: var(--color-warning-background-active);
161
+ }
162
+
163
+ &.disabled {
164
+ color: var(--color-neutral-txt-secondary);
165
+ background-color: var(--color-neutral-background-disabled);
166
+ }
167
+ }
168
+
169
+ &.accent--danger {
170
+ color: var(--color-danger-txt-base);
171
+ background-color: var(--color-neutral-background-primary);
172
+
173
+ &.selected {
174
+ color: var(--color-danger-txt-base);
175
+ background-color: var(--color-danger-background-selected);
176
+ }
177
+
178
+ &:is(:hover, .hover) {
179
+ color: var(--color-danger-txt-hover);
180
+ background-color: var(--color-danger-background-hover);
181
+ }
182
+
183
+ &:active {
184
+ color: var(--color-danger-txt-active);
185
+ background-color: var(--color-danger-background-active);
186
+ }
187
+
188
+ &.disabled {
189
+ color: var(--color-neutral-txt-secondary);
190
+ background-color: var(--color-neutral-background-disabled);
191
+ }
192
+ }
193
+
194
+ &:focus-visible {
195
+ outline: none;
196
+
197
+ &::before {
198
+ content: '';
199
+ position: absolute;
200
+ inset: 0.2rem;
201
+ border: 0.2rem solid var(--color-info-txt-base);
202
+ border-radius: 0.4rem;
203
+ }
204
+ }
205
+
206
+ .info {
207
+ color: var(--color-neutral-txt-secondary);
208
+ }
209
+
210
+ .right-icon {
211
+ font-size: 1.2rem;
212
+ }
213
+ }
214
+ </style>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="ui-dropdown-list">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style lang="postcss" scoped>
8
+ .ui-dropdown-list {
9
+ display: flex;
10
+ flex-direction: column;
11
+ overflow: auto;
12
+ background: var(--color-neutral-background-primary);
13
+ border: 0.1rem solid var(--color-neutral-border);
14
+ border-radius: 0.4rem;
15
+ }
16
+ </style>
@@ -22,7 +22,7 @@
22
22
  @click="modelValue = ''"
23
23
  />
24
24
  </div>
25
- <UiInfo v-if="slots.info || info" :accent>
25
+ <UiInfo v-if="slots.info || info" :accent="accent === 'brand' ? 'info' : accent">
26
26
  <slot name="info">{{ info }}</slot>
27
27
  </UiInfo>
28
28
  </div>
@@ -37,7 +37,7 @@ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
37
37
  import { faXmark } from '@fortawesome/free-solid-svg-icons'
38
38
  import { computed, useAttrs, useId } from 'vue'
39
39
 
40
- type InputAccent = 'info' | 'warning' | 'danger'
40
+ type InputAccent = 'brand' | 'warning' | 'danger'
41
41
  type InputType = 'text' | 'number' | 'password' | 'search'
42
42
 
43
43
  defineOptions({
@@ -67,7 +67,7 @@ const slots = defineSlots<{
67
67
 
68
68
  const attrs = useAttrs()
69
69
 
70
- const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
70
+ const labelAccent = computed(() => (accent === 'brand' ? 'neutral' : accent))
71
71
  </script>
72
72
 
73
73
  <style lang="postcss" scoped>
@@ -76,7 +76,6 @@ const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
76
76
  position: relative;
77
77
  display: flex;
78
78
  flex-direction: column;
79
- flex: 1;
80
79
  gap: 0.4rem;
81
80
  flex: 1;
82
81
 
@@ -107,20 +106,20 @@ const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
107
106
 
108
107
  /* VARIANT */
109
108
 
110
- &.accent--info {
109
+ &.accent--brand {
111
110
  .input {
112
111
  border-color: var(--color-neutral-border);
113
112
 
114
113
  &:hover {
115
- border-color: var(--color-info-item-hover);
114
+ border-color: var(--color-brand-item-hover);
116
115
  }
117
116
 
118
117
  &:focus {
119
- border-color: var(--color-info-item-base);
118
+ border-color: var(--color-brand-item-base);
120
119
  }
121
120
 
122
121
  &:active {
123
- border-color: var(--color-info-item-active);
122
+ border-color: var(--color-brand-item-active);
124
123
  }
125
124
 
126
125
  &:disabled {
@@ -15,8 +15,10 @@ import UiLink from '@core/components/ui/link/UiLink.vue'
15
15
  import { toVariants } from '@core/utils/to-variants.util'
16
16
  import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
17
17
 
18
+ export type LabelAccent = 'neutral' | 'warning' | 'danger'
19
+
18
20
  const { for: htmlFor } = defineProps<{
19
- accent: 'neutral' | 'warning' | 'danger'
21
+ accent: LabelAccent
20
22
  for?: string
21
23
  icon?: IconDefinition
22
24
  required?: boolean
@@ -0,0 +1,108 @@
1
+ <!-- v2 -->
2
+ <template>
3
+ <div class="ui-progress-bar" :class="className">
4
+ <div class="progress-bar">
5
+ <div class="fill" :style="{ width: `${fillWidth}%` }" />
6
+ </div>
7
+ <div v-if="shouldShowSteps" class="steps typo-body-regular-small">
8
+ <span>{{ $n(0, 'percent') }}</span>
9
+ <span v-for="step in steps" :key="step">{{ $n(step, 'percent') }}</span>
10
+ </div>
11
+ <VtsLegendList class="legend">
12
+ <UiLegend :accent :value="Math.round(percentage)" unit="%">{{ legend }}</UiLegend>
13
+ </VtsLegendList>
14
+ </div>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import VtsLegendList from '@core/components/legend-list/VtsLegendList.vue'
19
+ import UiLegend from '@core/components/ui/legend/UiLegend.vue'
20
+ import { toVariants } from '@core/utils/to-variants.util'
21
+ import { useClamp, useMax } from '@vueuse/math'
22
+ import { computed } from 'vue'
23
+
24
+ const {
25
+ value: _value,
26
+ max = 100,
27
+ showSteps,
28
+ } = defineProps<{
29
+ legend: string
30
+ value: number
31
+ max?: number
32
+ showSteps?: boolean
33
+ }>()
34
+
35
+ const value = useMax(0, () => _value)
36
+
37
+ const percentage = computed(() => (max <= 0 ? 0 : (value.value / max) * 100))
38
+ const maxPercentage = computed(() => Math.ceil(percentage.value / 100) * 100)
39
+ const fillWidth = useClamp(() => (percentage.value / maxPercentage.value) * 100 || 0, 0, 100)
40
+ const shouldShowSteps = computed(() => showSteps || percentage.value > 100)
41
+ const steps = useMax(1, () => Math.floor(maxPercentage.value / 100))
42
+
43
+ const accent = computed(() => {
44
+ if (percentage.value >= 90) {
45
+ return 'danger'
46
+ }
47
+
48
+ if (percentage.value >= 80) {
49
+ return 'warning'
50
+ }
51
+
52
+ return 'info'
53
+ })
54
+
55
+ const className = computed(() => toVariants({ accent: accent.value }))
56
+ </script>
57
+
58
+ <style lang="postcss" scoped>
59
+ .ui-progress-bar {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: 0.4rem;
63
+
64
+ .progress-bar {
65
+ width: 100%;
66
+ height: 1.2rem;
67
+ border-radius: 0.4rem;
68
+ overflow: hidden;
69
+ background-color: var(--color-neutral-background-disabled);
70
+
71
+ .fill {
72
+ width: 0;
73
+ height: 100%;
74
+ transition: width 0.25s ease-in-out;
75
+ }
76
+ }
77
+
78
+ .steps {
79
+ color: var(--color-neutral-txt-secondary);
80
+ display: flex;
81
+ justify-content: space-between;
82
+ }
83
+
84
+ .legend {
85
+ margin-inline-start: auto;
86
+ }
87
+
88
+ /* ACCENT */
89
+
90
+ &.accent--info {
91
+ .fill {
92
+ background-color: var(--color-info-item-base);
93
+ }
94
+ }
95
+
96
+ &.accent--warning {
97
+ .fill {
98
+ background-color: var(--color-warning-item-base);
99
+ }
100
+ }
101
+
102
+ &.accent--danger {
103
+ .fill {
104
+ background-color: var(--color-danger-item-base);
105
+ }
106
+ }
107
+ }
108
+ </style>
@@ -8,7 +8,7 @@
8
8
  :id
9
9
  v-model="value"
10
10
  type="text"
11
- accent="info"
11
+ accent="brand"
12
12
  :aria-label="uiStore.isMobile ? $t('core.query-search-bar.label') : undefined"
13
13
  :icon="uiStore.isDesktop ? faMagnifyingGlass : undefined"
14
14
  :placeholder="$t('core.query-search-bar.placeholder')"