refactor: improve effect of menu expand (#5244)

#### What type of PR is this?

/area console
/milestone 2.12.x
/kind improvement

#### What this PR does / why we need it:

优化 Console 左侧菜单的展开逻辑,改为可以通过点击展开图标来展开子菜单。

<img width="323" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/6f9a4d2c-1141-424e-b5cd-4e0a9991c67d">

#### Does this PR introduce a user-facing change?

```release-note
优化 Console 左侧菜单的展开逻辑,支持通过点击图标来展开子菜单。
```
pull/5250/head
Ryan Wang 2024-01-25 11:40:48 +08:00 committed by GitHub
parent 29bd0590ca
commit 138af65d0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 19 deletions

View File

@ -34,17 +34,23 @@ const hasSubmenus = computed(() => {
}); });
function handleClick() { function handleClick() {
if (!open.value) {
handleExpand();
}
emit("select", props.id);
}
function handleExpand() {
if (hasSubmenus.value) { if (hasSubmenus.value) {
open.value = !open.value; open.value = !open.value;
} }
emit("select", props.id);
} }
</script> </script>
<template> <template>
<li <li
:class="{ 'has-submenus': hasSubmenus }" :class="{ 'has-submenus': hasSubmenus }"
class="menu-item" class="menu-item group"
@click.stop="handleClick" @click.stop="handleClick"
> >
<div :class="{ active }" class="menu-item-title"> <div :class="{ active }" class="menu-item-title">
@ -58,6 +64,7 @@ function handleClick() {
v-if="$slots.default" v-if="$slots.default"
:class="{ open }" :class="{ open }"
class="menu-icon-collapse self-center transition-all" class="menu-icon-collapse self-center transition-all"
@click.stop="handleExpand"
> >
<IconArrowRight /> <IconArrowRight />
</span> </span>
@ -105,8 +112,13 @@ function handleClick() {
} }
} }
.menu-icon-collapse.open { .menu-icon-collapse {
transform: rotate(90deg); @apply group-hover:bg-gray-200 p-0.5 rounded-full;
&.open {
@apply bg-gray-200;
transform: rotate(90deg);
}
} }
.submenus-show-enter-active, .submenus-show-enter-active,

View File

