mirror of https://github.com/halo-dev/halo
perf: improve the style of the scrollbar (#3587)
#### What type of PR is this? /kind improvement /area console /milestone 2.4.x #### What this PR does / why we need it: 优化页面滚动条的样式,引入 [OverlayScrollbars](https://github.com/KingSora/OverlayScrollbars) 实现类似于 macOS 下的仅滚动时显示滚动条的特性,并保证在各个浏览器的表现一致。  #### Special notes for your reviewer: 测试方式:使用不同的浏览器测试滚动条是否可以自动隐藏以及样式是否一致即可。 #### Does this PR introduce a user-facing change? ```release-note 优化 Console 端页面滚动条的样式。 ```pull/3568/head
parent
2b73a56b6c
commit
403702021c
|
@ -73,6 +73,8 @@
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"lodash.sortby": "^4.7.0",
|
"lodash.sortby": "^4.7.0",
|
||||||
|
"overlayscrollbars": "^2.1.0",
|
||||||
|
"overlayscrollbars-vue": "^0.5.1",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"pinia": "^2.0.26",
|
"pinia": "^2.0.26",
|
||||||
"pretty-bytes": "^6.0.0",
|
"pretty-bytes": "^6.0.0",
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, nextTick, ref, watch } from "vue";
|
import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||||
import { IconClose } from "../../icons/icons";
|
import { IconClose } from "../../icons/icons";
|
||||||
|
import type { UseOverlayScrollbarsParams } from "overlayscrollbars-vue";
|
||||||
|
import { useOverlayScrollbars } from "overlayscrollbars-vue";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -77,6 +79,29 @@ watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// body scroll
|
||||||
|
const modalBody = ref(null);
|
||||||
|
const reactiveParams = reactive<UseOverlayScrollbarsParams>({
|
||||||
|
options: {
|
||||||
|
scrollbars: {
|
||||||
|
autoHide: "scroll",
|
||||||
|
autoHideDelay: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defer: true,
|
||||||
|
});
|
||||||
|
const [initialize, instance] = useOverlayScrollbars(reactiveParams);
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(value) => {
|
||||||
|
if (value) {
|
||||||
|
if (modalBody.value) initialize({ target: modalBody.value });
|
||||||
|
} else {
|
||||||
|
instance()?.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Teleport :disabled="!mountToBody" to="body">
|
<Teleport :disabled="!mountToBody" to="body">
|
||||||
|
@ -134,7 +159,7 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div :class="bodyClass" class="modal-body">
|
<div ref="modalBody" :class="bodyClass" class="modal-body">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$slots.footer" class="modal-footer">
|
<div v-if="$slots.footer" class="modal-footer">
|
||||||
|
@ -222,7 +247,7 @@ watch(
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body {
|
.modal-body {
|
||||||
@apply overflow-y-auto
|
@apply overflow-y-hidden
|
||||||
overflow-x-hidden
|
overflow-x-hidden
|
||||||
flex-1;
|
flex-1;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import "./styles/tailwind.css";
|
import "./styles/tailwind.css";
|
||||||
|
import "overlayscrollbars/overlayscrollbars.css";
|
||||||
|
|
||||||
export * from "./components";
|
export * from "./components";
|
||||||
export * from "./icons/icons";
|
export * from "./icons/icons";
|
||||||
|
|
|
@ -75,6 +75,8 @@ importers:
|
||||||
lodash.isequal: ^4.5.0
|
lodash.isequal: ^4.5.0
|
||||||
lodash.merge: ^4.6.2
|
lodash.merge: ^4.6.2
|
||||||
lodash.sortby: ^4.7.0
|
lodash.sortby: ^4.7.0
|
||||||
|
overlayscrollbars: ^2.1.0
|
||||||
|
overlayscrollbars-vue: ^0.5.1
|
||||||
path-browserify: ^1.0.1
|
path-browserify: ^1.0.1
|
||||||
pinia: ^2.0.26
|
pinia: ^2.0.26
|
||||||
postcss: ^8.4.19
|
postcss: ^8.4.19
|
||||||
|
@ -145,6 +147,8 @@ importers:
|
||||||
lodash.isequal: 4.5.0
|
lodash.isequal: 4.5.0
|
||||||
lodash.merge: 4.6.2
|
lodash.merge: 4.6.2
|
||||||
lodash.sortby: 4.7.0
|
lodash.sortby: 4.7.0
|
||||||
|
overlayscrollbars: 2.1.0
|
||||||
|
overlayscrollbars-vue: 0.5.1_qvtrscepjgkfzkdt53swvamjn4
|
||||||
path-browserify: 1.0.1
|
path-browserify: 1.0.1
|
||||||
pinia: 2.0.26_e7lp6ggkpgyi5vqd44m2kxvk6i
|
pinia: 2.0.26_e7lp6ggkpgyi5vqd44m2kxvk6i
|
||||||
pretty-bytes: 6.0.0
|
pretty-bytes: 6.0.0
|
||||||
|
@ -8671,6 +8675,20 @@ packages:
|
||||||
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
|
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/overlayscrollbars-vue/0.5.1_qvtrscepjgkfzkdt53swvamjn4:
|
||||||
|
resolution: {integrity: sha512-hYoS7qm1xq4Kv7GpCTpo1YSUmgSXF2z9OcWbwGloGO8ZXefhADwDlYy6e35r2g5Gh04slZPsyQIqEXA/CptFMA==}
|
||||||
|
peerDependencies:
|
||||||
|
overlayscrollbars: ^2.0.0
|
||||||
|
vue: ^3.2.25
|
||||||
|
dependencies:
|
||||||
|
overlayscrollbars: 2.1.0
|
||||||
|
vue: 3.2.45
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/overlayscrollbars/2.1.0:
|
||||||
|
resolution: {integrity: sha512-L6p4o4aWse5pDstRnJjZaos+al+bkuAgzGIlWwlsxRSgW6+7Kvrp+kAzlWoTZ1bgB4CJj+8u5bjdq8XHEhWjrw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/p-filter/2.1.0:
|
/p-filter/2.1.0:
|
||||||
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
|
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { RouterView, useRoute } from "vue-router";
|
import { RouterView, useRoute } from "vue-router";
|
||||||
import { computed, watch, ref } from "vue";
|
import { computed, watch, ref, reactive, onMounted } from "vue";
|
||||||
import { useTitle } from "@vueuse/core";
|
import { useTitle } from "@vueuse/core";
|
||||||
import { useFavicon } from "@vueuse/core";
|
import { useFavicon } from "@vueuse/core";
|
||||||
import { useSystemConfigMapStore } from "./stores/system-configmap";
|
import { useSystemConfigMapStore } from "./stores/system-configmap";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import {
|
||||||
|
useOverlayScrollbars,
|
||||||
|
type UseOverlayScrollbarsParams,
|
||||||
|
} from "overlayscrollbars-vue";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -61,6 +65,22 @@ const favicon = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
useFavicon(favicon);
|
useFavicon(favicon);
|
||||||
|
|
||||||
|
// body scroll
|
||||||
|
const body = document.querySelector("body");
|
||||||
|
const reactiveParams = reactive<UseOverlayScrollbarsParams>({
|
||||||
|
options: {
|
||||||
|
scrollbars: {
|
||||||
|
autoHide: "scroll",
|
||||||
|
autoHideDelay: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defer: true,
|
||||||
|
});
|
||||||
|
const [initialize] = useOverlayScrollbars(reactiveParams);
|
||||||
|
onMounted(() => {
|
||||||
|
if (body) initialize({ target: body });
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -69,7 +89,6 @@ useFavicon(favicon);
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
body {
|
body {
|
||||||
overflow-y: overlay;
|
|
||||||
background: #eff4f9;
|
background: #eff4f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,27 +98,11 @@ body {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-track-piece {
|
.v-popper__popper {
|
||||||
background-color: #f8f8f8;
|
outline: none;
|
||||||
-webkit-border-radius: 2em;
|
|
||||||
-moz-border-radius: 2em;
|
|
||||||
border-radius: 2em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
.v-popper--theme-tooltip {
|
||||||
width: 8px;
|
pointer-events: none;
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #ddd;
|
|
||||||
background-clip: padding-box;
|
|
||||||
-webkit-border-radius: 2em;
|
|
||||||
-moz-border-radius: 2em;
|
|
||||||
border-radius: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb:hover {
|
|
||||||
background-color: #bbb;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -111,6 +111,7 @@ import type { queueAsPromised } from "fastq";
|
||||||
import type { Attachment } from "@halo-dev/api-client";
|
import type { Attachment } from "@halo-dev/api-client";
|
||||||
import { useFetchAttachmentPolicy } from "@/modules/contents/attachments/composables/use-attachment-policy";
|
import { useFetchAttachmentPolicy } from "@/modules/contents/attachments/composables/use-attachment-policy";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -548,7 +549,12 @@ watch(
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<div class="h-full w-72 overflow-y-auto border-l bg-white">
|
<OverlayScrollbarsComponent
|
||||||
|
element="div"
|
||||||
|
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||||
|
class="h-full w-72 border-l bg-white"
|
||||||
|
defer
|
||||||
|
>
|
||||||
<VTabs v-model:active-id="extraActiveId" type="outline">
|
<VTabs v-model:active-id="extraActiveId" type="outline">
|
||||||
<VTabItem
|
<VTabItem
|
||||||
id="toc"
|
id="toc"
|
||||||
|
@ -733,7 +739,7 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</VTabItem>
|
</VTabItem>
|
||||||
</VTabs>
|
</VTabs>
|
||||||
</div>
|
</OverlayScrollbarsComponent>
|
||||||
</template>
|
</template>
|
||||||
</RichTextEditor>
|
</RichTextEditor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
useRouter,
|
useRouter,
|
||||||
type RouteRecordRaw,
|
type RouteRecordRaw,
|
||||||
} from "vue-router";
|
} from "vue-router";
|
||||||
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
import { nextTick, onMounted, onUnmounted, reactive, ref, watch } from "vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import GlobalSearchModal from "@/components/global-search/GlobalSearchModal.vue";
|
import GlobalSearchModal from "@/components/global-search/GlobalSearchModal.vue";
|
||||||
import LoginModal from "@/components/login/LoginModal.vue";
|
import LoginModal from "@/components/login/LoginModal.vue";
|
||||||
|
@ -31,6 +31,10 @@ import { rbacAnnotations } from "@/constants/annotations";
|
||||||
import { useScroll } from "@vueuse/core";
|
import { useScroll } from "@vueuse/core";
|
||||||
import { defineStore, storeToRefs } from "pinia";
|
import { defineStore, storeToRefs } from "pinia";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import {
|
||||||
|
useOverlayScrollbars,
|
||||||
|
type UseOverlayScrollbarsParams,
|
||||||
|
} from "overlayscrollbars-vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -209,6 +213,23 @@ onMounted(() => {
|
||||||
y.value = navbarScrollStore.y;
|
y.value = navbarScrollStore.y;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// aside scroll
|
||||||
|
const reactiveParams = reactive<UseOverlayScrollbarsParams>({
|
||||||
|
options: {
|
||||||
|
scrollbars: {
|
||||||
|
autoHide: "scroll",
|
||||||
|
autoHideDelay: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defer: true,
|
||||||
|
});
|
||||||
|
const [initialize] = useOverlayScrollbars(reactiveParams);
|
||||||
|
onMounted(() => {
|
||||||
|
if (navbarScroller.value) {
|
||||||
|
initialize({ target: navbarScroller.value });
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -227,7 +248,7 @@ onMounted(() => {
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div ref="navbarScroller" class="flex-1 overflow-y-auto">
|
<div ref="navbarScroller" class="flex-1 overflow-y-hidden">
|
||||||
<div class="px-3">
|
<div class="px-3">
|
||||||
<div
|
<div
|
||||||
class="flex cursor-pointer items-center rounded bg-gray-100 p-2 text-gray-400 transition-all hover:text-gray-900"
|
class="flex cursor-pointer items-center rounded bg-gray-100 p-2 text-gray-400 transition-all hover:text-gray-900"
|
||||||
|
@ -297,7 +318,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main class="content w-full overflow-y-auto pb-12 mb-safe md:pb-0">
|
<main class="content w-full pb-12 mb-safe md:pb-0">
|
||||||
<slot v-if="$slots.default" />
|
<slot v-if="$slots.default" />
|
||||||
<RouterView v-else />
|
<RouterView v-else />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { apiClient } from "@/utils/api-client";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
import { postLabels } from "@/constants/labels";
|
import { postLabels } from "@/constants/labels";
|
||||||
import { useQuery } from "@tanstack/vue-query";
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||||
|
|
||||||
const { data } = useQuery<ListedPost[]>({
|
const { data } = useQuery<ListedPost[]>({
|
||||||
queryKey: ["widget-recent-posts"],
|
queryKey: ["widget-recent-posts"],
|
||||||
|
@ -32,9 +33,15 @@ const { data } = useQuery<ListedPost[]>({
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard
|
<VCard
|
||||||
:body-class="['h-full', '!p-0', 'overflow-y-auto']"
|
:body-class="['h-full', '!p-0', '!overflow-auto']"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
:title="$t('core.dashboard.widgets.presets.recent_published.title')"
|
:title="$t('core.dashboard.widgets.presets.recent_published.title')"
|
||||||
|
>
|
||||||
|
<OverlayScrollbarsComponent
|
||||||
|
element="div"
|
||||||
|
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||||
|
class="h-full w-full"
|
||||||
|
defer
|
||||||
>
|
>
|
||||||
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
||||||
<li v-for="(post, index) in data" :key="index">
|
<li v-for="(post, index) in data" :key="index">
|
||||||
|
@ -92,5 +99,6 @@ const { data } = useQuery<ListedPost[]>({
|
||||||
</VEntity>
|
</VEntity>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</OverlayScrollbarsComponent>
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { useRouter } from "vue-router";
|
||||||
import ThemePreviewModal from "@/modules/interface/themes/components/preview/ThemePreviewModal.vue";
|
import ThemePreviewModal from "@/modules/interface/themes/components/preview/ThemePreviewModal.vue";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||||
|
|
||||||
interface Action {
|
interface Action {
|
||||||
icon: Component;
|
icon: Component;
|
||||||
|
@ -159,9 +160,16 @@ const actions: Action[] = [
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard
|
<VCard
|
||||||
:body-class="['h-full', 'overflow-y-auto', '@container']"
|
:body-class="['h-full', '@container', '!p-0', '!overflow-auto']"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
:title="$t('core.dashboard.widgets.presets.quicklink.title')"
|
:title="$t('core.dashboard.widgets.presets.quicklink.title')"
|
||||||
|
>
|
||||||
|
<OverlayScrollbarsComponent
|
||||||
|
element="div"
|
||||||
|
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||||
|
class="h-full w-full"
|
||||||
|
style="padding: 12px 16px"
|
||||||
|
defer
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-1 gap-2 overflow-hidden @sm:grid-cols-2 @md:grid-cols-3"
|
class="grid grid-cols-1 gap-2 overflow-hidden @sm:grid-cols-2 @md:grid-cols-3"
|
||||||
|
@ -193,6 +201,7 @@ const actions: Action[] = [
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</OverlayScrollbarsComponent>
|
||||||
</VCard>
|
</VCard>
|
||||||
<ThemePreviewModal
|
<ThemePreviewModal
|
||||||
v-model:visible="themePreviewVisible"
|
v-model:visible="themePreviewVisible"
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { computed, markRaw, ref, watch } from "vue";
|
import { computed, markRaw, ref, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||||
import { useQuery } from "@tanstack/vue-query";
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
@ -315,11 +316,13 @@ const iframeClasses = computed(() => {
|
||||||
leave-to-class="-translate-x-full"
|
leave-to-class="-translate-x-full"
|
||||||
appear
|
appear
|
||||||
>
|
>
|
||||||
<div
|
<OverlayScrollbarsComponent
|
||||||
v-if="themesVisible || settingsVisible"
|
v-if="themesVisible || settingsVisible"
|
||||||
class="relative h-full w-96 overflow-y-auto"
|
element="div"
|
||||||
|
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||||
|
class="relative h-full w-96"
|
||||||
:class="{ '!overflow-hidden': switching }"
|
:class="{ '!overflow-hidden': switching }"
|
||||||
style="overflow-y: overlay"
|
defer
|
||||||
>
|
>
|
||||||
<transition
|
<transition
|
||||||
enter-active-class="transform transition ease-in-out duration-300 delay-150"
|
enter-active-class="transform transition ease-in-out duration-300 delay-150"
|
||||||
|
@ -432,7 +435,7 @@ const iframeClasses = computed(() => {
|
||||||
</VButton>
|
</VButton>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</OverlayScrollbarsComponent>
|
||||||
</transition>
|
</transition>
|
||||||
<div
|
<div
|
||||||
class="flex h-full flex-1 items-center justify-center transition-all duration-300"
|
class="flex h-full flex-1 items-center justify-center transition-all duration-300"
|
||||||
|
|
|
@ -2,3 +2,4 @@ import "@halo-dev/richtext-editor/dist/style.css";
|
||||||
import "@halo-dev/components/dist/style.css";
|
import "@halo-dev/components/dist/style.css";
|
||||||
import "@/styles/tailwind.css";
|
import "@/styles/tailwind.css";
|
||||||
import "@/styles/index.css";
|
import "@/styles/index.css";
|
||||||
|
import "overlayscrollbars/overlayscrollbars.css";
|
||||||
|
|
Loading…
Reference in New Issue