Skip to content

Commit

Permalink
feat(layouts): ✨ sidebar
Browse files Browse the repository at this point in the history
- Sidebar text overflows to display abbreviations and displays tootips

- Adjust the style to optimize the expansion and contraction animation
  • Loading branch information
jsxiaosi committed Oct 25, 2023
1 parent 8b98a5b commit 8acd3a0
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 285 deletions.
Empty file added .env
Empty file.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"dayjs": "^1.11.9",
"docx-preview": "^0.1.18",
"echarts": "^5.4.3",
"element-plus": "^2.3.12",
"element-plus": "^2.4.1",
"es6-promise": "^4.2.8",
"i18next": "^23.5.0",
"intro.js": "^7.2.0",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 8 additions & 11 deletions src/components/SvgIcon/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</script>

<template>
<el-icon v-if="isELIcon" :class="className">
<el-icon v-if="isELIcon" :class="`svg-icon ${className}`">
<component :is="name" />
</el-icon>
<i v-else class="svg-icon" :class="className">
Expand All @@ -37,24 +37,21 @@
</template>

<style lang="scss" scoped>
.el-icon {
.svg-icon {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 1em;
height: 1em;
margin: 0;
// 取父级的宽高
font-size: 1em;
color: currentcolor;
}
.svg-icon {
display: block;
height: 1em;
line-height: 1em;
font-size: 1em;
margin: 0;
.svg {
width: 1em;
height: 1em;
color: currentcolor;
use {
fill: currentcolor;
Expand Down
55 changes: 48 additions & 7 deletions src/layouts/page-layouts/components/Sidebar/Item.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { ref } from 'vue';
import SvgIcon from '@/components/SvgIcon/index.vue';
import type { localeTitle } from '@/router/type';
import { translateI18n } from '@/hooks/web/useI18n';
Expand All @@ -8,24 +9,64 @@
icon?: string;
title?: string | localeTitle;
className?: string;
collapse?: boolean;
mode?: 'vertical' | 'horizontal';
}>(),
{
icon: 'hello',
icon: '',
title: '',
className: '',
collapse: false,
mode: 'vertical',
},
);
const showTextTooltip = ref<Boolean | null>(null);
const sidebarItemTextRef = ref<HTMLDivElement>();
const onTextMove = () => {
if (showTextTooltip.value !== null || props.mode === 'horizontal') return;
const sidebarItemTextDom = sidebarItemTextRef.value?.children?.[0];
showTextTooltip.value = sidebarItemTextDom
? sidebarItemTextDom.scrollWidth > sidebarItemTextDom.clientWidth
: false;
};
</script>

<template>
<SvgIcon :class-name="props.className" :name="props.icon" />
<span v-if="props.title">{{ translateI18n(props.title) }}</span>
<SvgIcon v-if="props.icon" :class-name="props.className" :name="props.icon" />
<div
ref="sidebarItemTextRef"
class="menu-item-text"
:class="[
!props.icon && 'menu-item-text-only',
props.mode === 'vertical' && 'sidebar-menu-item-text',
]"
@mouseover="onTextMove"
>
<el-tooltip
:content="translateI18n(props.title)"
:disabled="!showTextTooltip || props.collapse"
placement="top"
>
<el-text truncated>
{{ translateI18n(props.title) }}
</el-text>
</el-tooltip>
</div>
</template>

<style lang="scss" scoped>
.sub-el-icon {
/* color: currentColor; */
width: 1em;
height: 1em;
.sidebar-menu-item-text {
width: 0;
flex: 1;
}
.menu-item-text {
color: currentcolor;
.el-text {
color: currentcolor;
}
}
</style>
1 change: 1 addition & 0 deletions src/layouts/page-layouts/components/Sidebar/MinSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
class-name="menu-item-svg"
:icon="menusRoute.meta && menusRoute.meta.icon"
:title="menusRoute.meta?.title"
mode="horizontal"
/>
</el-menu-item>
</AppLink>
Expand Down
95 changes: 63 additions & 32 deletions src/layouts/page-layouts/components/Sidebar/SidebarItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Item from './Item.vue';
import AppLink from './Link.vue';
import type { AppRouteRecordRaw } from '@/router/type';
import { translateI18n } from '@/hooks/web/useI18n';
const props = defineProps({
// route object
Expand All @@ -21,21 +22,32 @@
type: String,
default: '',
},
level: {
type: Number,
default: 0,
},
collapse: {
type: Boolean,
default: false,
},
mode: {
type: String as PropType<'vertical' | 'horizontal'>,
default: 'vertical',
},
});
const onlyOneChild = ref<any>({});
const hasOneShowingChild = (
children: Array<AppRouteRecordRaw> = [],
parent: AppRouteRecordRaw,
) => {
const showingChildren = children.filter((item: AppRouteRecordRaw) => {
if (item.meta?.hideSidebar) {
return false;
} else {
// Temp set(will be used if only has one showing child)
onlyOneChild.value = item;
return true;
}
});
const onlyOneChild = ref<Partial<AppRouteRecordRaw & { noShowingChildren: boolean }>>({});
const hasOneShowingChild = (parent: AppRouteRecordRaw) => {
const showingChildren =
parent.children?.filter((item: AppRouteRecordRaw) => {
if (item.meta?.hideSidebar) {
return false;
} else {
// Temp set(will be used if only has one showing child)
onlyOneChild.value = item;
return true;
}
}) ?? [];
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
Expand Down Expand Up @@ -65,44 +77,63 @@
<div v-if="!item.meta?.hideSidebar">
<template
v-if="
hasOneShowingChild(item.children, item) &&
hasOneShowingChild(item) &&
(!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
!item.meta?.alwaysShow
"
>
<AppLink v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item
:index="resolvePath(onlyOneChild.path)"
:class="{ 'submenu-title-noDropdown': !isNest }"
>
<Item
class-name="menu-item-svg"
:icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"
:title="onlyOneChild.meta.title || (item.meta && item.meta.title)"
/>
</el-menu-item>
</AppLink>
<el-tooltip
class="box-item"
:disabled="props.level > 0 || !props.collapse"
:content="translateI18n(onlyOneChild.meta?.title)"
placement="right"
>
<AppLink v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild?.path ?? '')">
<el-menu-item
:index="resolvePath(onlyOneChild?.path ?? '')"
:class="{
'submenu-title-noDropdown': !isNest,
'one-level-menu-item': props.level === 0,
}"
>
<Item
class-name="menu-item-svg"
:icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"
:title="onlyOneChild.meta.title || (item.meta && item.meta.title)"
:collapse="props.level === 0 && props.collapse"
:mode="mode"
/>
</el-menu-item>
</AppLink>
</el-tooltip>
</template>

<el-sub-menu v-else :index="resolvePath(item.path)" teleported>
<el-sub-menu
v-else
:index="resolvePath(item.path)"
:class="{ 'one-level-sub-menu': props.level === 0 }"
teleported
>
<template #title>
<Item
v-if="item.meta"
class-name="sub-menu-svg"
:icon="item.meta && item.meta.icon"
:title="item.meta.title"
:collapse="props.level === 0 && props.collapse"
:mode="mode"
/>
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
v-for="(child, index) in item.children"
:key="child.path + index"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
:level="props.level + 1"
:collapse="props.collapse"
/>
</el-sub-menu>
</div>
</template>

<style lang="scss" scoped></style>
9 changes: 8 additions & 1 deletion src/layouts/page-layouts/components/Sidebar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,29 @@
}
return path;
});
const collapse = computed(() =>
appConfig.value.sidebarMode === 'horizontal' ? false : appConfig.value.collapseMenu,
);
</script>

<template>
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenyu"
:unique-opened="true"
:collapse="appConfig.sidebarMode === 'horizontal' ? false : appConfig.collapseMenu"
:collapse="collapse"
:mode="mode"
:collapse-transition="true"
>
<SidebarItem
v-for="menuRoute in menuData"
:key="menuRoute.path"
:item="menuRoute"
:is-nest="false"
:base-path="menuRoute.path"
:collapse="collapse"
:mode="mode"
/>
</el-menu>
</el-scrollbar>
Expand Down
Loading

0 comments on commit 8acd3a0

Please sign in to comment.