@ -14,7 +14,7 @@ describe("Menu", () => {
const wrapper = await mount({ const wrapper = await mount({
setup() { setup() {
return () => ( return () => (
<VMenu openIds={["3"]}> <VMenu>
<VMenuItem id="1" title="Menu Item 1" /> <VMenuItem id="1" title="Menu Item 1" />
<VMenuItem id="2" title="Menu Item 2" /> <VMenuItem id="2" title="Menu Item 2" />
<VMenuItem id="3" title="Menu Item 3"> <VMenuItem id="3" title="Menu Item 3">
@ -29,17 +29,24 @@ describe("Menu", () => {
// toggling sub menu // toggling sub menu
expect( expect(
wrapper.find(".has-submenus .sub-menu-items").attributes().style wrapper.find(".has-submenus .sub-menu-items").attributes().style
).toBeUndefined(); // visible ).toBe("display: none;");
await wrapper.find(".has-submenus").trigger("click"); await wrapper.find(".has-submenus").trigger("click");
expect( expect(
wrapper.find(".has-submenus .sub-menu-items").attributes().style wrapper.find(".has-submenus .sub-menu-items").attributes().style
).toBe("display: none;"); ).toBe(""); // visible
await wrapper.find(".has-submenus").trigger("click"); await wrapper.find(".has-submenus").trigger("click");
expect( expect(
wrapper.find(".has-submenus .sub-menu-items").attributes().style wrapper.find(".has-submenus .sub-menu-items").attributes().style
).toBe(""); // visible ).toBe(""); // visible
await wrapper.find(".has-submenus .menu-icon-collapse").trigger("click");
expect(
wrapper.find(".has-submenus .sub-menu-items").attributes().style
).toBe("display: none;");
}); });
it("should work with openIds prop", function () { it("should work with openIds prop", function () {
@ -90,7 +97,7 @@ describe("Menu", () => {
item.trigger("click"); item.trigger("click");
expect(item.emitted().select).toBeDefined(); expect(item.emitted().select).toBeDefined();
expect(item.vm.open).toBe(false); expect(item.vm.open).toBe(true);
item.trigger("click"); item.trigger("click");
expect(item.vm.open).toBe(true); expect(item.vm.open).toBe(true);

View File

@ -7,7 +7,7 @@ exports[`Menu > should render 1`] = `
`; `;
exports[`Menu > should render 2`] = ` exports[`Menu > should render 2`] = `
"<li class=\\"menu-item\\"> "<li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\"></span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\"></span>
<!--v-if--> <!--v-if-->
@ -21,7 +21,7 @@ exports[`Menu > should render 2`] = `
exports[`Menu > should work with openIds prop 1`] = ` exports[`Menu > should work with openIds prop 1`] = `
"<div class=\\"menu-container w-full p-3\\"> "<div class=\\"menu-container w-full p-3\\">
<ul> <ul>
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 1</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 1</span>
<!--v-if--> <!--v-if-->
@ -30,7 +30,7 @@ exports[`Menu > should work with openIds prop 1`] = `
<ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul> <ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul>
</transition-stub> </transition-stub>
</li> </li>
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 2</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 2</span>
<!--v-if--> <!--v-if-->
@ -39,13 +39,13 @@ exports[`Menu > should work with openIds prop 1`] = `
<ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul> <ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul>
</transition-stub> </transition-stub>
</li> </li>
<li class=\\"has-submenus menu-item\\"> <li class=\\"has-submenus menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 3</span><span class=\\"open menu-icon-collapse self-center transition-all\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.2em\\" height=\\"1.2em\\"><path fill=\\"currentColor\\" d=\\"m13.171 12l-4.95-4.95l1.415-1.413L16 12l-6.364 6.364l-1.414-1.415l4.95-4.95Z\\"></path></svg></span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 3</span><span class=\\"open menu-icon-collapse self-center transition-all\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.2em\\" height=\\"1.2em\\"><path fill=\\"currentColor\\" d=\\"m13.171 12l-4.95-4.95l1.415-1.413L16 12l-6.364 6.364l-1.414-1.415l4.95-4.95Z\\"></path></svg></span>
</div> </div>
<transition-stub name=\\"submenus-show\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\"> <transition-stub name=\\"submenus-show\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\">
<ul class=\\"sub-menu-items transition-all\\"> <ul class=\\"sub-menu-items transition-all\\">
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 4</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 4</span>
<!--v-if--> <!--v-if-->
@ -64,7 +64,7 @@ exports[`Menu > should work with openIds prop 1`] = `
exports[`Menu > should work with sub menus 1`] = ` exports[`Menu > should work with sub menus 1`] = `
"<div class=\\"menu-container w-full p-3\\"> "<div class=\\"menu-container w-full p-3\\">
<ul> <ul>
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 1</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 1</span>
<!--v-if--> <!--v-if-->
@ -73,7 +73,7 @@ exports[`Menu > should work with sub menus 1`] = `
<ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul> <ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul>
</transition-stub> </transition-stub>
</li> </li>
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 2</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 2</span>
<!--v-if--> <!--v-if-->
@ -82,13 +82,13 @@ exports[`Menu > should work with sub menus 1`] = `
<ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul> <ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\"></ul>
</transition-stub> </transition-stub>
</li> </li>
<li class=\\"has-submenus menu-item\\"> <li class=\\"has-submenus menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 3</span><span class=\\"open menu-icon-collapse self-center transition-all\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.2em\\" height=\\"1.2em\\"><path fill=\\"currentColor\\" d=\\"m13.171 12l-4.95-4.95l1.415-1.413L16 12l-6.364 6.364l-1.414-1.415l4.95-4.95Z\\"></path></svg></span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 3</span><span class=\\"menu-icon-collapse self-center transition-all\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.2em\\" height=\\"1.2em\\"><path fill=\\"currentColor\\" d=\\"m13.171 12l-4.95-4.95l1.415-1.413L16 12l-6.364 6.364l-1.414-1.415l4.95-4.95Z\\"></path></svg></span>
</div> </div>
<transition-stub name=\\"submenus-show\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\"> <transition-stub name=\\"submenus-show\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\">
<ul class=\\"sub-menu-items transition-all\\"> <ul class=\\"sub-menu-items transition-all\\" style=\\"display: none;\\">
<li class=\\"menu-item\\"> <li class=\\"menu-item group\\">
<div class=\\"menu-item-title\\"> <div class=\\"menu-item-title\\">
<!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 4</span> <!--v-if--><span class=\\"menu-title flex-1 self-center\\">Menu Item 4</span>
<!--v-if--> <!--v-if-->