fix: move impersonation banner inside layout content flow

Replace position:fixed VSystemBar + fragile :deep() CSS overrides
with a normal-flow div inside the Vuexy content area. The banner
renders in VerticalNavLayout's default slot (layout-page-content)
so it sits naturally below the navbar without fighting the layout
system. Sidebar and navbar are no longer affected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 03:17:13 +02:00
parent dc886fed46
commit 0221e7f6d3
2 changed files with 52 additions and 69 deletions

View File

@@ -62,12 +62,9 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<VSystemBar <div
v-if="impersonationStore.isImpersonating" v-if="impersonationStore.isImpersonating"
color="warning" class="impersonation-banner d-flex align-center px-4"
height="48"
style="z-index: 9999; position: fixed; top: 0; left: 0; right: 0;"
class="px-4"
> >
<VIcon <VIcon
icon="tabler-user-search" icon="tabler-user-search"
@@ -93,15 +90,20 @@ onUnmounted(() => {
variant="elevated" variant="elevated"
color="white" color="white"
class="text-warning" class="text-warning"
prepend-icon="tabler-arrow-back"
:loading="isStopping" :loading="isStopping"
@click="handleStop" @click="handleStop"
> >
<VIcon
icon="tabler-arrow-back"
size="16"
class="me-1"
/>
Terug naar admin Terug naar admin
</VBtn> </VBtn>
</VSystemBar> </div>
</template> </template>
<style scoped>
.impersonation-banner {
background: rgb(var(--v-theme-warning));
color: rgb(var(--v-theme-on-warning));
block-size: 48px;
inline-size: 100%;
}
</style>

View File

@@ -49,70 +49,51 @@ import { VerticalNavLayout } from '@layouts'
</script> </script>
<template> <template>
<div :class="{ 'impersonation-active': impersonationStore.isImpersonating }"> <VerticalNavLayout :nav-items="navItems">
<VerticalNavLayout :nav-items="navItems"> <!-- 👉 Organisation switcher -->
<!-- 👉 Organisation switcher --> <template #before-vertical-nav-items>
<template #before-vertical-nav-items> <OrganisationSwitcher />
<OrganisationSwitcher /> <div class="vertical-nav-items-shadow" />
<div class="vertical-nav-items-shadow" /> </template>
</template>
<!-- 👉 navbar (match Vuexy full-version: search + actions; search flex-grows) --> <!-- 👉 navbar (match Vuexy full-version: search + actions; search flex-grows) -->
<template #navbar="{ toggleVerticalOverlayNavActive }"> <template #navbar="{ toggleVerticalOverlayNavActive }">
<div <div
class="d-flex h-100 align-center w-100" class="d-flex h-100 align-center w-100"
style="min-inline-size: 0;" style="min-inline-size: 0;"
>
<IconBtn
id="vertical-nav-toggle-btn"
class="ms-n3 d-lg-none flex-shrink-0"
@click="toggleVerticalOverlayNavActive(true)"
> >
<IconBtn <VIcon
id="vertical-nav-toggle-btn" size="26"
class="ms-n3 d-lg-none flex-shrink-0" icon="tabler-menu-2"
@click="toggleVerticalOverlayNavActive(true)" />
> </IconBtn>
<VIcon
size="26"
icon="tabler-menu-2"
/>
</IconBtn>
<NavSearchBar class="flex-grow-1 ms-lg-n3 min-w-0" /> <NavSearchBar class="flex-grow-1 ms-lg-n3 min-w-0" />
<NavbarThemeSwitcher class="flex-shrink-0 me-2" /> <NavbarThemeSwitcher class="flex-shrink-0 me-2" />
<NavbarShortcuts class="flex-shrink-0" /> <NavbarShortcuts class="flex-shrink-0" />
<NavBarNotifications class="flex-shrink-0 me-1" /> <NavBarNotifications class="flex-shrink-0 me-1" />
<UserProfile class="flex-shrink-0" /> <UserProfile class="flex-shrink-0" />
</div> </div>
</template> </template>
<!-- 👉 Impersonation Banner --> <!-- 👉 Impersonation Banner -->
<ImpersonationBanner /> <ImpersonationBanner />
<!-- 👉 Pages --> <!-- 👉 Pages -->
<slot /> <slot />
<!-- 👉 Footer --> <!-- 👉 Footer -->
<template #footer> <template #footer>
<Footer /> <Footer />
</template> </template>
<!-- 👉 Customizer --> <!-- 👉 Customizer -->
<!-- <TheCustomizer /> --> <!-- <TheCustomizer /> -->
</VerticalNavLayout> </VerticalNavLayout>
</div>
</template> </template>
<style scoped>
/*
* Push sidebar, navbar, and content below the fixed 48px impersonation banner.
* !important is needed because VerticalNavLayout's unscoped styles are injected
* after this component's scoped styles (child renders after parent), so equal-
* specificity rules from Vuexy win without it.
*/
.impersonation-active :deep(.layout-vertical-nav) {
inset-block-start: 48px !important;
block-size: calc(100% - 48px) !important;
}
.impersonation-active :deep(.layout-navbar) {
inset-block-start: 48px !important;
}
</style>