perf: 优化导航样式以及菜单折叠动画 (#408)

* chore: `4.0.0` 版本,正在开发中

* chore: update `element-plus`

* chore: update

* chore: update dependencies

* chore: update

* style: update

* chore: update `dependencies`

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update
This commit is contained in:
RealityBoy 2023-02-08 16:09:07 +08:00 committed by GitHub
parent 151592c660
commit 3e93618015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 781 additions and 698 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2022 啝裳 Copyright (c) 2023 啝裳
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -159,7 +159,7 @@ const frameRouter = {
const tabsRouter = { const tabsRouter = {
path: "/tabs", path: "/tabs",
meta: { meta: {
icon: "IF-team-icontabs", icon: "IF-pure-iconfont-tabs",
title: "menus.hstabs", title: "menus.hstabs",
rank: tabs rank: tabs
}, },

View File

@ -34,9 +34,9 @@
"@logicflow/core": "^1.1.30", "@logicflow/core": "^1.1.30",
"@logicflow/extension": "^1.1.30", "@logicflow/extension": "^1.1.30",
"@pureadmin/descriptions": "^1.1.0", "@pureadmin/descriptions": "^1.1.0",
"@pureadmin/table": "^1.9.0", "@pureadmin/table": "^2.0.0",
"@pureadmin/utils": "^1.8.5", "@pureadmin/utils": "^1.8.5",
"@vueuse/core": "^9.10.0", "@vueuse/core": "^9.12.0",
"@vueuse/motion": "2.0.0-beta.12", "@vueuse/motion": "2.0.0-beta.12",
"@wangeditor/editor": "^5.1.21", "@wangeditor/editor": "^5.1.21",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
@ -47,7 +47,7 @@
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"echarts": "^5.4.1", "echarts": "^5.4.1",
"el-table-infinite-scroll": "^3.0.1", "el-table-infinite-scroll": "^3.0.1",
"element-plus": "^2.2.28", "element-plus": "2.2.28",
"element-resize-detector": "^1.2.4", "element-resize-detector": "^1.2.4",
"intro.js": "^6.0.0", "intro.js": "^6.0.0",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
@ -57,12 +57,12 @@
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path": "^0.12.7", "path": "^0.12.7",
"pinia": "^2.0.28", "pinia": "^2.0.30",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"qs": "^6.11.0", "qs": "^6.11.0",
"responsive-storage": "^2.1.0", "responsive-storage": "^2.1.0",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
"swiper": "^8.4.5", "swiper": "^9.0.3",
"typeit": "^8.7.1", "typeit": "^8.7.1",
"v-contextmenu": "3.0.0", "v-contextmenu": "3.0.0",
"vue": "^3.2.45", "vue": "^3.2.45",
@ -130,7 +130,7 @@
"terser": "^5.16.1", "terser": "^5.16.1",
"typescript": "^4.9.4", "typescript": "^4.9.4",
"unplugin-vue-define-options": "^1.0.0", "unplugin-vue-define-options": "^1.0.0",
"vite": "^4.0.4", "vite": "^4.1.1",
"vite-plugin-cdn-import": "^0.3.5", "vite-plugin-cdn-import": "^0.3.5",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",

913
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 2208059 */ font-family: "iconfont"; /* Project id 2208059 */
src: url("iconfont.woff2?t=1638023560828") format("woff2"), src: url("iconfont.woff2?t=1671895108120") format("woff2"),
url("iconfont.woff?t=1638023560828") format("woff"), url("iconfont.woff?t=1671895108120") format("woff"),
url("iconfont.ttf?t=1638023560828") format("truetype"); url("iconfont.ttf?t=1671895108120") format("truetype");
} }
.iconfont { .iconfont {
@ -13,26 +13,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.team-icontabs::before { .pure-iconfont-tabs:before {
content: "\e63e"; content: "\e63e";
} }
.team-iconlogo::before { .pure-iconfont-logo:before {
content: "\e620"; content: "\e620";
} }
.team-iconxinpin::before { .pure-iconfont-new:before {
content: "\e614";
}
.team-iconxinpinrenqiwang::before {
content: "\e615"; content: "\e615";
} }
.team-iconexit-fullscreen::before {
content: "\e62a";
}
.team-iconfullscreen::before {
content: "\e62b";
}

File diff suppressed because one or more lines are too long

View File

@ -2,50 +2,29 @@
"id": "2208059", "id": "2208059",
"name": "pure-admin", "name": "pure-admin",
"font_family": "iconfont", "font_family": "iconfont",
"css_prefix_text": "team-icon", "css_prefix_text": "pure-iconfont-",
"description": "pure-admin", "description": "pure-admin-iconfont",
"glyphs": [ "glyphs": [
{ {
"icon_id": "20594647", "icon_id": "20594647",
"name": "标签页", "name": "Tabs",
"font_class": "tabs", "font_class": "tabs",
"unicode": "e63e", "unicode": "e63e",
"unicode_decimal": 58942 "unicode_decimal": 58942
}, },
{ {
"icon_id": "22129506", "icon_id": "22129506",
"name": "水能", "name": "PureLogo",
"font_class": "logo", "font_class": "logo",
"unicode": "e620", "unicode": "e620",
"unicode_decimal": 58912 "unicode_decimal": 58912
}, },
{
"icon_id": "7795613",
"name": "新品",
"font_class": "xinpin",
"unicode": "e614",
"unicode_decimal": 58900
},
{ {
"icon_id": "7795615", "icon_id": "7795615",
"name": "新品人气王", "name": "New",
"font_class": "xinpinrenqiwang", "font_class": "new",
"unicode": "e615", "unicode": "e615",
"unicode_decimal": 58901 "unicode_decimal": 58901
},
{
"icon_id": "5698509",
"name": "全屏缩小",
"font_class": "exit-fullscreen",
"unicode": "e62a",
"unicode_decimal": 58922
},
{
"icon_id": "5698510",
"name": "全屏显示",
"font_class": "fullscreen",
"unicode": "e62b",
"unicode_decimal": 58923
} }
] ]
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,21 +0,0 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { useFullscreen } from "@vueuse/core";
const { t } = useI18n();
const { isFullscreen, toggle } = useFullscreen();
</script>
<template>
<div
class="screen-full w-[36px] h-[48px] flex-ac cursor-pointer navbar-bg-hover"
@click="toggle"
>
<FontIcon
:title="
isFullscreen ? t('buttons.hsexitfullscreen') : t('buttons.hsfullscreen')
"
:icon="isFullscreen ? 'team-iconexit-fullscreen' : 'team-iconfullscreen'"
/>
</div>
</template>

View File

@ -46,7 +46,11 @@ watch(
class="horizontal-header" class="horizontal-header"
> >
<div class="horizontal-header-left" @click="backHome"> <div class="horizontal-header-left" @click="backHome">
<FontIcon icon="team-iconlogo" svg style="width: 35px; height: 35px" /> <FontIcon
icon="pure-iconfont-logo"
svg
style="width: 35px; height: 35px"
/>
<h4>{{ title }}</h4> <h4>{{ title }}</h4>
</div> </div>
<el-menu <el-menu

View File

@ -24,7 +24,7 @@ const iconClass = computed(() => {
"align-middle", "align-middle",
"text-primary", "text-primary",
"cursor-pointer", "cursor-pointer",
"duration-[360ms]", "duration-[100ms]",
"hover:text-primary", "hover:text-primary",
"dark:hover:!text-white" "dark:hover:!text-white"
]; ];

View File

@ -18,7 +18,11 @@ const { title } = useNav();
class="sidebar-logo-link" class="sidebar-logo-link"
to="/" to="/"
> >
<FontIcon icon="team-iconlogo" svg style="width: 35px; height: 35px" /> <FontIcon
icon="pure-iconfont-logo"
svg
style="width: 35px; height: 35px"
/>
<span class="sidebar-title">{{ title }}</span> <span class="sidebar-title">{{ title }}</span>
</router-link> </router-link>
<router-link <router-link
@ -28,7 +32,11 @@ const { title } = useNav();
class="sidebar-logo-link" class="sidebar-logo-link"
to="/" to="/"
> >
<FontIcon icon="team-iconlogo" svg style="width: 35px; height: 35px" /> <FontIcon
icon="pure-iconfont-logo"
svg
style="width: 35px; height: 35px"
/>
<span class="sidebar-title">{{ title }}</span> <span class="sidebar-title">{{ title }}</span>
</router-link> </router-link>
</transition> </transition>

View File

@ -28,17 +28,11 @@ const props = defineProps({
} }
}); });
const getExtraIconStyle = computed((): CSSProperties => { const getSpanStyle = computed((): CSSProperties => {
if (!isCollapse.value) { return {
return { width: "100%",
position: "absolute", textAlign: "center"
right: "10px" };
};
} else {
return {
position: "static"
};
}
}); });
const getNoDropdownStyle = computed((): CSSProperties => { const getNoDropdownStyle = computed((): CSSProperties => {
@ -48,16 +42,6 @@ const getNoDropdownStyle = computed((): CSSProperties => {
}; };
}); });
const getDivStyle = computed((): CSSProperties => {
return {
width: !isCollapse.value ? "" : "100%",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
overflow: "hidden"
};
});
const getMenuTextStyle = computed(() => { const getMenuTextStyle = computed(() => {
return { return {
overflow: "hidden", overflow: "hidden",
@ -66,22 +50,45 @@ const getMenuTextStyle = computed(() => {
}; };
}); });
const getSubTextStyle = computed((): CSSProperties => { const getDivStyle = computed((): CSSProperties => {
return { return {
width: !isCollapse.value ? "210px" : "", width: "100%",
display: "inline-block", display: "flex",
overflow: "hidden", alignItems: "center",
textOverflow: "ellipsis" justifyContent: "space-between",
overflow: "hidden"
}; };
}); });
const getSpanStyle = computed(() => { const getsubMenuIconStyle = computed((): CSSProperties => {
return { return {
overflow: "hidden", display: "flex",
textOverflow: "ellipsis" justifyContent: "center",
alignItems: "center",
margin:
layout.value === "horizontal"
? "0 5px 0 0"
: isCollapse.value
? "0 auto"
: "0 5px 0 0"
}; };
}); });
const getSubTextStyle = computed((): CSSProperties => {
if (!isCollapse.value) {
return {
width: "210px",
display: "inline-block",
overflow: "hidden",
textOverflow: "ellipsis"
};
} else {
return {
width: ""
};
}
});
const expandCloseIcon = computed(() => { const expandCloseIcon = computed(() => {
if (!getConfig()?.MenuArrowIconNoTransition) return ""; if (!getConfig()?.MenuArrowIconNoTransition) return "";
return { return {
@ -115,6 +122,20 @@ function hoverMenu(key) {
}); });
} }
//
function overflowSlice(text, item?: any) {
const newText =
(text?.length > 1 ? text.toString().slice(0, 1) : text) + "...";
if (item && !(isCollapse.value && item?.parentId === null)) {
return layout.value === "mix" &&
item?.pathList?.length === 2 &&
isCollapse.value
? newText
: text;
}
return newText;
}
function hasOneShowingChild( function hasOneShowingChild(
children: childrenType[] = [], children: childrenType[] = [],
parent: childrenType parent: childrenType
@ -151,84 +172,84 @@ function resolvePath(routePath) {
</script> </script>
<template> <template>
<template <el-menu-item
v-if=" v-if="
hasOneShowingChild(props.item.children, props.item) && hasOneShowingChild(props.item.children, props.item) &&
(!onlyOneChild.children || onlyOneChild.noShowingChildren) (!onlyOneChild.children || onlyOneChild.noShowingChildren)
" "
:index="resolvePath(onlyOneChild.path)"
:class="{ 'submenu-title-noDropdown': !isNest }"
:style="getNoDropdownStyle"
> >
<el-menu-item <div
:index="resolvePath(onlyOneChild.path)" v-if="toRaw(props.item.meta.icon)"
:class="{ 'submenu-title-noDropdown': !isNest }" class="sub-menu-icon"
:style="getNoDropdownStyle" :style="getsubMenuIconStyle"
> >
<div class="sub-menu-icon" v-if="toRaw(props.item.meta.icon)"> <component
<component :is="
:is=" useRenderIcon(
useRenderIcon( toRaw(onlyOneChild.meta.icon) ||
toRaw(onlyOneChild.meta.icon) || (props.item.meta && toRaw(props.item.meta.icon))
(props.item.meta && toRaw(props.item.meta.icon)) )
)
"
/>
</div>
<div
v-if="
isCollapse &&
layout === 'vertical' &&
props.item?.pathList?.length === 1
" "
:style="getDivStyle" />
> </div>
<span :style="getMenuTextStyle"> <span
v-if="
!props.item?.meta.icon &&
isCollapse &&
layout === 'vertical' &&
props.item?.pathList?.length === 1
"
:style="getSpanStyle"
>
{{ overflowSlice(transformI18n(onlyOneChild.meta.title)) }}
</span>
<span
v-if="
!onlyOneChild.meta.icon &&
isCollapse &&
layout === 'mix' &&
props.item?.pathList?.length === 2
"
:style="getSpanStyle"
>
{{ overflowSlice(transformI18n(onlyOneChild.meta.title)) }}
</span>
<template #title>
<div :style="getDivStyle">
<span v-if="layout === 'horizontal'">
{{ transformI18n(onlyOneChild.meta.title) }} {{ transformI18n(onlyOneChild.meta.title) }}
</span> </span>
</div> <el-tooltip
<div v-else
v-if=" placement="top"
isCollapse && layout === 'mix' && props.item?.pathList?.length === 2 :effect="tooltipEffect"
" :offset="-10"
:style="getDivStyle" :disabled="!onlyOneChild.showTooltip"
> >
<span :style="getMenuTextStyle"> <template #content>
{{ transformI18n(onlyOneChild.meta.title) }} {{ transformI18n(onlyOneChild.meta.title) }}
</span> </template>
</div> <span
<template #title> ref="menuTextRef"
<div :style="getDivStyle"> :style="getMenuTextStyle"
<span v-if="layout === 'horizontal'"> @mouseover="hoverMenu(onlyOneChild)"
>
{{ transformI18n(onlyOneChild.meta.title) }} {{ transformI18n(onlyOneChild.meta.title) }}
</span> </span>
<el-tooltip </el-tooltip>
v-else <FontIcon
placement="top" v-if="onlyOneChild.meta.extraIcon"
:effect="tooltipEffect" width="30px"
:offset="-10" height="30px"
:disabled="!onlyOneChild.showTooltip" :icon="onlyOneChild.meta.extraIcon.name"
> :svg="onlyOneChild.meta.extraIcon.svg ? true : false"
<template #content> />
{{ transformI18n(onlyOneChild.meta.title) }} </div>
</template> </template>
<span </el-menu-item>
ref="menuTextRef"
:style="getMenuTextStyle"
@mouseover="hoverMenu(onlyOneChild)"
>
{{ transformI18n(onlyOneChild.meta.title) }}
</span>
</el-tooltip>
<FontIcon
v-if="onlyOneChild.meta.extraIcon"
width="30px"
height="30px"
:style="getExtraIconStyle"
:icon="onlyOneChild.meta.extraIcon.name"
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
/>
</div>
</template>
</el-menu-item>
</template>
<el-sub-menu <el-sub-menu
v-else v-else
@ -237,7 +258,11 @@ function resolvePath(routePath) {
:index="resolvePath(props.item.path)" :index="resolvePath(props.item.path)"
> >
<template #title> <template #title>
<div v-if="toRaw(props.item.meta.icon)" class="sub-menu-icon"> <div
v-if="toRaw(props.item.meta.icon)"
:style="getsubMenuIconStyle"
class="sub-menu-icon"
>
<component <component
:is="useRenderIcon(props.item.meta && toRaw(props.item.meta.icon))" :is="useRenderIcon(props.item.meta && toRaw(props.item.meta.icon))"
/> />
@ -255,21 +280,25 @@ function resolvePath(routePath) {
<template #content> <template #content>
{{ transformI18n(props.item.meta.title) }} {{ transformI18n(props.item.meta.title) }}
</template> </template>
<div <span
v-if="
!(
isCollapse &&
toRaw(props.item.meta.icon) &&
props.item.parentId === null
)
"
ref="menuTextRef" ref="menuTextRef"
:style="getSubTextStyle" :style="getSubTextStyle"
@mouseover="hoverMenu(props.item)" @mouseover="hoverMenu(props.item)"
> >
<span :style="getSpanStyle"> {{ overflowSlice(transformI18n(props.item.meta.title), props.item) }}
{{ transformI18n(props.item.meta.title) }} </span>
</span>
</div>
</el-tooltip> </el-tooltip>
<FontIcon <FontIcon
v-if="props.item.meta.extraIcon" v-if="props.item.meta.extraIcon"
width="30px" width="30px"
height="30px" height="30px"
style="position: absolute; right: 10px"
:icon="props.item.meta.extraIcon.name" :icon="props.item.meta.extraIcon.name"
:svg="props.item.meta.extraIcon.svg ? true : false" :svg="props.item.meta.extraIcon.svg ? true : false"
/> />

View File

@ -281,7 +281,7 @@
left: 0; left: 0;
bottom: 0; bottom: 0;
background: var(--el-color-primary); background: var(--el-color-primary);
animation: scheduleInWidth 400ms ease-in; animation: scheduleInWidth 200ms ease-in;
} }
/* 灵动模式下鼠标移出隐藏蓝色进度条 */ /* 灵动模式下鼠标移出隐藏蓝色进度条 */
@ -292,5 +292,5 @@
left: 0; left: 0;
bottom: 0; bottom: 0;
background: var(--el-color-primary); background: var(--el-color-primary);
animation: scheduleOutWidth 400ms ease-in; animation: scheduleOutWidth 200ms ease-in;
} }

View File

@ -13,13 +13,13 @@ const home = 0, // 平台规定只有 home 路由的 rank 才能为 0 ,所以
list = 10, list = 10,
permission = 11, permission = 11,
system = 12, system = 12,
menuoverflow = 13, tabs = 13,
tabs = 14, formdesign = 14,
formdesign = 15, flowchart = 15,
flowchart = 16, ppt = 16,
ppt = 17, editor = 17,
editor = 18, guide = 18,
guide = 19, menuoverflow = 19,
about = 20; about = 20;
export { export {
@ -36,12 +36,12 @@ export {
list, list,
permission, permission,
system, system,
menuoverflow,
tabs, tabs,
formdesign, formdesign,
flowchart, flowchart,
ppt, ppt,
editor, editor,
guide, guide,
menuoverflow,
about about
}; };

View File

@ -18,7 +18,7 @@ export default {
title: $t("menus.hsmessage"), title: $t("menus.hsmessage"),
extraIcon: { extraIcon: {
svg: true, svg: true,
name: "team-iconxinpinrenqiwang" name: "pure-iconfont-new"
}, },
transition: { transition: {
enterTransition: "animate__fadeInLeft", enterTransition: "animate__fadeInLeft",

View File

@ -55,7 +55,7 @@ export default {
keepAlive: true, keepAlive: true,
extraIcon: { extraIcon: {
svg: true, svg: true,
name: "team-iconxinpinrenqiwang" name: "pure-iconfont-new"
} }
} }
} }

View File

@ -6,7 +6,8 @@
/* 自定义全局 CssVar */ /* 自定义全局 CssVar */
:root { :root {
--pure-transition-duration: 0.016s; /* 左侧菜单展开、收起动画时长 */
--pure-transition-duration: 0.3s;
} }
/* 灰色模式 */ /* 灰色模式 */

View File

@ -14,12 +14,13 @@
} }
.sub-menu-icon { .sub-menu-icon {
vertical-align: middle;
font-size: 18px; font-size: 18px;
display: inline-flex;
justify-content: center;
align-items: center;
margin-right: 5px; margin-right: 5px;
svg {
width: 18px;
height: 18px;
}
} }
.set-icon { .set-icon {
@ -195,7 +196,7 @@
align-items: center; align-items: center;
padding-left: 10px; padding-left: 10px;
cursor: pointer; cursor: pointer;
transition: all 0.125s ease; transition: all var(--pure-transition-duration) ease;
i { i {
font-size: 30px; font-size: 30px;
@ -284,6 +285,7 @@
.el-menu-item, .el-menu-item,
.el-sub-menu__title { .el-sub-menu__title {
padding-right: var(--el-menu-base-level-padding);
color: $menuText; color: $menuText;
&:hover { &:hover {
@ -374,19 +376,13 @@
.el-menu-item, .el-menu-item,
.el-sub-menu { .el-sub-menu {
// i { .iconfont {
// width: 20px; font-size: 18px;
// text-align: center; }
// font-size: 16px;
// }
// i.fa {
// margin-right: 5px;
// font-size: 16px;
// }
.el-menu-tooltip__trigger { .el-menu-tooltip__trigger {
width: 54px; width: 54px;
padding: 18px !important; padding: 0;
} }
} }
} }
@ -471,13 +467,13 @@
.el-menu--collapse .is-active.submenu-title-noDropdown.outer-most::before { .el-menu--collapse .is-active.submenu-title-noDropdown.outer-most::before {
position: absolute; position: absolute;
top: 0; top: 0;
left: 2px; left: 0;
width: 2px; width: 2px;
height: 100%; height: 100%;
background-color: $menuActiveBefore; background-color: $menuActiveBefore;
content: ""; content: "";
clear: both; clear: both;
transition: all 0.125s ease-in-out; transition: all var(--pure-transition-duration) ease-in-out;
transform: translateY(0); transform: translateY(0);
} }
@ -537,7 +533,7 @@ body[layout="vertical"] {
} }
.sidebar-container { .sidebar-container {
transition: width 0.125s; transition: width var(--pure-transition-duration);
width: 54px !important; width: 54px !important;
.is-active.submenu-title-noDropdown.outer-most { .is-active.submenu-title-noDropdown.outer-most {
@ -554,11 +550,10 @@ body[layout="vertical"] {
.el-sub-menu { .el-sub-menu {
& > .el-sub-menu__title { & > .el-sub-menu__title {
& > span { & > span {
height: 0; height: 100%;
width: 0; width: 100%;
overflow: hidden; text-align: center;
visibility: hidden; visibility: visible;
display: inline-block;
} }
} }
} }
@ -568,7 +563,7 @@ body[layout="vertical"] {
} }
.el-sub-menu__title { .el-sub-menu__title {
padding: 0 18px !important; padding: 0;
} }
} }
@ -597,9 +592,13 @@ body[layout="horizontal"] {
$sideBarWidth: 0; $sideBarWidth: 0;
@include merge-style($sideBarWidth); @include merge-style($sideBarWidth);
.fixed-header,
.main-container {
transition: none !important;
}
.fixed-header { .fixed-header {
width: 100%; width: 100%;
transition: none !important;
} }
} }
@ -622,7 +621,7 @@ body[layout="mix"] {
} }
.sidebar-container { .sidebar-container {
transition: width 0.125s; transition: width var(--pure-transition-duration);
width: 54px !important; width: 54px !important;
.is-active.submenu-title-noDropdown.outer-most { .is-active.submenu-title-noDropdown.outer-most {
@ -638,12 +637,12 @@ body[layout="mix"] {
.el-menu--collapse { .el-menu--collapse {
.el-sub-menu { .el-sub-menu {
& > .el-sub-menu__title { & > .el-sub-menu__title {
padding: 0;
& > span { & > span {
height: 0; height: 100%;
width: 0; width: 100%;
overflow: hidden; text-align: center;
visibility: hidden; visibility: visible;
display: inline-block;
} }
} }
} }