@xen-orchestra/web-core 0.14.0 → 0.16.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/lib/assets/css/_typography.pcss +148 -6
- package/lib/assets/css/base.pcss +4 -4
- package/lib/components/backup-item/VtsBackupItem.vue +1 -1
- package/lib/components/card/VtsCardRowKeyValue.vue +4 -2
- package/lib/components/cell-object/VtsCellObject.vue +1 -1
- package/lib/components/cell-text/VtsCellText.vue +2 -2
- package/lib/components/connection-status/VtsConnectionStatus.vue +3 -0
- package/lib/components/console/VtsClipboardConsole.vue +2 -2
- package/lib/components/data-table/VtsDataTable.vue +11 -3
- package/lib/components/menu/MenuTrigger.vue +2 -2
- package/lib/components/resources/VtsResource.vue +4 -5
- package/lib/components/state-hero/VtsPageNotFoundHero.vue +1 -1
- package/lib/components/state-hero/VtsStateHero.vue +2 -2
- package/lib/components/tab/TabItem.vue +10 -10
- package/lib/components/table/ColumnTitle.vue +8 -8
- package/lib/components/table/VtsTable.vue +2 -2
- package/lib/components/task/VtsQuickTaskList.vue +1 -1
- package/lib/components/tree/VtsTreeItemError.vue +1 -1
- package/lib/components/ui/account-menu-button/UiAccountMenuButton.vue +1 -1
- package/lib/components/ui/actions-title/UiActionsTitle.vue +1 -1
- package/lib/components/ui/button/UiButton.vue +12 -12
- package/lib/components/ui/button-icon/UiButtonIcon.vue +3 -3
- package/lib/components/ui/card-numbers/UiCardNumbers.vue +4 -6
- package/lib/components/ui/card-subtitle/UiCardSubtitle.vue +3 -3
- package/lib/components/ui/card-title/UiCardTitle.vue +3 -3
- package/lib/components/ui/character-limit/UiCharacterLimit.vue +35 -0
- package/lib/components/ui/checkbox/UiCheckbox.vue +4 -4
- package/lib/components/ui/chip/UiChip.vue +1 -1
- package/lib/components/ui/counter/UiCounter.vue +7 -7
- package/lib/components/ui/dropdown-button/UiDropdownButton.vue +2 -2
- package/lib/components/ui/head-bar/UiHeadBar.vue +2 -2
- package/lib/components/ui/info/UiInfo.vue +1 -1
- package/lib/components/ui/input/UiInput.vue +15 -9
- package/lib/components/ui/label/UiLabel.vue +1 -1
- package/lib/components/ui/legend/UiLegend.vue +3 -3
- package/lib/components/ui/legend-title/UiLegendTitle.vue +1 -1
- package/lib/components/ui/link/UiLink.vue +3 -3
- package/lib/components/ui/object-link/UiObjectLink.vue +7 -7
- package/lib/components/ui/panel/UiPanel.vue +4 -2
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +2 -2
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +3 -3
- package/lib/components/ui/radio-button/UiRadioButton.vue +2 -2
- package/lib/components/ui/stacked-bar/StackedBarSegment.vue +1 -1
- package/lib/components/ui/table-pagination/UiTablePagination.vue +4 -4
- package/lib/components/ui/tag/UiTag.vue +1 -1
- package/lib/components/ui/{input → text-area}/UiTextarea.vue +54 -12
- package/lib/components/ui/title/UiTitle.vue +3 -3
- package/lib/components/ui/toaster/UiToaster.vue +2 -2
- package/lib/components/ui/toggle/UiToggle.vue +3 -3
- package/lib/components/ui/tooltip/UiTooltip.vue +1 -1
- package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +1 -1
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +1 -1
- package/lib/components/ui/user-link/UiUserLink.vue +8 -8
- package/lib/i18n.ts +4 -0
- package/lib/locales/cs.json +362 -16
- package/lib/locales/de.json +245 -41
- package/lib/locales/en.json +316 -14
- package/lib/locales/es.json +355 -29
- package/lib/locales/fa.json +206 -9
- package/lib/locales/fr.json +320 -18
- package/lib/locales/sv.json +421 -0
- package/lib/utils/to-variants.util.md +3 -3
- package/package.json +1 -1
- package/lib/assets/css/typography/_legacy.pcss +0 -123
- package/lib/assets/css/typography/_letter-spacing.pcss +0 -27
- package/lib/assets/css/typography/_line-height.pcss +0 -19
- package/lib/assets/css/typography/_size.pcss +0 -95
- package/lib/assets/css/typography/_style.pcss +0 -35
- package/lib/assets/css/typography/_weight.pcss +0 -57
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<!-- v1 -->
|
|
2
2
|
<template>
|
|
3
3
|
<div class="ui-card-numbers" :class="sizeClass">
|
|
4
|
-
<span class="label
|
|
4
|
+
<span class="label typo-caption-small">{{ label }}</span>
|
|
5
5
|
<div class="values" :class="sizeClass">
|
|
6
|
-
<span v-if="percentValue" class="value typo
|
|
6
|
+
<span v-if="percentValue" class="value typo-caption-small">
|
|
7
7
|
{{ percentValue }}
|
|
8
8
|
</span>
|
|
9
9
|
|
|
@@ -31,11 +31,9 @@ const { n } = useI18n()
|
|
|
31
31
|
|
|
32
32
|
const sizeClass = computed(() => toVariants({ size: props.size }))
|
|
33
33
|
|
|
34
|
-
const
|
|
34
|
+
const valueFontClass = computed(() => (props.size === 'medium' ? 'typo-h3' : 'typo-caption-small'))
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
const unitFontClass = computed(() => (props.size === 'medium' ? 'typo p2-medium' : 'typo c2-semi-bold'))
|
|
36
|
+
const unitFontClass = computed(() => (props.size === 'medium' ? 'typo-body-bold-small' : 'typo-caption-small'))
|
|
39
37
|
|
|
40
38
|
const percentValue = computed(() => {
|
|
41
39
|
if (props.size !== 'small' || props.max === undefined || props.max === 0) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- v1 -->
|
|
2
2
|
<template>
|
|
3
|
-
<div class="ui-card-subtitle">
|
|
4
|
-
<span
|
|
5
|
-
<span v-if="slots.info"
|
|
3
|
+
<div class="ui-card-subtitle typo-body-bold-small">
|
|
4
|
+
<span><slot /></span>
|
|
5
|
+
<span v-if="slots.info"><slot name="info" /></span>
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
8
8
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<div class="ui-card-title">
|
|
4
4
|
<div class="main-content">
|
|
5
|
-
<div class="title typo
|
|
5
|
+
<div class="title typo-body-bold">
|
|
6
6
|
<slot />
|
|
7
7
|
</div>
|
|
8
|
-
<div v-if="slots.info" class="info typo
|
|
8
|
+
<div v-if="slots.info" class="info typo-body-bold-small">
|
|
9
9
|
<slot name="info" />
|
|
10
10
|
</div>
|
|
11
11
|
</div>
|
|
12
|
-
<p v-if="slots.description" class="description typo
|
|
12
|
+
<p v-if="slots.description" class="description typo-body-regular-small">
|
|
13
13
|
<slot name="description" />
|
|
14
14
|
</p>
|
|
15
15
|
</div>
|
|
@@ -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>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<span class="fake-checkbox">
|
|
13
13
|
<VtsIcon :icon accent="current" class="icon" />
|
|
14
14
|
</span>
|
|
15
|
-
<span v-if="slots.default" class="typo
|
|
15
|
+
<span v-if="slots.default" class="typo-body-regular">
|
|
16
16
|
<slot />
|
|
17
17
|
</span>
|
|
18
18
|
</label>
|
|
@@ -156,7 +156,7 @@ const attrs = useAttrs()
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
&:focus-visible + .fake-checkbox::before {
|
|
159
|
-
border: 0.2rem solid var(--color-
|
|
159
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
&:active + .fake-checkbox {
|
|
@@ -207,7 +207,7 @@ const attrs = useAttrs()
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
&:focus-visible + .fake-checkbox::before {
|
|
210
|
-
border: 0.2rem solid var(--color-
|
|
210
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
&:active + .fake-checkbox {
|
|
@@ -262,7 +262,7 @@ const attrs = useAttrs()
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
&:focus-visible + .fake-checkbox::before {
|
|
265
|
-
border: 0.2rem solid var(--color-
|
|
265
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
&:active + .fake-checkbox {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- v4 -->
|
|
2
2
|
<template>
|
|
3
|
-
<span :class="classNames" class="ui-chip typo
|
|
3
|
+
<span :class="classNames" class="ui-chip typo-body-regular-small" @click="emit('edit')">
|
|
4
4
|
<ChipIcon :disabled :icon />
|
|
5
5
|
<span class="content text-ellipsis">
|
|
6
6
|
<slot />
|
|
@@ -21,8 +21,8 @@ const { size, accent, variant } = defineProps<{
|
|
|
21
21
|
}>()
|
|
22
22
|
|
|
23
23
|
const typoClasses = {
|
|
24
|
-
small: 'typo
|
|
25
|
-
medium: 'typo
|
|
24
|
+
small: 'typo-body-bold-small',
|
|
25
|
+
medium: 'typo-body-bold',
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const classNames = computed(() => {
|
|
@@ -57,16 +57,16 @@ const classNames = computed(() => {
|
|
|
57
57
|
color: var(--color-brand-txt-item);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
&.accent--info {
|
|
61
|
-
background-color: var(--color-info-item-base);
|
|
62
|
-
color: var(--color-info-txt-item);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
60
|
&.accent--neutral {
|
|
66
61
|
background-color: var(--color-neutral-txt-primary);
|
|
67
62
|
color: var(--color-neutral-background-primary);
|
|
68
63
|
}
|
|
69
64
|
|
|
65
|
+
&.accent--info {
|
|
66
|
+
background-color: var(--color-info-item-base);
|
|
67
|
+
color: var(--color-info-txt-item);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
70
|
&.accent--success {
|
|
71
71
|
background-color: var(--color-success-item-base);
|
|
72
72
|
color: var(--color-success-txt-item);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<button :class="{ selected }" :disabled="isDisabled" class="ui-dropdown-item" type="button">
|
|
4
4
|
<VtsIcon :icon accent="current" class="left-icon" fixed-width />
|
|
5
|
-
<span class="typo
|
|
5
|
+
<span class="typo-action-button label">
|
|
6
6
|
<slot />
|
|
7
7
|
</span>
|
|
8
8
|
<VtsIcon :icon="faAngleDown" accent="current" class="right-icon" fixed-width />
|
|
@@ -62,7 +62,7 @@ const isDisabled = useDisabled(() => disabled)
|
|
|
62
62
|
content: '';
|
|
63
63
|
position: absolute;
|
|
64
64
|
inset: -0.5rem;
|
|
65
|
-
border: 0.2rem solid var(--color-
|
|
65
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
66
66
|
border-radius: 0.4rem;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
<VtsIcon :icon accent="current" />
|
|
8
8
|
</slot>
|
|
9
9
|
</span>
|
|
10
|
-
<h4 v-tooltip class="typo
|
|
10
|
+
<h4 v-tooltip class="typo-h4 label text-ellipsis">
|
|
11
11
|
<slot />
|
|
12
12
|
</h4>
|
|
13
13
|
</div>
|
|
14
|
-
<div v-if="slots.status" class="status typo
|
|
14
|
+
<div v-if="slots.status" class="status typo-caption-small">
|
|
15
15
|
<slot name="status" />
|
|
16
16
|
</div>
|
|
17
17
|
<div v-if="slots.actions" class="actions">
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<div class="ui-info">
|
|
4
4
|
<VtsIcon :accent class="icon" :icon="faCircle" :overlay-icon="icon" />
|
|
5
|
-
<p v-tooltip="!wrap" class="typo
|
|
5
|
+
<p v-tooltip="!wrap" class="typo-form-info" :class="{ 'text-ellipsis': !wrap }">
|
|
6
6
|
<slot />
|
|
7
7
|
</p>
|
|
8
8
|
</div>
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
</UiLabel>
|
|
7
7
|
<div>
|
|
8
8
|
<VtsIcon :icon accent="current" class="before" />
|
|
9
|
-
<input
|
|
9
|
+
<input
|
|
10
|
+
:id
|
|
11
|
+
v-model.trim="modelValue"
|
|
12
|
+
class="typo-body-regular input text-ellipsis"
|
|
13
|
+
:type
|
|
14
|
+
:disabled
|
|
15
|
+
v-bind="attrs"
|
|
16
|
+
/>
|
|
10
17
|
<VtsIcon
|
|
11
18
|
v-if="!attrs.disabled && modelValue && clearable"
|
|
12
19
|
:icon="faXmark"
|
|
@@ -15,7 +22,7 @@
|
|
|
15
22
|
@click="modelValue = ''"
|
|
16
23
|
/>
|
|
17
24
|
</div>
|
|
18
|
-
<UiInfo v-if="slots.info || info" :accent>
|
|
25
|
+
<UiInfo v-if="slots.info || info" :accent="accent === 'brand' ? 'info' : accent">
|
|
19
26
|
<slot name="info">{{ info }}</slot>
|
|
20
27
|
</UiInfo>
|
|
21
28
|
</div>
|
|
@@ -30,7 +37,7 @@ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
|
30
37
|
import { faXmark } from '@fortawesome/free-solid-svg-icons'
|
|
31
38
|
import { computed, useAttrs, useId } from 'vue'
|
|
32
39
|
|
|
33
|
-
type InputAccent = '
|
|
40
|
+
type InputAccent = 'brand' | 'warning' | 'danger'
|
|
34
41
|
type InputType = 'text' | 'number' | 'password' | 'search'
|
|
35
42
|
|
|
36
43
|
defineOptions({
|
|
@@ -60,7 +67,7 @@ const slots = defineSlots<{
|
|
|
60
67
|
|
|
61
68
|
const attrs = useAttrs()
|
|
62
69
|
|
|
63
|
-
const labelAccent = computed(() => (accent === '
|
|
70
|
+
const labelAccent = computed(() => (accent === 'brand' ? 'neutral' : accent))
|
|
64
71
|
</script>
|
|
65
72
|
|
|
66
73
|
<style lang="postcss" scoped>
|
|
@@ -69,7 +76,6 @@ const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
|
|
|
69
76
|
position: relative;
|
|
70
77
|
display: flex;
|
|
71
78
|
flex-direction: column;
|
|
72
|
-
flex: 1;
|
|
73
79
|
gap: 0.4rem;
|
|
74
80
|
flex: 1;
|
|
75
81
|
|
|
@@ -100,20 +106,20 @@ const labelAccent = computed(() => (accent === 'info' ? 'neutral' : accent))
|
|
|
100
106
|
|
|
101
107
|
/* VARIANT */
|
|
102
108
|
|
|
103
|
-
&.accent--
|
|
109
|
+
&.accent--brand {
|
|
104
110
|
.input {
|
|
105
111
|
border-color: var(--color-neutral-border);
|
|
106
112
|
|
|
107
113
|
&:hover {
|
|
108
|
-
border-color: var(--color-
|
|
114
|
+
border-color: var(--color-brand-item-hover);
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
&:focus {
|
|
112
|
-
border-color: var(--color-
|
|
118
|
+
border-color: var(--color-brand-item-base);
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
&:active {
|
|
116
|
-
border-color: var(--color-
|
|
122
|
+
border-color: var(--color-brand-item-active);
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
&:disabled {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<div :class="toVariants({ accent })" class="ui-label">
|
|
4
4
|
<VtsIcon accent="current" :icon class="icon" />
|
|
5
|
-
<label :for="htmlFor" :class="{ required }" class="typo
|
|
5
|
+
<label :for="htmlFor" :class="{ required }" class="typo-caption label">
|
|
6
6
|
<slot />
|
|
7
7
|
</label>
|
|
8
8
|
<UiLink v-if="href" class="learn-more-link" size="small" :href>{{ $t('learn-more') }}</UiLink>
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<li :class="classNames" class="ui-legend">
|
|
4
4
|
<VtsIcon :icon="faCircle" accent="current" class="circle-icon" />
|
|
5
|
-
<span class="label typo
|
|
6
|
-
<VtsIcon v-if="tooltip" v-tooltip="tooltip" :icon="faCircleInfo" class="tooltip-icon" accent="
|
|
7
|
-
<span v-if="valueLabel" class="value-and-unit typo
|
|
5
|
+
<span class="label typo-body-regular-small"><slot /></span>
|
|
6
|
+
<VtsIcon v-if="tooltip" v-tooltip="tooltip" :icon="faCircleInfo" class="tooltip-icon" accent="info" />
|
|
7
|
+
<span v-if="valueLabel" class="value-and-unit typo-caption-small">{{ valueLabel }}</span>
|
|
8
8
|
</li>
|
|
9
9
|
</template>
|
|
10
10
|
|
|
@@ -22,8 +22,8 @@ const props = defineProps<
|
|
|
22
22
|
>()
|
|
23
23
|
|
|
24
24
|
const typoClasses = {
|
|
25
|
-
small: 'typo
|
|
26
|
-
medium: 'typo
|
|
25
|
+
small: 'typo-action-link-small',
|
|
26
|
+
medium: 'typo-action-link',
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const { component, attributes, isDisabled } = useLinkComponent('span', () => props)
|
|
@@ -53,7 +53,7 @@ const classes = computed(() => [typoClasses[props.size], { disabled: isDisabled.
|
|
|
53
53
|
content: '';
|
|
54
54
|
position: absolute;
|
|
55
55
|
inset: -0.4rem;
|
|
56
|
-
border: 0.2rem solid var(--color-
|
|
56
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
57
57
|
border-radius: 0.4rem;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- v3 -->
|
|
2
2
|
<template>
|
|
3
|
-
<RouterLink v-if="route && !disabled" :to="route" class="ui-object-link is-link typo
|
|
3
|
+
<RouterLink v-if="route && !disabled" :to="route" class="ui-object-link is-link typo-action-link-small">
|
|
4
4
|
<span class="icon">
|
|
5
5
|
<slot name="icon">
|
|
6
6
|
<VtsIcon :icon accent="current" />
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<slot />
|
|
11
11
|
</span>
|
|
12
12
|
</RouterLink>
|
|
13
|
-
<span v-else :class="{ disabled }" class="ui-object-link typo
|
|
13
|
+
<span v-else :class="{ disabled }" class="ui-object-link typo-action-link-small">
|
|
14
14
|
<span class="icon">
|
|
15
15
|
<slot name="icon">
|
|
16
16
|
<VtsIcon :icon accent="current" />
|
|
@@ -43,7 +43,7 @@ defineSlots<{
|
|
|
43
43
|
display: flex;
|
|
44
44
|
min-width: 0;
|
|
45
45
|
align-items: center;
|
|
46
|
-
color: var(--color-
|
|
46
|
+
color: var(--color-brand-txt-base);
|
|
47
47
|
gap: 1rem;
|
|
48
48
|
|
|
49
49
|
&.disabled {
|
|
@@ -53,18 +53,18 @@ defineSlots<{
|
|
|
53
53
|
|
|
54
54
|
.icon {
|
|
55
55
|
color: var(--color-neutral-txt-primary);
|
|
56
|
-
font-size:
|
|
56
|
+
font-size: 1.6rem;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/* INTERACTION VARIANTS */
|
|
60
60
|
|
|
61
61
|
&.is-link {
|
|
62
62
|
&:hover {
|
|
63
|
-
color: var(--color-
|
|
63
|
+
color: var(--color-brand-txt-hover);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
&:active {
|
|
67
|
-
color: var(--color-
|
|
67
|
+
color: var(--color-brand-txt-active);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
&:focus-visible {
|
|
@@ -74,7 +74,7 @@ defineSlots<{
|
|
|
74
74
|
content: '';
|
|
75
75
|
position: absolute;
|
|
76
76
|
inset: -0.6rem;
|
|
77
|
-
border: 0.2rem solid var(--color-
|
|
77
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
78
78
|
border-radius: 0.4rem;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -23,10 +23,12 @@ const slots = defineSlots<{
|
|
|
23
23
|
|
|
24
24
|
<style scoped lang="postcss">
|
|
25
25
|
.ui-panel {
|
|
26
|
-
height:
|
|
26
|
+
max-height: calc(100dvh - 5.5rem);
|
|
27
|
+
position: sticky;
|
|
28
|
+
top: 0;
|
|
27
29
|
display: flex;
|
|
28
30
|
flex-direction: column;
|
|
29
|
-
border: 0.1rem solid var(--color-neutral-border);
|
|
31
|
+
border-inline-start: 0.1rem solid var(--color-neutral-border);
|
|
30
32
|
background-color: var(--color-neutral-background-secondary);
|
|
31
33
|
|
|
32
34
|
.header {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<!-- v3 -->
|
|
2
2
|
<template>
|
|
3
3
|
<form class="ui-query-search-bar" @submit.prevent="emit('search', value)">
|
|
4
|
-
<label v-if="uiStore.isDesktop" :for="id" class="typo
|
|
4
|
+
<label v-if="uiStore.isDesktop" :for="id" class="typo-body-regular-small label">
|
|
5
5
|
{{ $t('core.query-search-bar.label') }}
|
|
6
6
|
</label>
|
|
7
7
|
<UiInput
|
|
8
8
|
:id
|
|
9
9
|
v-model="value"
|
|
10
10
|
type="text"
|
|
11
|
-
accent="
|
|
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')"
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<UiButtonIcon accent="brand" :icon="isExpanded ? faAngleDown : faAngleRight" size="small" />
|
|
6
6
|
</div>
|
|
7
7
|
<div class="content">
|
|
8
|
-
<div class="typo
|
|
8
|
+
<div class="typo-body-bold">
|
|
9
9
|
{{ task.name }}
|
|
10
10
|
</div>
|
|
11
11
|
<div class="informations">
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
<UiTag v-if="task.tag" accent="neutral" variant="primary">{{ task.tag }}</UiTag>
|
|
14
14
|
<div v-if="hasSubTasks" class="subtasks">
|
|
15
15
|
<VtsIcon :icon="faCircleNotch" accent="current" />
|
|
16
|
-
<span class="typo
|
|
16
|
+
<span class="typo-body-regular-small">{{ $t('tasks.n-subtasks', { n: subTasksCount }) }}</span>
|
|
17
17
|
</div>
|
|
18
18
|
</div>
|
|
19
|
-
<div v-if="task.start" class="line-2 typo
|
|
19
|
+
<div v-if="task.start" class="line-2 typo-body-regular-small">
|
|
20
20
|
{{ $d(task.start, 'datetime_short') }}
|
|
21
21
|
<template v-if="task.end">
|
|
22
22
|
<VtsIcon :icon="faArrowRight" accent="current" />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- v4 -->
|
|
2
2
|
<template>
|
|
3
|
-
<label :class="variant" class="ui-radio-button typo
|
|
3
|
+
<label :class="variant" class="ui-radio-button typo-body-regular">
|
|
4
4
|
<span class="radio-container">
|
|
5
5
|
<input v-model="model" :disabled="isDisabled" :value class="input" type="radio" />
|
|
6
6
|
<VtsIcon :icon="faCircle" accent="current" class="radio-icon" />
|
|
@@ -60,7 +60,7 @@ const isDisabled = useDisabled(() => disabled)
|
|
|
60
60
|
position: absolute;
|
|
61
61
|
content: '';
|
|
62
62
|
inset: -0.5rem;
|
|
63
|
-
border: 0.2rem solid var(--color-
|
|
63
|
+
border: 0.2rem solid var(--color-brand-txt-base);
|
|
64
64
|
border-radius: 0.4rem;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
v-tooltip="{ selector: '.text-ellipsis' }"
|
|
5
5
|
:class="`accent--${accent}`"
|
|
6
6
|
:style="{ width: percentage + '%' }"
|
|
7
|
-
class="stacked-bar-segment typo
|
|
7
|
+
class="stacked-bar-segment typo-caption-small"
|
|
8
8
|
>
|
|
9
9
|
<div ref="ellipsisElement" :class="{ hidden }" class="text-ellipsis">
|
|
10
10
|
{{ $n(percentage / 100, 'percent') }}
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
<PaginationButton :disabled="isLastPage || disabled" :icon="faAngleRight" @click="goToNextPage()" />
|
|
8
8
|
<PaginationButton :disabled="isLastPage || disabled" :icon="faAngleDoubleRight" @click="goToLastPage()" />
|
|
9
9
|
</div>
|
|
10
|
-
<span class="typo
|
|
10
|
+
<span class="typo-body-regular-small label">
|
|
11
11
|
{{ $t('core.select.n-object-of', { from: startIndex, to: endIndex, total: totalItems }) }}
|
|
12
12
|
</span>
|
|
13
|
-
<span class="typo
|
|
13
|
+
<span class="typo-body-regular-small label show">{{ $t('core.show-by') }}</span>
|
|
14
14
|
<div class="dropdown-wrapper">
|
|
15
|
-
<select v-model="pageSize" :disabled class="dropdown typo
|
|
16
|
-
<option v-for="option in pageSizeOptions" :key="option" :value="option" class="typo
|
|
15
|
+
<select v-model="pageSize" :disabled class="dropdown typo-body-regular-small" @change="goToFirstPage">
|
|
16
|
+
<option v-for="option in pageSizeOptions" :key="option" :value="option" class="typo-body-bold-small">
|
|
17
17
|
{{ option }}
|
|
18
18
|
</option>
|
|
19
19
|
</select>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- v3 -->
|
|
2
2
|
<!-- TODO: implement tertiary variant to bump to v4 -->
|
|
3
3
|
<template>
|
|
4
|
-
<span :class="toVariants({ accent, variant })" class="ui-tag typo
|
|
4
|
+
<span :class="toVariants({ accent, variant })" class="ui-tag typo-body-regular-small">
|
|
5
5
|
<slot name="icon">
|
|
6
6
|
<VtsIcon :icon accent="current" fixed-width />
|
|
7
7
|
</slot>
|
|
@@ -1,25 +1,41 @@
|
|
|
1
1
|
<!-- v2 -->
|
|
2
2
|
<template>
|
|
3
|
-
<div class="ui-textarea" :class="toVariants({ accent })">
|
|
4
|
-
<UiLabel v-if="slots.default" :accent="labelAccent" :required :icon :href
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
<div class="ui-textarea" :class="toVariants({ accent: hasMaxCharactersError ? 'danger' : accent })">
|
|
4
|
+
<UiLabel v-if="slots.default" :accent="labelAccent" :required :icon :href :for="id">
|
|
5
|
+
<slot />
|
|
6
|
+
</UiLabel>
|
|
7
|
+
<textarea v-bind="attrs" :id ref="textarea" v-model="model" :disabled class="textarea" />
|
|
8
|
+
<UiCharacterLimit v-if="maxCharacters" :count="model.trim().length" :max="maxCharacters" />
|
|
9
|
+
<UiInfo v-if="isExceedingMaxCharacters" accent="danger">
|
|
10
|
+
{{ $t('core.textarea.exceeds-max-characters', { max: maxCharacters }) }}
|
|
11
|
+
</UiInfo>
|
|
12
|
+
<UiInfo v-if="slots.info" :accent="accent === 'brand' ? 'info' : accent">
|
|
13
|
+
<slot name="info" />
|
|
14
|
+
</UiInfo>
|
|
7
15
|
</div>
|
|
8
16
|
</template>
|
|
9
17
|
|
|
10
18
|
<script lang="ts" setup>
|
|
19
|
+
import UiCharacterLimit from '@core/components/ui/character-limit/UiCharacterLimit.vue'
|
|
11
20
|
import UiInfo from '@core/components/ui/info/UiInfo.vue'
|
|
12
21
|
import UiLabel from '@core/components/ui/label/UiLabel.vue'
|
|
13
22
|
import { toVariants } from '@core/utils/to-variants.util'
|
|
14
23
|
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
15
|
-
import {
|
|
24
|
+
import { useFocus } from '@vueuse/core'
|
|
25
|
+
import { computed, useAttrs, useId, useTemplateRef } from 'vue'
|
|
16
26
|
|
|
17
27
|
defineOptions({
|
|
18
28
|
inheritAttrs: false,
|
|
19
29
|
})
|
|
20
30
|
|
|
21
|
-
const
|
|
22
|
-
accent
|
|
31
|
+
const {
|
|
32
|
+
accent,
|
|
33
|
+
maxCharacters,
|
|
34
|
+
id = useId(),
|
|
35
|
+
} = defineProps<{
|
|
36
|
+
accent: 'brand' | 'warning' | 'danger'
|
|
37
|
+
id?: string
|
|
38
|
+
maxCharacters?: number
|
|
23
39
|
disabled?: boolean
|
|
24
40
|
href?: string
|
|
25
41
|
icon?: IconDefinition
|
|
@@ -35,7 +51,24 @@ const slots = defineSlots<{
|
|
|
35
51
|
|
|
36
52
|
const attrs = useAttrs()
|
|
37
53
|
|
|
38
|
-
const
|
|
54
|
+
const textAreaElement = useTemplateRef('textarea')
|
|
55
|
+
|
|
56
|
+
const { focused } = useFocus(textAreaElement)
|
|
57
|
+
|
|
58
|
+
// WIP: To update when using VeeValidate and custom validation rules
|
|
59
|
+
const isExceedingMaxCharacters = computed(() =>
|
|
60
|
+
maxCharacters !== undefined ? model.value.trim().length > maxCharacters : false
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
const hasMaxCharactersError = computed(() => !focused.value && isExceedingMaxCharacters.value)
|
|
64
|
+
|
|
65
|
+
const labelAccent = computed(() => {
|
|
66
|
+
if (hasMaxCharactersError.value) {
|
|
67
|
+
return 'danger'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return accent === 'brand' ? 'neutral' : accent
|
|
71
|
+
})
|
|
39
72
|
</script>
|
|
40
73
|
|
|
41
74
|
<style lang="postcss" scoped>
|
|
@@ -54,20 +87,23 @@ const labelAccent = computed(() => (props.accent === 'info' ? 'neutral' : props.
|
|
|
54
87
|
width: 100%;
|
|
55
88
|
}
|
|
56
89
|
|
|
57
|
-
&.accent--
|
|
90
|
+
&.accent--brand {
|
|
58
91
|
.textarea {
|
|
59
92
|
border-color: var(--color-neutral-border);
|
|
60
93
|
|
|
61
94
|
&:hover {
|
|
62
|
-
border-color: var(--color-
|
|
95
|
+
border-color: var(--color-brand-item-hover);
|
|
63
96
|
}
|
|
97
|
+
|
|
64
98
|
&:active {
|
|
65
|
-
border-color: var(--color-
|
|
99
|
+
border-color: var(--color-brand-item-active);
|
|
66
100
|
}
|
|
101
|
+
|
|
67
102
|
&:focus:not(:active) {
|
|
68
103
|
border-width: 0.2rem;
|
|
69
|
-
border-color: var(--color-
|
|
104
|
+
border-color: var(--color-brand-item-base);
|
|
70
105
|
}
|
|
106
|
+
|
|
71
107
|
&:disabled {
|
|
72
108
|
background-color: var(--color-neutral-background-disabled);
|
|
73
109
|
border-color: var(--color-neutral-border);
|
|
@@ -82,13 +118,16 @@ const labelAccent = computed(() => (props.accent === 'info' ? 'neutral' : props.
|
|
|
82
118
|
&:hover {
|
|
83
119
|
border-color: var(--color-warning-item-hover);
|
|
84
120
|
}
|
|
121
|
+
|
|
85
122
|
&:active {
|
|
86
123
|
border-color: var(--color-warning-item-active);
|
|
87
124
|
}
|
|
125
|
+
|
|
88
126
|
&:focus:not(:active) {
|
|
89
127
|
border-width: 0.2rem;
|
|
90
128
|
border-color: var(--color-warning-item-base);
|
|
91
129
|
}
|
|
130
|
+
|
|
92
131
|
&:disabled {
|
|
93
132
|
background-color: var(--color-neutral-background-disabled);
|
|
94
133
|
border-color: var(--color-neutral-border);
|
|
@@ -103,13 +142,16 @@ const labelAccent = computed(() => (props.accent === 'info' ? 'neutral' : props.
|
|
|
103
142
|
&:hover {
|
|
104
143
|
border-color: var(--color-danger-item-hover);
|
|
105
144
|
}
|
|
145
|
+
|
|
106
146
|
&:active {
|
|
107
147
|
border-color: var(--color-danger-item-active);
|
|
108
148
|
}
|
|
149
|
+
|
|
109
150
|
&:focus:not(:active) {
|
|
110
151
|
border-width: 0.2rem;
|
|
111
152
|
border-color: var(--color-danger-item-base);
|
|
112
153
|
}
|
|
154
|
+
|
|
113
155
|
&:disabled {
|
|
114
156
|
background-color: var(--color-neutral-background-disabled);
|
|
115
157
|
border-color: var(--color-neutral-border);
|