perf: 重构并美化整体UI
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed} from 'vue';
|
||||
|
||||
import type { ContentCompactType } from '@easyflow-core/typings';
|
||||
import type {ContentCompactType} from '@easyflow-core/typings';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useLayoutContentStyle } from '@easyflow-core/composables';
|
||||
import { Slot } from '@easyflow-core/shadcn-ui';
|
||||
import {useLayoutContentStyle} from '@easyflow-core/composables';
|
||||
import {Slot} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
@@ -27,6 +26,10 @@ interface Props {
|
||||
const props = withDefaults(defineProps<Props>(), {});
|
||||
|
||||
const { contentElement, overlayStyle } = useLayoutContentStyle();
|
||||
const flowContinuationStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(ellipse 96% 34% at -4% -6%, hsl(var(--nav-flow-core) / 0.18) 0%, hsl(var(--nav-flow-core) / 0.08) 30%, transparent 62%), radial-gradient(ellipse 74% 24% at 20% 8%, hsl(var(--nav-ambient) / 0.2) 0%, transparent 64%), linear-gradient(128deg, hsl(var(--nav-flow-trace) / 0.1) 0%, hsl(var(--nav-flow-secondary) / 0.08) 12%, transparent 24%, transparent 48%, hsl(var(--nav-flow-core) / 0.05) 66%, transparent 88%), radial-gradient(ellipse 52% 18% at 50% 26%, hsl(var(--nav-flow-accent) / 0.05) 0%, transparent 72%)',
|
||||
};
|
||||
|
||||
const style = computed((): CSSProperties => {
|
||||
const {
|
||||
@@ -44,6 +47,9 @@ const style = computed((): CSSProperties => {
|
||||
: {};
|
||||
return {
|
||||
...compactStyle,
|
||||
backgroundColor: 'hsl(var(--surface-canvas) / 0.72)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface) / 0.72) 0%, hsl(var(--surface-canvas) / 0.92) 16%, hsl(var(--background) / 0.98) 100%)',
|
||||
flex: 1,
|
||||
padding: `${padding}px`,
|
||||
paddingBottom: `${paddingBottom}px`,
|
||||
@@ -55,14 +61,16 @@ const style = computed((): CSSProperties => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main
|
||||
ref="contentElement"
|
||||
:style="style"
|
||||
class="relative overflow-hidden bg-[radial-gradient(circle_at_top,hsl(var(--glass-tint))/0.34,transparent_40%),linear-gradient(180deg,hsl(var(--surface-canvas)),hsl(var(--background-deep)))]"
|
||||
>
|
||||
<main ref="contentElement" :style="style" class="relative overflow-hidden">
|
||||
<div
|
||||
:style="flowContinuationStyle"
|
||||
class="pointer-events-none absolute inset-0"
|
||||
></div>
|
||||
<Slot :style="overlayStyle">
|
||||
<slot name="overlay"></slot>
|
||||
</Slot>
|
||||
<slot></slot>
|
||||
<div class="relative z-[1] h-full">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import { computed, useSlots } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed, useSlots} from 'vue';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
@@ -47,11 +46,10 @@ const style = computed((): CSSProperties => {
|
||||
const right = !show || !fullWidth ? undefined : 0;
|
||||
|
||||
return {
|
||||
backgroundColor: 'hsl(var(--nav-surface) / 0.86)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface) / 0.96), hsl(var(--glass-tint) / 0.82))',
|
||||
backdropFilter: 'blur(var(--glass-blur)) saturate(160%)',
|
||||
boxShadow: 'var(--shadow-subtle)',
|
||||
backgroundColor: 'transparent',
|
||||
backgroundImage: 'none',
|
||||
backdropFilter: 'none',
|
||||
boxShadow: 'none',
|
||||
height: `${height}px`,
|
||||
marginTop: show ? 0 : `-${height}px`,
|
||||
right,
|
||||
@@ -63,10 +61,6 @@ const logoStyle = computed((): CSSProperties => {
|
||||
minWidth: `${props.isMobile ? 40 : props.sidebarWidth}px`,
|
||||
};
|
||||
});
|
||||
const ambientStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient) / 0.42) 0%, hsl(var(--nav-ambient) / 0.18) 22%, transparent 56%), radial-gradient(circle at 20% 0%, hsl(var(--nav-ambient-secondary) / 0.22) 0%, transparent 40%), linear-gradient(180deg, hsl(var(--nav-sheen) / 0.22), transparent 48%)',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -75,8 +69,6 @@ const ambientStyle: CSSProperties = {
|
||||
:style="style"
|
||||
class="relative top-0 flex w-full flex-[0_0_auto] items-center gap-1 overflow-x-hidden overflow-y-visible px-3 transition-[margin-top,background-color,box-shadow] duration-200"
|
||||
>
|
||||
<div :style="ambientStyle" class="pointer-events-none absolute inset-0"></div>
|
||||
|
||||
<div v-if="slots.logo" :style="logoStyle" class="relative z-10">
|
||||
<slot name="logo"></slot>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed, shallowRef, useSlots, watchEffect} from 'vue';
|
||||
|
||||
import { computed, shallowRef, useSlots, watchEffect } from 'vue';
|
||||
import {EasyFlowScrollbar} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import { EasyFlowScrollbar } from '@easyflow-core/shadcn-ui';
|
||||
import {useScrollLock} from '@vueuse/core';
|
||||
|
||||
import { useScrollLock } from '@vueuse/core';
|
||||
|
||||
import { SidebarCollapseButton, SidebarFixedButton } from './widgets';
|
||||
import {SidebarCollapseButton, SidebarFixedButton} from './widgets';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
@@ -123,12 +122,12 @@ const style = computed((): CSSProperties => {
|
||||
|
||||
return {
|
||||
'--scroll-shadow': 'var(--surface-elevated)',
|
||||
backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.44)',
|
||||
backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.16)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface) / 0.66) 0%, hsl(var(--nav-surface-subtle) / 0.5) 28%, hsl(var(--glass-tint) / 0.36) 100%)',
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface) / 0.3) 0%, hsl(var(--nav-surface-subtle) / 0.2) 28%, hsl(var(--glass-tint) / 0.12) 100%)',
|
||||
backdropFilter: 'blur(calc(var(--glass-blur) * 1.5)) saturate(188%)',
|
||||
boxShadow:
|
||||
'0 26px 64px -42px hsl(var(--primary) / 0.28), inset 0 1px 0 hsl(var(--nav-sheen) / 0.42), inset -1px 0 0 hsl(var(--nav-sheen) / 0.14)',
|
||||
'inset 0 1px 0 hsl(var(--nav-sheen) / 0.14), inset -1px 0 0 hsl(var(--nav-border) / 0.08)',
|
||||
...calcMenuWidthStyle(false),
|
||||
height: `calc(100% - ${marginTop}px)`,
|
||||
marginTop: `${marginTop}px`,
|
||||
@@ -142,26 +141,17 @@ const extraStyle = computed((): CSSProperties => {
|
||||
const { extraWidth, show, width, zIndex } = props;
|
||||
|
||||
return {
|
||||
backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.4)',
|
||||
backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.12)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface-subtle) / 0.62) 0%, hsl(var(--glass-tint) / 0.34) 100%)',
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface-subtle) / 0.24) 0%, hsl(var(--glass-tint) / 0.12) 100%)',
|
||||
backdropFilter: 'blur(calc(var(--glass-blur) * 1.34)) saturate(182%)',
|
||||
boxShadow:
|
||||
'0 26px 64px -42px hsl(var(--primary) / 0.24), inset 0 1px 0 hsl(var(--nav-sheen) / 0.34), inset -1px 0 0 hsl(var(--nav-sheen) / 0.1)',
|
||||
'inset 0 1px 0 hsl(var(--nav-sheen) / 0.12), inset -1px 0 0 hsl(var(--nav-border) / 0.08)',
|
||||
left: `${width}px`,
|
||||
width: extraVisible.value && show ? `${extraWidth}px` : 0,
|
||||
zIndex,
|
||||
};
|
||||
});
|
||||
const shellAmbientStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient) / 0.58) 0%, hsl(var(--nav-ambient) / 0.22) 20%, transparent 56%), radial-gradient(circle at 14% 0%, hsl(var(--nav-ambient-secondary) / 0.24) 0%, transparent 34%), linear-gradient(180deg, hsl(var(--nav-sheen) / 0.34), transparent 16%)',
|
||||
};
|
||||
const extraAmbientStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient) / 0.42) 0%, hsl(var(--nav-ambient) / 0.16) 18%, transparent 44%), linear-gradient(180deg, hsl(var(--nav-sheen) / 0.28), transparent 16%)',
|
||||
};
|
||||
|
||||
const extraTitleStyle = computed((): CSSProperties => {
|
||||
const { headerHeight } = props;
|
||||
|
||||
@@ -211,6 +201,10 @@ const toolStyle = computed((): CSSProperties => {
|
||||
top: `${Math.max(10, (props.headerHeight - 36) / 2)}px`,
|
||||
};
|
||||
});
|
||||
const pinToolStyle: CSSProperties = {
|
||||
bottom: '16px',
|
||||
left: '12px',
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
extraVisible.value = props.fixedExtra ? true : extraVisible.value;
|
||||
@@ -240,11 +234,7 @@ function calcMenuWidthStyle(isHiddenDom: boolean): CSSProperties {
|
||||
};
|
||||
}
|
||||
|
||||
function handleMouseenter(e: MouseEvent) {
|
||||
if (e?.offsetX < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
function handleMouseenter() {
|
||||
// 未开启和未折叠状态不生效
|
||||
if (expandOnHover.value) {
|
||||
return;
|
||||
@@ -271,6 +261,22 @@ function handleMouseleave() {
|
||||
collapse.value = true;
|
||||
extraVisible.value = false;
|
||||
}
|
||||
|
||||
function handleFixedToggle(nextValue: boolean) {
|
||||
if (nextValue) {
|
||||
collapse.value = false;
|
||||
extraVisible.value = true;
|
||||
expandOnHovering.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
collapse.value = true;
|
||||
extraVisible.value = false;
|
||||
expandOnHovering.value = false;
|
||||
if (props.isSidebarMixed) {
|
||||
isLocked.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -289,11 +295,10 @@ function handleMouseleave() {
|
||||
},
|
||||
]"
|
||||
:style="style"
|
||||
class="fixed left-0 top-0 h-full overflow-hidden transition-all duration-150"
|
||||
class="fixed left-0 top-0 h-full overflow-hidden transition-all duration-150"
|
||||
@mouseenter="handleMouseenter"
|
||||
@mouseleave="handleMouseleave"
|
||||
>
|
||||
<div :style="shellAmbientStyle" class="pointer-events-none absolute inset-0"></div>
|
||||
<div
|
||||
v-if="slots.logo"
|
||||
:style="headerStyle"
|
||||
@@ -306,12 +311,13 @@ function handleMouseleave() {
|
||||
</EasyFlowScrollbar>
|
||||
|
||||
<div
|
||||
v-if="!isSidebarMixed && !collapse && showFixedButton"
|
||||
:style="toolStyle"
|
||||
class="absolute right-3 z-20 flex"
|
||||
v-if="!isSidebarMixed && showFixedButton"
|
||||
:style="pinToolStyle"
|
||||
class="absolute z-20 flex"
|
||||
>
|
||||
<SidebarFixedButton
|
||||
v-model:expand-on-hover="expandOnHover"
|
||||
@toggle="handleFixedToggle"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@@ -320,7 +326,6 @@ function handleMouseleave() {
|
||||
:style="extraStyle"
|
||||
class="fixed top-0 h-full overflow-hidden transition-all duration-200"
|
||||
>
|
||||
<div :style="extraAmbientStyle" class="pointer-events-none absolute inset-0"></div>
|
||||
<div
|
||||
v-if="!extraCollapse"
|
||||
:style="extraTitleStyle"
|
||||
@@ -346,6 +351,7 @@ function handleMouseleave() {
|
||||
<SidebarFixedButton
|
||||
v-if="!extraCollapse"
|
||||
v-model:expand-on-hover="expandOnHover"
|
||||
@toggle="handleFixedToggle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed} from 'vue';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
@@ -15,18 +14,13 @@ const props = withDefaults(defineProps<Props>(), {});
|
||||
const style = computed((): CSSProperties => {
|
||||
const { height } = props;
|
||||
return {
|
||||
backgroundColor: 'hsl(var(--glass-tint) / 0.68)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface-subtle) / 0.92), hsl(var(--glass-tint) / 0.74))',
|
||||
backdropFilter: 'blur(calc(var(--glass-blur) * 0.9)) saturate(155%)',
|
||||
boxShadow: '0 18px 36px -30px hsl(var(--primary) / 0.12)',
|
||||
backgroundColor: 'transparent',
|
||||
backgroundImage: 'none',
|
||||
backdropFilter: 'none',
|
||||
boxShadow: 'none',
|
||||
height: `${height}px`,
|
||||
};
|
||||
});
|
||||
const ambientStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient) / 0.24) 0%, transparent 38%), linear-gradient(180deg, hsl(var(--nav-sheen) / 0.14), transparent 62%)',
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,7 +28,6 @@ const ambientStyle: CSSProperties = {
|
||||
:style="style"
|
||||
class="relative flex w-full overflow-hidden transition-all"
|
||||
>
|
||||
<div :style="ambientStyle" class="pointer-events-none absolute inset-0"></div>
|
||||
<div class="relative z-10 flex w-full">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
|
||||
import { Pin, PinOff } from '@easyflow-core/icons';
|
||||
import {Pin, PinOff} from '@easyflow-core/icons';
|
||||
|
||||
const expandOnHover = defineModel<boolean>('expandOnHover');
|
||||
const emit = defineEmits<{
|
||||
toggle: [value: boolean];
|
||||
}>();
|
||||
const buttonStyle: CSSProperties = {
|
||||
backgroundColor: 'hsl(var(--nav-tool-bg) / 0.92)',
|
||||
backgroundImage:
|
||||
@@ -13,7 +16,9 @@ const buttonStyle: CSSProperties = {
|
||||
};
|
||||
|
||||
function toggleFixed() {
|
||||
expandOnHover.value = !expandOnHover.value;
|
||||
const nextValue = !expandOnHover.value;
|
||||
expandOnHover.value = nextValue;
|
||||
emit('toggle', nextValue);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed, ref, watch} from 'vue';
|
||||
|
||||
import type { EasyFlowLayoutProps } from './easyflow-layout';
|
||||
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import type {EasyFlowLayoutProps} from './easyflow-layout';
|
||||
|
||||
import {
|
||||
SCROLL_FIXED_CLASS,
|
||||
useLayoutFooterStyle,
|
||||
useLayoutHeaderStyle,
|
||||
} from '@easyflow-core/composables';
|
||||
import { IconifyIcon } from '@easyflow-core/icons';
|
||||
import { EasyFlowIconButton } from '@easyflow-core/shadcn-ui';
|
||||
import { ELEMENT_ID_MAIN_CONTENT } from '@easyflow-core/shared/constants';
|
||||
import {IconifyIcon} from '@easyflow-core/icons';
|
||||
import {EasyFlowIconButton} from '@easyflow-core/shadcn-ui';
|
||||
import {ELEMENT_ID_MAIN_CONTENT} from '@easyflow-core/shared/constants';
|
||||
|
||||
import { useMouse, useScroll, useThrottleFn } from '@vueuse/core';
|
||||
import {useMouse, useScroll, useThrottleFn} from '@vueuse/core';
|
||||
|
||||
import {
|
||||
LayoutContent,
|
||||
@@ -23,7 +22,7 @@ import {
|
||||
LayoutSidebar,
|
||||
LayoutTabbar,
|
||||
} from './components';
|
||||
import { useLayout } from './hooks/use-layout';
|
||||
import {useLayout} from './hooks/use-layout';
|
||||
|
||||
interface Props extends EasyFlowLayoutProps {}
|
||||
|
||||
@@ -40,13 +39,13 @@ const headerToggleButtonStyle: CSSProperties = {
|
||||
border: '1px solid hsl(var(--glass-border) / 0.2)',
|
||||
boxShadow: '0 18px 36px -28px hsl(var(--primary) / 0.24)',
|
||||
};
|
||||
const layoutAmbientLeftStyle: CSSProperties = {
|
||||
const layoutFlowFieldStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient) / 0.34) 0%, hsl(var(--nav-ambient) / 0.14) 28%, transparent 72%)',
|
||||
'radial-gradient(ellipse 14% 18% at 5% 3%, hsl(var(--nav-flow-core) / 0.34) 0%, hsl(var(--nav-flow-core) / 0.14) 34%, transparent 74%), radial-gradient(ellipse 48% 18% at 16% 8%, hsl(var(--nav-flow-core) / 0.12) 0%, transparent 68%), radial-gradient(ellipse 68% 34% at 28% 18%, hsl(var(--nav-flow-secondary) / 0.1) 0%, transparent 70%), linear-gradient(122deg, hsl(var(--nav-flow-trace) / 0.13) 0%, hsl(var(--nav-flow-trace) / 0.1) 8%, hsl(var(--nav-flow-core) / 0.08) 14%, transparent 24%, transparent 42%, hsl(var(--nav-flow-secondary) / 0.06) 58%, hsl(var(--nav-flow-trace) / 0.04) 70%, transparent 88%), radial-gradient(ellipse 84% 34% at 34% 26%, hsl(var(--nav-flow-core) / 0.08) 0%, transparent 72%), radial-gradient(ellipse 74% 30% at 48% 38%, hsl(var(--nav-flow-secondary) / 0.06) 0%, transparent 74%), radial-gradient(ellipse 62% 26% at 60% 48%, hsl(var(--nav-flow-accent) / 0.04) 0%, transparent 76%)',
|
||||
};
|
||||
const layoutAmbientRightStyle: CSSProperties = {
|
||||
const layoutFlowGlowStyle: CSSProperties = {
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at left top, hsl(var(--nav-ambient-secondary) / 0.14) 0%, transparent 72%)',
|
||||
'radial-gradient(ellipse 18% 20% at 6% 4%, hsl(var(--nav-flow-core) / 0.18) 0%, transparent 74%), radial-gradient(ellipse 72% 28% at 26% 16%, hsl(var(--nav-flow-trace) / 0.08) 0%, transparent 70%), radial-gradient(ellipse 68% 26% at 44% 28%, hsl(var(--nav-flow-secondary) / 0.05) 0%, transparent 72%), radial-gradient(ellipse 58% 22% at 62% 42%, hsl(var(--nav-flow-trace) / 0.04) 0%, transparent 74%)',
|
||||
};
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -335,6 +334,11 @@ const headerZIndex = computed(() => {
|
||||
const headerWrapperStyle = computed((): CSSProperties => {
|
||||
const fixed = headerFixed.value;
|
||||
return {
|
||||
backdropFilter: 'blur(calc(var(--glass-blur) * 1.1)) saturate(158%)',
|
||||
backgroundColor: 'hsl(var(--glass-tint) / 0.18)',
|
||||
backgroundImage:
|
||||
'linear-gradient(180deg, hsl(var(--nav-surface) / 0.22), hsl(var(--glass-tint) / 0.08))',
|
||||
boxShadow: 'inset 0 -1px 0 hsl(var(--nav-border) / 0.05)',
|
||||
height: isFullContent.value ? '0' : `${headerWrapperHeight.value}px`,
|
||||
left: isMixedNav.value ? 0 : mainStyle.value.sidebarAndExtraWidth,
|
||||
position: fixed ? 'fixed' : 'static',
|
||||
@@ -501,8 +505,8 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
|
||||
<template>
|
||||
<div class="relative flex min-h-full w-full">
|
||||
<div class="pointer-events-none absolute inset-0 overflow-hidden">
|
||||
<div :style="layoutAmbientLeftStyle" class="absolute -left-16 top-0 h-[320px] w-[320px] rounded-full blur-3xl"></div>
|
||||
<div :style="layoutAmbientRightStyle" class="absolute right-[-120px] top-[-40px] h-[260px] w-[320px] rounded-full blur-3xl"></div>
|
||||
<div :style="layoutFlowFieldStyle" class="absolute inset-0"></div>
|
||||
<div :style="layoutFlowGlowStyle" class="absolute inset-0 blur-3xl"></div>
|
||||
</div>
|
||||
<LayoutSidebar
|
||||
v-if="sidebarEnableState"
|
||||
|
||||
Reference in New Issue
Block a user