refactor(menu): code clean

This commit is contained in:
07akioni 2019-12-31 18:22:45 +08:00
parent f212d3f26c
commit eed89f91d6
19 changed files with 596 additions and 324 deletions

View File

@ -22,10 +22,10 @@
</n-sub-menu>
</n-sub-menu>
<n-sub-menu title="subMenu3" name="subMenu3">
<n-item-group title="group">
<n-menu-handleSelectup title="group">
<n-menu-item title="sub1" name="sub6"></n-menu-item>
<n-menu-item title="sub1" name="sub7"></n-menu-item>
</n-item-group>
</n-menu-handleSelectup>
</n-sub-menu>
</n-menu>
</div>

View File

@ -24,11 +24,26 @@ export default {
{
title: 'subMenu',
name: 'subMenu',
groupTitle: 'group1',
children: [
{
title:'sub1',
title:'group1',
name: 'sub1',
group: true,
children: [
{
title: 'subsub001',
name: 'subsub001'
},
{
title: 'subsub002',
name: 'subsub002'
}
]
},
{
title:'group2',
name: 'sub1',
group: true,
children: [
{
title: 'subsub001',

View File

@ -7,8 +7,7 @@
:defaultOpenNames="initOpenKeys"
@openNamesChange="changeOpen"
@select="changeSelect"
>
>
<template v-slot:drawer-header-icon>
<div style="overflow:hidden">1111</div>
</template>
@ -24,21 +23,20 @@
</n-sub-menu>
</n-sub-menu>
<n-sub-menu title="subMenu3" name="subMenu3">
<n-item-group title="group">
<n-menu-item-group title="group">
<n-menu-item title="sub1" name="sub6"></n-menu-item>
<n-menu-item title="sub1" name="sub7"></n-menu-item>
</n-item-group>
</n-menu-item-group>
</n-sub-menu>
</n-menu>
Items:
<n-menu
v-model="selected"
:openNames="opens"
:items="items"
@select="changeSelect"
@openNamesChange="changeOpen"
>
</n-menu>
v-model="selected"
:openNames="opens"
:items="items"
@select="changeSelect"
@openNamesChange="changeOpen"
/>
</div>
```
@ -58,10 +56,10 @@ export default {
{
title: 'subMenu',
name: 'subMenu',
groupTitle: 'group1',
children: [
{
title:'sub1',
group: true,
name: 'sub1',
children: [
{
@ -81,9 +79,11 @@ export default {
},
methods: {
changeOpen (names) {
this.opens = names
console.log('names', names)
},
changeSelect (val) {
changeSelect (name) {
this.selected = name
console.log('changeSelect', val)
}
}

View File

@ -29,11 +29,11 @@ export default {
{
title: 'subMenu',
name: 'subMenu',
groupTitle: 'group1',
children: [
{
title:'sub1',
name: 'sub1',
group: true,
children: [
{
title: 'subsub001',
@ -46,9 +46,9 @@ export default {
{
title: 'subMenu2',
name: 'subMenu2',
groupTitle: 'group1',
children: [
{
group: true,
title:'sub2',
name: 'sub2',
children: [
@ -63,9 +63,9 @@ export default {
{
title: 'subMenu3',
name: 'subMenu3',
groupTitle: 'group1',
children: [
{
group: true,
title:'sub3',
name: 'sub3',
children: [

View File

@ -3,11 +3,10 @@
Menu1:
<n-menu
v-model="selected"
:openNames="initOpenKeys"
:openNames="opens"
:items="items"
@select="changeSelect"
>
</n-menu>
/>
Menu2:
<n-menu
v-model="selected"
@ -15,15 +14,13 @@ Menu2:
:items="items"
@select="changeSelect"
@openNamesChange="changeOpen"
>
</n-menu>
/>
```
```js
export default {
data () {
return {
selected: 'sub1',
initOpenKeys: ['subMenu'],
opens: ['subMenu'],
items: [
{
@ -33,9 +30,9 @@ export default {
{
title: 'subMenu',
name: 'subMenu',
groupTitle: 'group1',
children: [
{
group: true,
title:'sub1',
name: 'sub1',
children: [

View File

@ -1,14 +1,13 @@
import Menu from './src/main.vue'
import MenuItem from './src/menuItem.vue'
import SubMenu from './src/subMenu.vue'
import ItemGroup from './src/itemGroup.vue'
import Menu from './src/MenuAdapter.vue'
import MenuItem from './src/MenuItem.vue'
import SubMenu from './src/SubMenu.vue'
import MenuItemGroup from './src/MenuItemGroup.vue'
Menu.install = function (Vue) {
// Menu.Item = MenuItem
Vue.component(Menu.name, Menu)
Vue.component(MenuItem.name, MenuItem)
Vue.component(SubMenu.name, SubMenu)
Vue.component(ItemGroup.name, ItemGroup)
Vue.component(MenuItemGroup.name, MenuItemGroup)
}
export default Menu

View File

@ -0,0 +1,88 @@
<template>
<div
class="n-menu"
:class="{
[`n-${synthesizedTheme}-theme`]: synthesizedTheme,
[`n-menu--${mode}`]: mode,
}"
>
<ul class="n-menu-list">
<slot />
</ul>
</div>
</template>
<script>
import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable'
export default {
name: 'Menu',
provide () {
return {
NMenu: this
}
},
mixins: [withapp, themeable],
props: {
value: {
type: String,
default: null
},
rootIndent: {
type: Number,
default: null
},
indent: {
type: Number,
default: 32
},
mode: {
type: String,
default: 'vertical'
},
defaultOpenNames: {
type: Array,
default: undefined
},
openNames: {
type: Array,
default: undefined
}
// hasIcon: {
// type: Boolean,
// default: false
// }
},
data () {
return {
internalOpenNames: this.openNames || this.defaultOpenNames || []
}
},
computed: {
synthesizedOpenNames () {
if (this.openNames !== undefined) return this.openNames || []
else return this.internalOpenNames
}
},
methods: {
handleSelect (value) {
this.$emit('select', value)
this.$emit('input', value)
},
handleOpenNamesChange (name) {
const currentOpenNames = Array.from(this.synthesizedOpenNames)
const index = currentOpenNames.findIndex(openName => openName === name)
if (~index) {
currentOpenNames.splice(index, 1)
} else {
currentOpenNames.push(name)
}
if (this.openNames === undefined) {
this.internalOpenNames = currentOpenNames
}
this.$emit('openNamesChange', currentOpenNames)
}
}
}
</script>

View File

@ -0,0 +1,69 @@
<script>
import Menu from './Menu.vue'
import MenuItem from './MenuItem.vue'
import SubMenu from './SubMenu.vue'
import MenuItemGroup from './MenuItemGroup.vue'
export default {
name: 'NMenu',
functional: true,
render (h, context) {
if (context.props.items) {
const createItems = items => {
return items.map(item => {
const props = {
title: item.title,
name: item.name,
disabled: !!item.disabled
}
if (item.children) {
const scopedSlots = {}
if (typeof item.title === 'function') {
delete props.title
scopedSlots.header = item.title
}
if (item.group) {
return h(MenuItemGroup, {
props,
scopedSlots
}, createItems(item.children))
} else {
return h(SubMenu, {
props,
scopedSlots
}, createItems(item.children))
}
} else {
const scopedSlots = {}
if (typeof item.title === 'function') {
delete props.title
scopedSlots.default = item.title
}
return h(MenuItem, {
props,
scopedSlots
})
}
})
}
return h(Menu,
{
props: context.props,
scopedSlots: { ...context.scopedSlots },
on: context.listeners,
attrs: context.data.attrs
},
createItems(context.props.items)
)
} else {
return h(Menu, {
props: context.props,
scopedSlots: { ...context.scopedSlots },
on: context.listeners,
attrs: context.data.attrs
})
}
}
}
</script>

View File

@ -0,0 +1,91 @@
<template>
<li
class="n-menu-item"
:style="{ paddingLeft: paddingLeft + 'px' }"
:class="{
'n-menu-item--selected': isSelected,
'n-menu-item--disabled': synthesizedDisabled
}"
@click="handleClick"
>
<!-- <span
v-if="hasIcon"
class="n-menu-title-icon"
/> -->
<slot>
<render :render="title" />
</slot>
</li>
</template>
<script>
import registerable from '../../../mixins/registerable'
import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable'
import render from '../../../utils/render'
export default {
name: 'NMenuItem',
components: {
render
},
mixins: [
registerable('NMenu'),
withapp,
themeable
],
inject: {
NMenu: {
default: null
},
NSubMenu: {
default: null
},
NMenuItemGroup: {
default: null
}
},
props: {
title: {
type: [String, Function],
default: null
},
name: {
type: String,
required: true
},
disabled: {
type: Boolean,
default: false
}
},
computed: {
paddingLeft () {
if (this.NMenuItemGroup) {
return this.NMenu.indent / 2 + this.NMenuItemGroup.paddingLeft
} else if (this.NSubMenu) {
return this.NMenu.indent + this.NSubMenu.paddingLeft
} else {
return this.NMenu.rootIndent || this.NMenu.indent
}
},
synthesizedDisabled () {
return ((this.NSubMenu && this.NSubMenu.synthesizedDisabled) || this.disabled)
},
isSelected () {
if (this.NMenu.value === this.name) {
return true
} else {
return false
}
}
},
methods: {
handleClick () {
if (!this.synthesizedDisabled) {
this.NMenu.handleSelect(this.name)
this.$emit('click', this)
}
}
}
}
</script>

View File

@ -0,0 +1,54 @@
<template>
<li class="n-menu-item-group">
<span class="n-menu-item-group-title" :style="{ paddingLeft: paddingLeft + 'px' }">
<slot name="header"><render :render="title" /></slot>
</span>
<div>
<slot />
</div>
</li>
</template>
<script>
import render from '../../../utils/render'
export default {
name: 'NMenuItemGroup',
components: {
render
},
props: {
title: {
type: [String, Function],
default: null
}
},
provide () {
return {
NMenuItemGroup: this,
NSubMenu: null
}
},
inject: {
NMenuItemGroup: {
default: null
},
NMenu: {
default: null
},
NSubMenu: {
default: null
}
},
computed: {
paddingLeft () {
if (this.NMenuItemGroup) {
return this.NMenu.indent / 2 + this.NMenuItemGroup.paddingLeft
} else if (this.NSubMenu) {
return this.NMenu.indent / 2 + this.NSubMenu.paddingLeft
} else {
return (this.NMenu.rootIndent || this.NMenu.indent) / 2
}
}
}
}
</script>

View File

@ -0,0 +1,100 @@
<template>
<li
class="n-sub-menu"
>
<div
class="n-sub-menu-header"
:style="{paddingLeft: paddingLeft + 'px'}"
:class="{
'n-sub-menu-header--collapsed': isCollapsed,
'n-sub-menu-header--active': !isCollapsed,
'n-sub-menu-header--disabled': disabled,
}"
@click="handleClick"
>
<!-- <span
v-if="hasIcon"
class="n-menu-title-icon"
/> -->
<slot name="header">
<render :render="title" />
</slot>
</div>
<fade-in-height-expand-transition>
<ul
v-if="!isCollapsed"
class="n-sub-menu-content"
>
<slot />
</ul>
</fade-in-height-expand-transition>
</li>
</template>
<script>
import FadeInHeightExpandTransition from '../../../transition/FadeInHeightExpandTransition'
import render from '../../../utils/render'
export default {
name: 'NSubMenu',
provide () {
return {
NSubMenu: this,
NMenuItemGroup: null
}
},
components: {
FadeInHeightExpandTransition,
render
},
inject: {
NMenu: {
default: null
},
NSubMenu: {
default: null
},
NMenuItemGroup: {
default: null
}
},
props: {
title: {
type: [String, Function],
default: null
},
name: {
type: String,
required: true
},
disabled: {
type: Boolean,
default: false
}
},
computed: {
synthesizedDisabled () {
return (this.NMenu && this.NMenu.disabled) || this.disabled
},
paddingLeft () {
if (this.NMenuItemGroup) {
return this.NMenu.indent / 2 + this.NMenuItemGroup.paddingLeft
} else if (this.NSubMenu) {
return this.NMenu.indent + this.NSubMenu.paddingLeft
} else {
return this.NMenu.rootIndent || this.NMenu.indent
}
},
isCollapsed () {
return !(this.NMenu.synthesizedOpenNames.includes(this.name))
}
},
methods: {
handleClick () {
if (!this.disabled) {
this.NMenu.handleOpenNamesChange(this.name)
this.$emit('click', this)
}
}
}
}
</script>

View File

@ -1,38 +0,0 @@
<template>
<li class="n-menu-item-group">
<span class="n-menu-item-group-title" :style="{paddingLeft: paddingLeft + 'px'}">
{{ title }}
</span>
<div>
<slot />
</div>
</li>
</template>
<script>
export default {
name: 'NItemGroup',
props: {
title: {
type: String,
default: null
}
},
inject: {
NMenu: {
default: null
},
NSubMenu: {
default: null
}
},
computed: {
paddingLeft () {
let padding = this.NMenu.indent / 2
if (this.NSubMenu) {
padding = padding + this.NSubMenu.paddingLeft
}
return padding
}
}
}
</script>

View File

@ -1,65 +0,0 @@
<script>
import Menu from './menu.vue'
import MenuItem from './menuItem.vue'
import SubMenu from './subMenu.vue'
import ItemGroup from './itemGroup.vue'
export default {
name: 'NMenu',
functional: true,
render (h, context) {
if (context.props.items && !(context.$slots && context.$slots.default && context.$slots.default.length)) {
let test = function (list) {
return list.map(function (item, index) {
let props = {
title: item.title,
name: item.name,
disabled: !!item.disabled
}
if (item.children) {
if (item.groupTitle) {
let groupProps = {
title: item.groupTitle
}
return h(SubMenu, {
props: props
},
[
h(ItemGroup, {
props: groupProps
}, test(item.children))
]
)
} else {
return h(SubMenu, {
props: props
},
test(item.children)
)
}
} else {
return h(MenuItem, {
props: props
})
}
})
}
return h(Menu,
{
props: context.props,
scopedSlots: context.scopedSlots,
on: context.listeners
},
test(context.props.items)
)
} else {
return h(Menu, {
props: context.props,
scopedSlots: context.scopedSlots,
on: context.listeners
})
}
}
}
</script>

View File

@ -3,30 +3,12 @@
class="n-menu"
:class="{
[`n-${synthesizedTheme}-theme`]: synthesizedTheme,
'n-menu--collapsed': isCollapsed,
'n-menu--active': !isCollapsed,
[`n-menu--${mode}`]: mode,
}"
>
<div
class="n-menu-container"
:class="{
'n-menu-container--collapsed': isCollapsed,
'n-menu-container--active': !isCollapsed,
}"
>
<div
class="n-menu-content"
:class="{
[`n-menu-content--${mode}`]: mode,
}"
>
<ul class="n-menu-list">
<slot />
</ul>
</div>
</div>
<ul class="n-menu-list">
<slot />
</ul>
</div>
</template>
@ -47,6 +29,10 @@ export default {
type: String,
default: null
},
rootIndent: {
type: Number,
default: null
},
indent: {
type: Number,
default: 32
@ -57,56 +43,45 @@ export default {
},
defaultOpenNames: {
type: Array,
default: () => {
return undefined
}
default: undefined
},
openNames: {
type: Array,
default: () => {
return undefined
}
},
hasIcon: {
type: Boolean,
default: false
default: undefined
}
// hasIcon: {
// type: Boolean,
// default: false
// }
},
data () {
return {
componentName: 'NMenu',
isCollapsed: false,
currentOpenNames: this.openNames || this.defaultOpenNames || []
internalOpenNames: this.openNames || this.defaultOpenNames || []
}
},
watch: {
openNames (val) {
this.currentOpenNames = val
},
defaultOpenNames (val) {
this.currentOpenNames = val
computed: {
synthesizedOpenNames () {
if (this.openNames !== undefined) return this.openNames || []
else return this.internalOpenNames
}
},
methods: {
toggle () {
this.isCollapsed = !this.isCollapsed
},
changeSelect (value) {
handleSelect (value) {
this.$emit('select', value)
this.$emit('input', value)
},
openKeysChangeCallback (val) {
let indexs = [...this.currentOpenNames]
if (indexs.includes(val)) {
indexs.splice(indexs.findIndex(item => item === val), 1)
handleOpenNamesChange (name) {
const currentOpenNames = Array.from(this.synthesizedOpenNames)
const index = currentOpenNames.findIndex(openName => openName === name)
if (~index) {
currentOpenNames.splice(index, 1)
} else {
indexs.push(val)
currentOpenNames.push(name)
}
if (typeof (this.openNames) === 'undefined') {
this.currentOpenNames = indexs
if (this.openNames === undefined) {
this.internalOpenNames = currentOpenNames
}
this.$emit('openNamesChange', indexs)
this.$emit('openNamesChange', currentOpenNames)
}
}
}

View File

@ -1,28 +1,33 @@
<template>
<li
class="n-menu-item"
:style="{paddingLeft: paddingLeft + 'px'}"
:style="{ paddingLeft: paddingLeft + 'px' }"
:class="{
'n-menu-item--selected': isSelected,
'n-menu-item--disabled': isDisabled
'n-menu-item--disabled': synthesizedDisabled
}"
@click="handleClick"
>
<span
<!-- <span
v-if="hasIcon"
class="n-menu-title-icon"
/>
<span>{{ title }}</span>
/> -->
<slot>
<render :render="title" />
</slot>
</li>
</template>
<script>
import registerable from '../../../mixins/registerable'
import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable'
import render from '../../../utils/render'
export default {
name: 'NMenuItem',
componentName: 'NMenuItem',
components: {
render
},
mixins: [
registerable('NMenu'),
withapp,
@ -34,11 +39,14 @@ export default {
},
NSubMenu: {
default: null
},
NMenuItemGroup: {
default: null
}
},
props: {
title: {
type: String,
type: [String, Function],
default: null
},
name: {
@ -51,18 +59,17 @@ export default {
}
},
computed: {
hasIcon () {
return this.NMenu.hasIcon && this.$parent.componentName === 'NMenu'
},
paddingLeft () {
let padding = this.NMenu.indent
if (this.NSubMenu) {
padding = padding + this.NSubMenu.paddingLeft
if (this.NMenuItemGroup) {
return this.NMenu.indent / 2 + this.NMenuItemGroup.paddingLeft
} else if (this.NSubMenu) {
return this.NMenu.indent + this.NSubMenu.paddingLeft
} else {
return this.NMenu.rootIndent || this.NMenu.indent
}
return padding
},
isDisabled () {
return ((this.NSubMenu && this.NSubMenu.disabled) || this.disabled)
synthesizedDisabled () {
return ((this.NSubMenu && this.NSubMenu.synthesizedDisabled) || this.disabled)
},
isSelected () {
if (this.NMenu.value === this.name) {
@ -74,8 +81,8 @@ export default {
},
methods: {
handleClick () {
if (!this.isDisabled) {
this.NMenu.changeSelect(this.name)
if (!this.synthesizedDisabled) {
this.NMenu.handleSelect(this.name)
this.$emit('click', this)
}
}

View File

@ -8,16 +8,17 @@
:class="{
'n-sub-menu-header--collapsed': isCollapsed,
'n-sub-menu-header--active': !isCollapsed,
'n-sub-menu-header--has-icon': hasIcon,
'n-sub-menu-header--disabled': disabled,
}"
@click="handleClick"
>
<span
<!-- <span
v-if="hasIcon"
class="n-menu-title-icon"
/>
<span>{{ title }}</span>
/> -->
<slot name="header">
<render :render="title" />
</slot>
</div>
<fade-in-height-expand-transition>
<ul
@ -31,16 +32,19 @@
</template>
<script>
import FadeInHeightExpandTransition from '../../../transition/FadeInHeightExpandTransition'
import render from '../../../utils/render'
export default {
name: 'NSubMenu',
provide () {
return {
NSubMenu: this
NSubMenu: this,
NMenuItemGroup: null
}
},
components: {
FadeInHeightExpandTransition
FadeInHeightExpandTransition,
render
},
inject: {
NMenu: {
@ -48,11 +52,14 @@ export default {
},
NSubMenu: {
default: null
},
NMenuItemGroup: {
default: null
}
},
props: {
title: {
type: String,
type: [String, Function],
default: null
},
name: {
@ -65,24 +72,26 @@ export default {
}
},
computed: {
hasIcon () {
return this.NMenu.haIcon && this.$parent.$options.name === 'NMenu'
synthesizedDisabled () {
return (this.NMenu && this.NMenu.disabled) || this.disabled
},
paddingLeft () {
let padding = this.NMenu.indent
if (this.NSubMenu) {
padding = padding + this.NSubMenu.paddingLeft
if (this.NMenuItemGroup) {
return this.NMenu.indent / 2 + this.NMenuItemGroup.paddingLeft
} else if (this.NSubMenu) {
return this.NMenu.indent + this.NSubMenu.paddingLeft
} else {
return this.NMenu.rootIndent || this.NMenu.indent
}
return padding
},
isCollapsed () {
return !(this.NMenu.currentOpenNames.includes(this.name))
return !(this.NMenu.synthesizedOpenNames.includes(this.name))
}
},
methods: {
handleClick () {
if (!this.disabled) {
this.NMenu.openKeysChangeCallback(this.name)
this.NMenu.handleOpenNamesChange(this.name)
this.$emit('click', this)
}
}

View File

@ -2,110 +2,75 @@
@import './mixins/mixins.scss';
@import './themes/vars.scss';
$layout-nav-height: 64px;
@include themes-mixin() {
@include b(menu) {
width: 100%;
transition:width .3s;
@include b(menu-container) {
transition: transform .3s $--n-ease-in-out-cubic-bezier, opacity .3s $--n-ease-in-out-cubic-bezier, background-color .3s $--n-ease-in-out-cubic-bezier, border-color .3s $--n-ease-in-out-cubic-bezier;
@include b(menu-divider) {
margin: 0px 25px;
border-bottom: 1px solid rgba(255, 255, 255, .08);
}
@include b(menu-content) {
overflow: hidden;
transition: opacity .3s $--n-ease-in-out-cubic-bezier;
@include b(menu-list) {
list-style: none;
margin: 0;
padding: 0;
@include b(menu-item) {
cursor: pointer;
padding-left: 24px;
position: relative;
padding-top: 16px;
padding-bottom: 16px;
// padding-left: 48px;
font-size: 14px;
list-style: none;
@include e(icon) {
&::before {
content: '';
width: 10px;
height: 10px;
position: absolute;
background-image:linear-gradient(47deg,rgba(120, 205, 104, 1) 0%,rgba(20, 166, 165, 1) 100%);
top: 20px;
left: 30px;
-webkit-clip-path: polygon(100% 0, 100% 100%, 0% 100%);
clip-path: polygon(100% 0, 100% 100%, 0% 100%);
}
}
// @include m(selected) {
// background-image: $menu-item-selected-background-image;
// }
&::before { // item background
content: "";
background-size: 300%;
background-image: $menu-item-selected-background-image;
background-position: $--menu-item-background-position;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 0;
transition: opacity 0.3s $--n-ease-in-out-cubic-bezier, background-position .3s $--n-ease-in-out-cubic-bezier;
opacity: 0;
}
@include m(selected) {
&::before {
opacity: .9;
}
}
@include m(disabled) {
opacity: 0.45;
cursor: not-allowed;
}
box-sizing: border-box;
font-size: 14px;
@include b(menu-list) {
list-style: none;
margin: 0;
padding: 0;
@include b(menu-item) {
cursor: pointer;
color: $--menu-item-text-color;
transition: color .3s $--n-ease-in-out-cubic-bezier;
position: relative;
height: 48px;
display: flex;
align-items: center;
font-size: 14px;
list-style: none;
line-height: 1.5;
@include e(icon) {
&::before {
content: '';
width: 10px;
height: 10px;
position: absolute;
background-image:linear-gradient(47deg,rgba(120, 205, 104, 1) 0%,rgba(20, 166, 165, 1) 100%);
top: 20px;
left: 30px;
clip-path: polygon(100% 0, 100% 100%, 0% 100%);
}
}
@include m(horizontal) {
@include b(menu-header) {
display: none;
}
@include b(menu-list) {
> * {
float: left;
}
&::before {
content: "";
background-size: 300%;
background-image: $--menu-item-background-image;
background-position: $--menu-item-background-position;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 0;
transition: opacity 0.3s $--n-ease-in-out-cubic-bezier, background-position .3s $--n-ease-in-out-cubic-bezier;
opacity: 0;
}
@include m(selected) {
&::before {
opacity: .9;
}
}
}
}
@include b(menu-title-icon) {
width: 10px;
height: 10px;
margin-right: 10px;
&::before {
content: '';
width: 10px;
height: 10px;
background-image: linear-gradient(47deg, #78cd68 0%, #14a6a5 100%);
display: inline-block;
-webkit-clip-path: polygon(100% 0, 100% 100%, 0% 100%);
clip-path: polygon(100% 0, 100% 100%, 0% 100%);
@include m(disabled) {
opacity: 0.45;
cursor: not-allowed;
}
}
}
@include b(sub-menu) {
cursor: pointer;
font-size: 14px;
position: relative;
@include b(sub-menu-header) {
font-weight: 500;
font-size: 14px;
color: $--menu-sub-menu-text-color;
transition: color .3s $--n-ease-in-out-cubic-bezier;
height: 48px;
display: flex;
align-items: center;
position: relative;
padding: 16px 0;
&::after { // down arrow
content: '';
height: 6px;
@ -113,15 +78,15 @@ $layout-nav-height: 64px;
border-left: 2px solid $--n-primary-color;
border-top: 2px solid $--n-primary-color;
position: absolute;
right: 20px;
right: 24px;
top: calc(50% - 3px);
transform: rotate(45deg) ;
transform-origin: 25% 25%;
transition: transform 0.3s $--n-ease-in-out-cubic-bezier, opacity 0.3s $--n-ease-in-out-cubic-bezier, border-color 0.3s $--n-ease-in-out-cubic-bezier;
transition: transform 0.2s $--n-ease-in-out-cubic-bezier, opacity 0.3s $--n-ease-in-out-cubic-bezier, border-color 0.3s $--n-ease-in-out-cubic-bezier;
}
@include m(collapsed) {
&::after {
transform: rotate(225deg) ;
transform: rotate(225deg);
}
}
@include m(disabled) {
@ -131,15 +96,17 @@ $layout-nav-height: 64px;
}
@include b(sub-menu-content) {
padding: 0;
@include fade-in-height-expand-transition();
@include fade-in-height-expand-transition($duration: .2s);
}
}
@include b(menu-item-group) {
@include b(menu-item-group-title) {
display: block;
padding-top: 16px;
padding-bottom: 16px;
color: #999;
cursor: default;
height: 40px;
display: flex;
align-items: center;
color: $--menu-item-group-text-color;
transition: color .3s $--n-ease-in-out-cubic-bezier;
}
}
}

View File

@ -1,5 +1,7 @@
@mixin setup-dark-menu {
$menu-background-color: $--n-card-color !global;
$menu-item-selected-background-image: linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .03) 40%, rgba(0, 0, 0, .09) 60%, rgba(0, 0, 0, .09) 100%) !global;
$--menu-item-background-image: linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .03) 40%, rgba(0, 0, 0, .09) 60%, rgba(0, 0, 0, .09) 100%) !global;
$--menu-item-background-position: 0% !global;
$--menu-item-group-text-color: $--n-meta-text-color !global;
$--menu-item-text-color: $--n-secondary-text-color !global;
$--menu-sub-menu-text-color: $--n-text-color !global;
}

View File

@ -1,5 +1,7 @@
@mixin setup-light-menu {
$menu-background-color: $--neutral-10 !global;
$menu-item-selected-background-image: linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .03) 40%, rgba(0, 0, 0, .09) 60%, rgba(0, 0, 0, .09) 100%) !global;
$--menu-item-background-image: linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .03) 40%, rgba(0, 0, 0, .09) 60%, rgba(0, 0, 0, .09) 100%) !global;
$--menu-item-background-position: 100% !global;
$--menu-item-group-text-color: $--n-meta-text-color !global;
$--menu-item-text-color: $--n-secondary-text-color !global;
$--menu-sub-menu-text-color: $--n-text-color !global;
}