feat(web-core/tab-item): update UiTabItem component to v7 (#10338)

This commit is contained in:
OlivierFL
2026-09-09 12:39:43 +02:00
committed by GitHub
parent 505ac6caf5
commit 5cf93b3c3c
25 changed files with 263 additions and 256 deletions

View File

@@ -3,6 +3,7 @@
## **next**
- [Host] Add possibility to reboot a host (PR [#10250](https://github.com/vatesfr/xen-orchestra/pull/10250))
- [Web-Core/TabItem] Update the component to remove uppercase for better readability (PR [#10338](https://github.com/vatesfr/xen-orchestra/pull/10338))
## **0.25.0** (2026-08-31)

View File

@@ -1,18 +1,18 @@
<template>
<RouterLink v-slot="{ isActive, href }" :to custom>
<TabItem
<UiTabItem
:active="isActive"
:disabled="isDisabled"
:href="isDisabled ? undefined : href"
:tag="isDisabled ? undefined : 'a'"
>
<slot />
</TabItem>
</UiTabItem>
</RouterLink>
</template>
<script lang="ts" setup>
import TabItem from '@core/components/tab/TabItem.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useDisabled } from '@core/composables/disabled.composable.ts'
import type { RouteLocationRaw } from 'vue-router'

View File

@@ -1,7 +1,7 @@
<template>
<TabList>
<TabItem v-bind="tab(TAB.PROPS, propParams)">Props</TabItem>
<TabItem class="event-tab" v-bind="tab(TAB.EVENTS, eventParams)">
<UiTabItem v-bind="tab(TAB.PROPS, propParams)">Props</UiTabItem>
<UiTabItem class="event-tab" v-bind="tab(TAB.EVENTS, eventParams)">
Events
<UiCounter
v-if="unreadEventsCount > 0"
@@ -10,15 +10,15 @@
variant="primary"
size="small"
/>
</TabItem>
<TabItem v-bind="tab(TAB.SLOTS, slotParams)">Slots</TabItem>
<TabItem v-bind="tab(TAB.SETTINGS, settingParams)">Settings</TabItem>
</UiTabItem>
<UiTabItem v-bind="tab(TAB.SLOTS, slotParams)">Slots</UiTabItem>
<UiTabItem v-bind="tab(TAB.SETTINGS, settingParams)">Settings</UiTabItem>
<MenuList placement="bottom">
<template #trigger="{ open, isOpen }">
<TabItem :active="isOpen" :disabled="presets === undefined" class="preset-tab" @click="open">
<UiTabItem :active="isOpen" :disabled="presets === undefined" class="preset-tab" @click="open">
<VtsIcon name="fa:sliders" size="medium" />
Presets
</TabItem>
</UiTabItem>
</template>
<MenuItem v-for="(preset, label) in presets" :key="label" @click="applyPreset(preset)">
{{ label }}
@@ -91,12 +91,12 @@ import {
import VtsIcon from '@core/components/icon/VtsIcon.vue'
import MenuItem from '@core/components/menu/MenuItem.vue'
import MenuList from '@core/components/menu/MenuList.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiButton from '@core/components/ui/button/UiButton.vue'
import UiCard from '@core/components/ui/card/UiCard.vue'
import UiCardTitle from '@core/components/ui/card-title/UiCardTitle.vue'
import UiCounter from '@core/components/ui/counter/UiCounter.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import 'highlight.js/styles/github-dark.css'
import { uniqueId, upperFirst } from 'lodash-es'
import { computed, onBeforeMount, reactive, ref, watch, watchEffect } from 'vue'

View File

@@ -26,7 +26,7 @@
<script lang="ts" setup>
import RouterTab from '@/components/RouterTab.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import { useI18n } from 'vue-i18n'
defineProps<{

View File

@@ -33,7 +33,7 @@
<script lang="ts" setup>
import RouterTab from '@/components/RouterTab.vue'
import { usePoolStore } from '@/stores/xen-api/pool.store.ts'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()

View File

@@ -29,7 +29,7 @@
<script lang="ts" setup>
import RouterTab from '@/components/RouterTab.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import { useI18n } from 'vue-i18n'
defineProps<{

View File

@@ -492,16 +492,9 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/story/web-core/tab/tab-item': RouteRecordInfo<
'/story/web-core/tab/tab-item',
'/story/web-core/tab/tab-item',
Record<never, never>,
Record<never, never>,
| never
>,
'/story/web-core/tab/tab-list': RouteRecordInfo<
'/story/web-core/tab/tab-list',
'/story/web-core/tab/tab-list',
'/story/web-core/tab-list/tab-list': RouteRecordInfo<
'/story/web-core/tab-list/tab-list',
'/story/web-core/tab-list/tab-list',
Record<never, never>,
Record<never, never>,
| never
@@ -877,6 +870,13 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/story/web-core/ui/tab-item/ui-tab-item': RouteRecordInfo<
'/story/web-core/ui/tab-item/ui-tab-item',
'/story/web-core/ui/tab-item/ui-tab-item',
Record<never, never>,
Record<never, never>,
| never
>,
'/story/web-core/ui/table-actions/ui-table-actions': RouteRecordInfo<
'/story/web-core/ui/table-actions/ui-table-actions',
'/story/web-core/ui/table-actions/ui-table-actions',
@@ -1472,15 +1472,9 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/stories/web-core/tab/tab-item.story.vue': {
'src/stories/web-core/tab-list/tab-list.story.vue': {
routes:
| '/story/web-core/tab/tab-item'
views:
| never
}
'src/stories/web-core/tab/tab-list.story.vue': {
routes:
| '/story/web-core/tab/tab-list'
| '/story/web-core/tab-list/tab-list'
views:
| never
}
@@ -1802,6 +1796,12 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/stories/web-core/ui/tab-item/ui-tab-item.story.vue': {
routes:
| '/story/web-core/ui/tab-item/ui-tab-item'
views:
| never
}
'src/stories/web-core/ui/table-actions/ui-table-actions.story.vue': {
routes:
| '/story/web-core/ui/table-actions/ui-table-actions'

View File

@@ -1,12 +1,12 @@
<template>
<ComponentStory
v-slot="{ properties }"
:params="[prop('disabled').bool().widget(), slot().help('Contains <RouterTab> or <TabItem>')]"
:params="[prop('disabled').bool().widget(), slot().help('Contains <RouterTab> or <UiTabItem>')]"
>
<TabList v-bind="properties">
<TabItem>Foo</TabItem>
<TabItem>Bar</TabItem>
<TabItem>Baz</TabItem>
<UiTabItem>Foo</UiTabItem>
<UiTabItem>Bar</UiTabItem>
<UiTabItem>Baz</UiTabItem>
</TabList>
</ComponentStory>
</template>
@@ -14,6 +14,6 @@
<script lang="ts" setup>
import ComponentStory from '@/components/component-story/ComponentStory.vue'
import { prop, slot } from '@/libs/story/story-param.ts'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
</script>

View File

@@ -19,5 +19,5 @@ import ComponentStory from '@/components/component-story/ComponentStory.vue'
import RouterTab from '@/components/RouterTab.vue'
import { prop, setting, slot } from '@/libs/story/story-param.ts'
import { text } from '@/libs/story/story-widget.ts'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
</script>

View File

@@ -4,17 +4,18 @@
:params="[
prop('disabled').bool().widget().ctx(),
prop('active').bool().widget(),
prop('tag').str().default('span'),
prop('tag').str().default('span').widget(),
prop('href').str().widget(),
slot(),
setting('label').widget(text()).preset('Foobar'),
setting('counter').widget(text()),
]"
>
<TabList>
<TabItem v-bind="properties">
<UiTabItem v-bind="properties">
{{ settings.label }}
<UiCounter v-if="settings.counter" :value="settings.counter" accent="info" variant="primary" size="small" />
</TabItem>
</UiTabItem>
</TabList>
</ComponentStory>
</template>
@@ -23,7 +24,7 @@
import ComponentStory from '@/components/component-story/ComponentStory.vue'
import { prop, setting, slot } from '@/libs/story/story-param.ts'
import { text } from '@/libs/story/story-widget.ts'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiCounter from '@core/components/ui/counter/UiCounter.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
</script>

View File

@@ -1,98 +0,0 @@
<!-- v1.0 -->
<template>
<component :is="tag" :class="classNames" class="tab-item">
<slot />
</component>
</template>
<script lang="ts" setup>
import { useDisabled } from '@core/composables/disabled.composable.ts'
import { useUiStore } from '@core/stores/ui.store.ts'
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
disabled?: boolean
active?: boolean
tag?: string
}>(),
{ tag: 'span' }
)
const uiStore = useUiStore()
const isDisabled = useDisabled(() => props.disabled)
const classNames = computed(() => {
return [
uiStore.isSmall ? 'typo-caption-small' : 'typo-caption',
{
disabled: isDisabled.value,
active: props.active,
},
]
})
</script>
<style lang="postcss" scoped>
/* COLOR VARIANTS */
.tab-item {
& {
--color: var(--color-neutral-txt-primary);
--border-color: transparent;
--background-color: transparent;
}
&:is(:hover, .hover, :focus-visible) {
--color: var(--color-neutral-txt-primary);
--border-color: var(--color-brand-item-hover);
--background-color: var(--color-brand-background-hover);
}
&:is(:active, .pressed) {
--color: var(--color-neutral-txt-primary);
--border-color: var(--color-brand-item-active);
--background-color: var(--color-brand-background-active);
}
&:is(.active, .selected) {
--color: var(--color-neutral-txt-primary);
--border-color: var(--color-brand-item-base);
--background-color: var(--color-brand-background-selected);
}
&:is(:disabled, .disabled) {
--color: var(--color-neutral-txt-secondary);
--border-color: transparent;
--background-color: transparent;
}
}
/* SIZE VARIANTS */
.tab-item {
&.typo-caption-small {
--spacing: 0.8rem;
}
&.typo-caption {
--spacing: 1.6rem;
}
}
/* IMPLEMENTATION */
.tab-item {
display: flex;
align-items: center;
gap: var(--spacing);
padding: var(--spacing);
text-decoration: none;
color: var(--color);
background-color: var(--background-color);
border-bottom: 0.2rem solid var(--border-color);
cursor: pointer;
&.disabled {
pointer-events: none;
}
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<TabList :disabled="loading">
<TabItem v-bind="tabs.pending.bindings">
<UiTabItem v-bind="tabs.pending.bindings">
{{ t('in-progress') }}
<UiCounter
v-if="pendingCount !== undefined"
@@ -9,8 +9,8 @@
variant="primary"
size="small"
/>
</TabItem>
<TabItem v-bind="tabs.success.bindings">
</UiTabItem>
<UiTabItem v-bind="tabs.success.bindings">
{{ t('done') }}
<UiCounter
v-if="successCount !== undefined"
@@ -19,8 +19,8 @@
variant="primary"
size="small"
/>
</TabItem>
<TabItem v-bind="tabs.failure.bindings">
</UiTabItem>
<UiTabItem v-bind="tabs.failure.bindings">
{{ t('failed') }}
<UiCounter
v-if="failureCount !== undefined"
@@ -29,11 +29,11 @@
variant="primary"
size="small"
/>
</TabItem>
</UiTabItem>
<VtsDivider type="tab" />
<TabItem v-bind="tabs.all.bindings">
<UiTabItem v-bind="tabs.all.bindings">
{{ t('all') }}
</TabItem>
</UiTabItem>
<!--
TODO
<UiButton :right-icon="faAngleRight" class="see-all" level="tertiary" size="extra-small">
@@ -45,9 +45,9 @@
<script lang="ts" setup>
import VtsDivider from '@core/components/divider/VtsDivider.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiCounter from '@core/components/ui/counter/UiCounter.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useTabList } from '@core/composables/tab-list.composable.ts'
import type { TaskStatus } from '@core/types/task.type.ts'
import { useI18n } from 'vue-i18n'

View File

@@ -0,0 +1,102 @@
<!-- v7 -->
<template>
<component :is="resolvedTag" :class="className" class="ui-tab-item" :href="resolvedHref">
<slot />
</component>
</template>
<script lang="ts" setup>
import { useDisabled } from '@core/composables/disabled.composable.ts'
import { useUiStore } from '@core/stores/ui.store.ts'
import { computed } from 'vue'
const {
tag: rawTag = 'span',
disabled,
active,
href: rawHref,
} = defineProps<{
disabled?: boolean
active?: boolean
tag?: string
href?: string
}>()
const uiStore = useUiStore()
const isDisabled = useDisabled(() => disabled)
const resolvedTag = computed(() => {
if (isDisabled.value || (rawTag === 'a' && !rawHref)) {
return 'span'
}
return rawTag
})
const resolvedHref = computed(() => (resolvedTag.value === 'a' ? rawHref : undefined))
const className = computed(() => {
return [
uiStore.isSmall ? 'typo-h6' : 'typo-h5',
{
disabled: isDisabled.value,
active,
},
]
})
</script>
<style lang="postcss" scoped>
.ui-tab-item {
display: flex;
align-items: center;
gap: 1.6rem;
padding: 1.6rem;
text-decoration: none;
cursor: pointer;
color: var(--color-neutral-txt-primary);
background-color: transparent;
border-block-end: 0.2rem solid transparent;
&:is(:hover, .hover) {
background-color: var(--color-brand-background-hover);
border-block-end-color: var(--color-brand-item-hover);
}
&:focus-visible {
position: relative;
outline: none;
&::before {
content: '';
position: absolute;
inset: 0;
border: 0.2rem solid var(--color-brand-txt-base);
border-radius: 0.4rem;
}
}
&:is(:active, .pressed) {
background-color: var(--color-brand-background-active);
border-block-end-color: var(--color-brand-item-active);
}
&:is(.active, .selected) {
background-color: var(--color-brand-background-selected);
border-block-end-color: var(--color-brand-item-base);
}
&:is(:disabled, .disabled) {
pointer-events: none;
color: var(--color-neutral-txt-secondary);
background-color: transparent;
border-block-end-color: transparent;
}
@media (--small) {
gap: 0.8rem;
padding: 0.8rem;
}
}
</style>

View File

@@ -4,17 +4,17 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/admin/user-management/users' }" custom>
<TabItem :active="isExactActive" :href tag="a">
<UiTabItem :active="isExactActive" :href tag="a">
{{ t('users') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
<script lang="ts" setup>
import TabItem from '@xen-orchestra/web-core/components/tab/TabItem.vue'
import TabList from '@xen-orchestra/web-core/components/tab/TabList.vue'
import UiHeadBar from '@xen-orchestra/web-core/components/ui/head-bar/UiHeadBar.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()

View File

@@ -21,32 +21,32 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/backup/[id]/runs', params: { id: backupJob.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('runs') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink
v-slot="{ isActive, href }"
:to="{ name: '/backup/[id]/configuration', params: { id: backupJob.id } }"
custom
>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('configuration') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink
v-slot="{ isActive, href }"
:to="{ name: '/backup/[id]/backed-up-vms', params: { id: backupJob.id } }"
custom
>
<TabItem :active="isActive" :href tag="a" :disabled="backupJob.type !== 'backup'">
<UiTabItem :active="isActive" :href tag="a" :disabled="backupJob.type !== 'backup'">
{{ t('backed-up-vms') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/backup/[id]/targets', params: { id: backupJob.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('backup-targets') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -56,11 +56,11 @@ import type { FrontAnyXoBackupJob } from '@/modules/backup/remote-resources/use-
import { XOA_NAME } from '@/shared/constants.ts'
import { useXoRoutes } from '@/shared/remote-resources/use-xo-routes.ts'
import VtsIcon from '@core/components/icon/VtsIcon.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiBreadcrumb from '@core/components/ui/breadcrumb/UiBreadcrumb.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useUiStore } from '@core/stores/ui.store.ts'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

View File

@@ -46,44 +46,44 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/dashboard', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('dashboard') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/console', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('console') }}
</TabItem>
</UiTabItem>
</RouterLink>
<TabItem>
<UiTabItem>
<UiLink :href="xo5HostStatsHref" size="medium">
{{ t('stats') }}
</UiLink>
</TabItem>
</UiTabItem>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/system', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('system') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/networks', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('network') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/storage', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('storage') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/tasks', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('tasks') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/host/[id]/vms', params: { id: host.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('vms') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -97,12 +97,12 @@ import { useXoRoutes } from '@/shared/remote-resources/use-xo-routes.ts'
import VtsIcon from '@core/components/icon/VtsIcon.vue'
import MenuList from '@core/components/menu/MenuList.vue'
import VtsObjectIcon from '@core/components/object-icon/VtsObjectIcon.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
import UiDropdownButton from '@core/components/ui/dropdown-button/UiDropdownButton.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { vTooltip } from '@core/directives/tooltip.directive.ts'
import { useUiStore } from '@core/stores/ui.store.ts'
import { toLower } from 'lodash-es'

View File

@@ -2,7 +2,7 @@
<VtsLayoutSidebar :side class="app-navigation-sidebar">
<template #header>
<TabList class="sidebar-tabs">
<TabItem
<UiTabItem
:active="activeSidebarPanel === SIDEBAR_PANEL.TREEVIEW"
tag="button"
type="button"
@@ -10,8 +10,8 @@
@click="activeSidebarPanel = SIDEBAR_PANEL.TREEVIEW"
>
{{ t('treeview') }}
</TabItem>
<TabItem
</UiTabItem>
<UiTabItem
:active="activeSidebarPanel === SIDEBAR_PANEL.ADMINISTRATION"
tag="button"
type="button"
@@ -19,7 +19,7 @@
@click="activeSidebarPanel = SIDEBAR_PANEL.ADMINISTRATION"
>
{{ t('administration') }}
</TabItem>
</UiTabItem>
</TabList>
</template>
<template v-if="activeSidebarPanel === SIDEBAR_PANEL.TREEVIEW" #subheader>
@@ -48,10 +48,10 @@ import SiteTreeList from '@/modules/treeview/components/SiteTreeList.vue'
import type { SidebarSide } from '@core/packages/sidebar'
import VtsLayoutSidebar from '@core/components/layout/VtsLayoutSidebar.vue'
import VtsStateHero from '@core/components/state-hero/VtsStateHero.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import VtsTreeList from '@core/components/tree/VtsTreeList.vue'
import VtsTreeLoadingItem from '@core/components/tree/VtsTreeLoadingItem.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useSseStore } from '@core/packages/remote-resource/sse.store.ts'
import { watchImmediate } from '@vueuse/core'
import { storeToRefs } from 'pinia'

View File

@@ -9,49 +9,49 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/dashboard', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('dashboard') }}
</TabItem>
</UiTabItem>
</RouterLink>
<TabItem>
<UiTabItem>
<UiLink :href="xo5PoolStatsHref" size="medium">
{{ t('stats') }}
</UiLink>
</TabItem>
</UiTabItem>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/system', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('system') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/networks', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('network') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/traffic-rules', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('traffic-rules') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/storage', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('storage') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/tasks', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('tasks') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/hosts', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('hosts') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/pool/[id]/vms', params: { id: pool.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('vms') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -59,10 +59,10 @@
<script lang="ts" setup>
import type { FrontXoPool } from '@/modules/pool/remote-resources/use-xo-pool-collection.ts'
import { useXoRoutes } from '@/shared/remote-resources/use-xo-routes.ts'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

View File

@@ -9,38 +9,38 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/dashboard' }" custom>
<TabItem :active="isExactActive" :href tag="a">
<UiTabItem :active="isExactActive" :href tag="a">
{{ t('dashboard') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/backups' }" custom>
<TabItem :active="isExactActive" :href tag="a">
<UiTabItem :active="isExactActive" :href tag="a">
{{ t('backups') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/tasks' }" custom>
<TabItem :active="isExactActive" :href tag="a">
<UiTabItem :active="isExactActive" :href tag="a">
{{ t('tasks') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/pools' }" custom>
<TabItem :active="isExactActive" :href tag="a">{{ t('pools') }}</TabItem>
<UiTabItem :active="isExactActive" :href tag="a">{{ t('pools') }}</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/hosts' }" custom>
<TabItem :active="isExactActive" :href tag="a">{{ t('hosts') }}</TabItem>
<UiTabItem :active="isExactActive" :href tag="a">{{ t('hosts') }}</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isExactActive, href }" :to="{ name: '/(site)/vms' }" custom>
<TabItem :active="isExactActive" :href tag="a">{{ t('vms') }}</TabItem>
<UiTabItem :active="isExactActive" :href tag="a">{{ t('vms') }}</UiTabItem>
</RouterLink>
</TabList>
</template>
<script lang="ts" setup>
import { XOA_NAME } from '@/shared/constants.ts'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()

View File

@@ -15,18 +15,18 @@
:to="{ name: '/sr/[id]/general', params: { id: sr.id }, query: scopeQuery }"
custom
>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('general') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink
v-slot="{ isActive, href }"
:to="{ name: '/sr/[id]/hosts', params: { id: sr.id }, query: scopeQuery }"
custom
>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('hosts') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -41,9 +41,9 @@ import { toSrScopeQuery } from '@/modules/storage-repository/utils/sr-scope.util
import type { SrScope } from '@core/types/storage-repository.type.ts'
import VtsIcon from '@core/components/icon/VtsIcon.vue'
import VtsObjectIcon from '@core/components/object-icon/VtsObjectIcon.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { vTooltip } from '@core/directives/tooltip.directive.ts'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

View File

@@ -19,14 +19,14 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vif/[id]/general', params: { id: vif.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('general') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vif/[id]/traffic-rules', params: { id: vif.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('traffic-rules') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -37,11 +37,11 @@ import type { FrontXoVif } from '@/modules/vif/remote-resources/use-xo-vif-colle
import { useXoVmCollection } from '@/modules/vm/remote-resources/use-xo-vm-collection.ts'
import VtsIcon from '@core/components/icon/VtsIcon.vue'
import VtsObjectIcon from '@core/components/object-icon/VtsObjectIcon.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiBreadcrumb from '@core/components/ui/breadcrumb/UiBreadcrumb.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { useUiStore } from '@core/stores/ui.store.ts'
import { toLower } from 'lodash-es'
import { computed } from 'vue'

View File

@@ -36,7 +36,7 @@ async function mountHeader(vm: FrontXoVm = createVm({ id: 'vm-42' as FrontXoVm['
}
function findTabs(wrapper: Awaited<ReturnType<typeof mountHeader>>) {
return wrapper.findAll('.tab-item')
return wrapper.findAll('.ui-tab-item')
}
/**

View File

@@ -39,49 +39,49 @@
</UiHeadBar>
<TabList>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/dashboard', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('dashboard') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/console', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('console') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/backups', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('backups') }}
</TabItem>
</UiTabItem>
</RouterLink>
<TabItem>
<UiTabItem>
<UiLink :href="xo5VmStatsHref" size="medium">
{{ t('stats') }}
</UiLink>
</TabItem>
</UiTabItem>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/system', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('system') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/networks', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('network') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/vdis', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('vdis') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: `/vm/[id]/snapshots`, params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('snapshots') }}
</TabItem>
</UiTabItem>
</RouterLink>
<RouterLink v-slot="{ isActive, href }" :to="{ name: '/vm/[id]/tasks', params: { id: vm.id } }" custom>
<TabItem :active="isActive" :href tag="a">
<UiTabItem :active="isActive" :href tag="a">
{{ t('tasks') }}
</TabItem>
</UiTabItem>
</RouterLink>
</TabList>
</template>
@@ -94,12 +94,12 @@ import type { FrontXoVm } from '@/modules/vm/remote-resources/use-xo-vm-collecti
import { useXoRoutes } from '@/shared/remote-resources/use-xo-routes.ts'
import MenuList from '@core/components/menu/MenuList.vue'
import VtsObjectIcon from '@core/components/object-icon/VtsObjectIcon.vue'
import TabItem from '@core/components/tab/TabItem.vue'
import TabList from '@core/components/tab/TabList.vue'
import TabList from '@core/components/tab-list/TabList.vue'
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
import UiDropdownButton from '@core/components/ui/dropdown-button/UiDropdownButton.vue'
import UiHeadBar from '@core/components/ui/head-bar/UiHeadBar.vue'
import UiLink from '@core/components/ui/link/UiLink.vue'
import UiTabItem from '@core/components/ui/tab-item/UiTabItem.vue'
import { vTooltip } from '@core/directives/tooltip.directive.ts'
import { toLower } from 'lodash-es'
import { computed } from 'vue'

View File

@@ -16,6 +16,7 @@
- [XO6/SR] Add dedicated Storage Repository page hosts sidepanel (PR [#10140](https://github.com/vatesfr/xen-orchestra/pull/10140))
- [Rolling pool update/reboot] A pool can now skip the phase which brings the VMs back to the host they were running on, which halves the migrations of the run (PR [#10295](https://github.com/vatesfr/xen-orchestra/pull/10295))
- [XO5/Backups] Open the backup job edition form in the same tab when editing a backup job from the VM page (PR [#10342](https://github.com/vatesfr/xen-orchestra/pull/10342))
- [Web-Core/TabItem] Update the component to remove uppercase for better readability (PR [#10338](https://github.com/vatesfr/xen-orchestra/pull/10338))
### Bug fixes