diff --git a/src/_styles/new-common/light.js b/src/_styles/new-common/light.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/dropdown/src/Dropdown.js b/src/dropdown/src/Dropdown.js index b4daaa111..c1cea0466 100644 --- a/src/dropdown/src/Dropdown.js +++ b/src/dropdown/src/Dropdown.js @@ -203,7 +203,9 @@ export default defineComponent({ [createKey('optionIconPrefixWidth', size)]: optionIconPrefixWidth, [createKey('optionPrefixWidth', size)]: optionPrefixWidth, [createKey('fontSize', size)]: fontSize, - [createKey('optionHeight', size)]: optionHeight + [createKey('optionHeight', size)]: optionHeight, + [createKey('optionIconSize', size)]: optionIconSize, + [createKey('groupHeaderFontSize', size)]: groupHeaderFontSize } } = themeRef.value return { @@ -223,7 +225,9 @@ export default defineComponent({ '--option-text-color': optionTextColor, '--prefix-color': prefixColor, '--suffix-color': suffixColor, - '--group-header-text-color': groupHeaderTextColor + '--group-header-text-color': groupHeaderTextColor, + '--group-header-font-size': groupHeaderFontSize, + '--option-icon-size': optionIconSize } }) } diff --git a/src/dropdown/src/DropdownGroupHeader.js b/src/dropdown/src/DropdownGroupHeader.js index 85fa4aea7..8cbc97d28 100644 --- a/src/dropdown/src/DropdownGroupHeader.js +++ b/src/dropdown/src/DropdownGroupHeader.js @@ -44,7 +44,8 @@ export default defineComponent({ class: 'n-dropdown-option-body__label', 'n-dropdown-option': true }, - [h(render, { render: rawNode.label })] + // TODO: Workaround, menu campatible + [h(render, { render: rawNode.label ?? rawNode.title })] ), h('div', { class: [ diff --git a/src/dropdown/src/DropdownOption.js b/src/dropdown/src/DropdownOption.js index 527e9eb74..985cf7d23 100644 --- a/src/dropdown/src/DropdownOption.js +++ b/src/dropdown/src/DropdownOption.js @@ -122,6 +122,7 @@ export default defineComponent({ render () { const { NDropdown: { animated }, + rawNode, mergedShowSubmenu } = this const submenuVNode = mergedShowSubmenu @@ -163,7 +164,7 @@ export default defineComponent({ ], 'n-dropdown-option': true }, - [h(render, { render: this.rawNode.icon })] + [h(render, { render: rawNode.icon })] ), h( 'div', @@ -171,7 +172,8 @@ export default defineComponent({ class: 'n-dropdown-option-body__label', 'n-dropdown-option': true }, - [h(render, { render: this.rawNode.label })] + // TODO: Workaround, menu campatible + [h(render, { render: rawNode.label ?? rawNode.title })] ), h( 'div', diff --git a/src/dropdown/src/styles/index.cssr.js b/src/dropdown/src/styles/index.cssr.js index 3c49e282c..4b4469c47 100644 --- a/src/dropdown/src/styles/index.cssr.js +++ b/src/dropdown/src/styles/index.cssr.js @@ -18,6 +18,7 @@ import fadeInScaleUpTransition from '../../../_styles/transitions/fade-in-scale- // --option-text-color // --prefix-color // --suffix-color +// --option-icon-size export default cB('dropdown-menu', { transformOrigin: 'inherit', padding: 'var(--padding)', @@ -46,6 +47,7 @@ export default cB('dropdown-menu', { backgroundColor: 'var(--option-color-hover)' }), cM('group', { + fontSize: 'calc(var(--font-size) - 1px)', color: 'var(--group-header-text-color)' }, [ cE('prefix', { @@ -68,7 +70,7 @@ export default cB('dropdown-menu', { cB('icon', { transition: 'color .3s var(--bezier)', color: 'var(--prefix-color)', - fontSize: '16px' + fontSize: 'var(--option-icon-size)' }) ]), cE('label', { @@ -91,7 +93,7 @@ export default cB('dropdown-menu', { cB('icon', { transition: 'color .3s var(--bezier)', color: 'var(--suffix-color)', - fontSize: '16px' + fontSize: 'var(--option-icon-size)' }) ]), cB('dropdown-menu', { diff --git a/src/dropdown/styles/_common.js b/src/dropdown/styles/_common.js index b1a906382..79be2487c 100644 --- a/src/dropdown/styles/_common.js +++ b/src/dropdown/styles/_common.js @@ -1,5 +1,9 @@ export default { padding: '4px 0', + optionIconSizeSmall: '14px', + optionIconSizeMedium: '16px', + optionIconSizeLarge: '16px', + optionIconSizeHuge: '18px', optionSuffixWidthSmall: '28px', optionSuffixWidthMedium: '28px', optionSuffixWidthLarge: '32px', diff --git a/src/menu/src/Menu.js b/src/menu/src/Menu.js index b0f99bd92..970d7c23d 100644 --- a/src/menu/src/Menu.js +++ b/src/menu/src/Menu.js @@ -1,4 +1,12 @@ -import { h, nextTick, ref, toRef, computed, onMounted } from 'vue' +import { + h, + nextTick, + ref, + toRef, + computed, + onMounted, + defineComponent +} from 'vue' import { createTreeMate } from 'treemate' import { useCompitable, useMergedState } from 'vooks' import { useTheme } from '../../_mixins' @@ -6,7 +14,7 @@ import { itemRenderer } from './utils' import { menuLight } from '../styles' import style from './styles/index.cssr.js' -export default { +export default defineComponent({ name: 'Menu', provide () { return { @@ -244,4 +252,4 @@ export default { this.tmNodes.map((tmNode) => itemRenderer(tmNode)) ) } -} +}) diff --git a/src/menu/src/MenuItem.vue b/src/menu/src/MenuItem.vue index 9edfe82fb..c2e86a4ef 100644 --- a/src/menu/src/MenuItem.vue +++ b/src/menu/src/MenuItem.vue @@ -8,8 +8,8 @@ > diff --git a/src/menu/src/MenuItemGroup.js b/src/menu/src/MenuItemGroup.js index 09303bf0d..d65effbdd 100644 --- a/src/menu/src/MenuItemGroup.js +++ b/src/menu/src/MenuItemGroup.js @@ -1,9 +1,9 @@ -import { h } from 'vue' +import { h, defineComponent } from 'vue' import { render } from '../../_utils' import { itemRenderer } from './utils' import menuChildMixin from './menu-child-mixin' -export default { +export default defineComponent({ name: 'MenuItemGroup', mixins: [menuChildMixin], provide () { @@ -44,4 +44,4 @@ export default { ] ) } -} +}) diff --git a/src/menu/src/Submenu.js b/src/menu/src/Submenu.js index 28ef3a40c..bbed16491 100644 --- a/src/menu/src/Submenu.js +++ b/src/menu/src/Submenu.js @@ -1,13 +1,13 @@ -import { h, withDirectives, vShow, ref } from 'vue' +import { h, withDirectives, vShow, ref, defineComponent } from 'vue' import { NFadeInExpandTransition } from '../../_base' -import { NPopover } from '../../popover' +import { NDropdown } from '../../dropdown' import NMenuItemContent from './MenuItemContent.vue' import menuChildMixin from './menu-child-mixin' import { itemRenderer } from './utils' import { useMemo } from 'vooks' import { useInjectionRef } from '../../_utils/composable' -export default { +export default defineComponent({ name: 'Submenu', mixins: [menuChildMixin], provide () { @@ -17,6 +17,14 @@ export default { } }, props: { + rawNodes: { + type: Array, + required: true + }, + tmNodes: { + type: Array, + required: true + }, extra: { type: [String, Function], default: undefined @@ -25,10 +33,6 @@ export default { type: Boolean, default: false }, - tmNodes: { - type: Array, - required: true - }, icon: { type: Function, default: undefined @@ -41,10 +45,10 @@ export default { setup (props) { const activePathRef = useInjectionRef('NMenu', 'activePath') return { - selectedInside: useMemo(() => { + childActive: useMemo(() => { return activePathRef.value.includes(props.internalKey) }), - popoverShow: ref(false) + dropdownShow: ref(false) } }, computed: { @@ -56,13 +60,12 @@ export default { }, collapsed () { if (this.horizontal) return false - if (this.insidePopover) return false if (this.menuCollapsed) { return true } return !this.NMenu.mergedExpandedKeys.includes(this.internalKey) }, - popoverEnabled () { + dropdownEnabled () { return !this.mergedDisabled && (this.horizontal || this.menuCollapsed) } }, @@ -80,7 +83,7 @@ export default { } }, handlePopoverShowChange (value) { - this.popoverShow = value + this.dropdownShow = value } }, render () { @@ -94,11 +97,10 @@ export default { title, extra, horizontal, - selectedInside, + childActive, icon, handleClick, - popoverShow, - insidePopover + dropdownShow } = this return h(NMenuItemContent, { paddingLeft: delayedPaddingLeft, @@ -108,15 +110,14 @@ export default { activeIconSize, title, extra, - showArrow: !horizontal && !insidePopover, - uncollapsable: insidePopover, - childActive: selectedInside, + showArrow: !horizontal, + childActive: childActive, icon, - hover: popoverShow, + hover: dropdownShow, onClick: handleClick }) } - const createSubmenuChildren = (insidePopover = false) => { + const createSubmenuChildren = () => { return h(NFadeInExpandTransition, null, { default: () => { const { tmNodes, collapsed } = this @@ -126,27 +127,31 @@ export default { { class: 'n-submenu-children' }, - tmNodes.map((item) => itemRenderer(item, insidePopover)) + tmNodes.map((item) => itemRenderer(item)) ), - [[vShow, insidePopover || !collapsed]] + [[vShow, !collapsed]] ) } }) } return this.root ? h( - NPopover, + NDropdown, { - class: 'n-menu-popover', + builtinThemeOverrides: { + fontSizeLarge: '14px', + optionIconSizeLarge: '18px' + }, + size: 'large', trigger: 'hover', - disabled: !this.popoverEnabled, - placement: this.popoverPlacement, - showArrow: false, - padded: false, - 'onUpdate:show': this.handlePopoverShowChange + disabled: !this.dropdownEnabled, + placement: this.dropdownPlacement, + 'onUpdate:show': this.handlePopoverShowChange, + options: this.rawNodes, + onSelect: this.NMenu.doSelect }, { - trigger: () => + default: () => h( 'div', { @@ -154,18 +159,9 @@ export default { }, [ createSubmenuItem(), - !this.horizontal ? createSubmenuChildren() : null + this.horizontal ? null : createSubmenuChildren() ] - ), - default: () => { - return h( - 'div', - { - class: 'n-menu' - }, - createSubmenuChildren(true) ) - } } ) : h( @@ -176,4 +172,4 @@ export default { [createSubmenuItem(), createSubmenuChildren()] ) } -} +}) diff --git a/src/menu/src/menu-child-mixin.js b/src/menu/src/menu-child-mixin.js index a66901a70..295635d97 100644 --- a/src/menu/src/menu-child-mixin.js +++ b/src/menu/src/menu-child-mixin.js @@ -28,10 +28,6 @@ export default { title: { type: [String, Function], default: undefined - }, - insidePopover: { - type: Boolean, - default: false } }, data () { @@ -53,7 +49,7 @@ export default { horizontal () { return this.NMenu.mode === 'horizontal' }, - popoverPlacement () { + dropdownPlacement () { if (this.horizontal) { return 'bottom' } @@ -84,7 +80,6 @@ export default { return collapsedIconSize === undefined ? iconSize : collapsedIconSize }, paddingLeft () { - // TODO handle popover const { NMenu: { collapsedWidth, indent, rootIndent }, NSubmenu, @@ -92,11 +87,8 @@ export default { root, horizontal, collapsedIconSize, - menuCollapsed, - insidePopover, - level + menuCollapsed } = this - if (insidePopover && level === 1) return 18 const mergedRootIndent = rootIndent === undefined ? indent : rootIndent const menuCollapsedPaddingLeft = collapsedWidth / 2 - collapsedIconSize / 2 diff --git a/src/menu/src/styles/index.cssr.js b/src/menu/src/styles/index.cssr.js index 22b413849..052c8a6b2 100644 --- a/src/menu/src/styles/index.cssr.js +++ b/src/menu/src/styles/index.cssr.js @@ -22,268 +22,258 @@ import fadeInHeightExpandTransition from '../../../_styles/transitions/fade-in-h // --item-text-color-child-active // --item-extra-text-color-child-active // --item-icon-color-child-active -export default c([ - cB('menu-popover', { - minWidth: '180px' - }), - cB('menu', { - color: 'var(--item-text-color)', - overflow: 'hidden', - transition: 'background-color .3s var(--bezier)', - width: '100%', - boxSizing: 'border-box', - fontSize: 'var(--font-size)', - paddingBottom: '6px' - }, [ - cM('transition-disabled', [ - cB('menu-item-content', [ - cE('icon', { - transition: 'none !important' - }) - ]), - cB('menu-item-content-header', { +export default cB('menu', { + color: 'var(--item-text-color)', + overflow: 'hidden', + transition: 'background-color .3s var(--bezier)', + width: '100%', + boxSizing: 'border-box', + fontSize: 'var(--font-size)', + paddingBottom: '6px' +}, [ + cM('transition-disabled', [ + cB('menu-item-content', [ + cE('icon', { transition: 'none !important' - }, [ - cE('extra', { - transition: 'none !important' - }) - ]) + }) ]), - cM('horizontal', { - display: 'flex', - paddingBottom: 0 + cB('menu-item-content-header', { + transition: 'none !important' }, [ - cB('submenu', { - margin: 0 - }), - cB('menu-item', { - margin: 0 - }, [ - c('&::after', { - backgroundColor: 'transparent !important' - }), - cM('selected', [ - cB('menu-item-content', { - borderBottom: '2px solid var(--border-color-horizontal)' - }) - ]) - ]), - cB('menu-item-content', { - padding: '0 20px', - borderBottom: '2px solid transparent' - }, [ - cM('child-selected', { - borderBottom: '2px solid var(--border-color-horizontal)' - }), - cNotM('disabled', [ - hoverStyle({ - borderBottom: '2px solid var(--border-color-horizontal)' - }) - ]) - ]) - ]), - cM('collapsed', [ - cB('menu-item', [ - c('&::after', { - backgroundColor: 'transparent !important' - }) - ]), - cB('menu-item-content', [ - cB('menu-item-content-header', { - opacity: 0 - }), - cE('arrow', { - opacity: 0 - }), - cE('icon', { - color: 'var(--item-icon-color-collapsed)' - }) - ]) - ]), + cE('extra', { + transition: 'none !important' + }) + ]) + ]), + cM('horizontal', { + display: 'flex', + paddingBottom: 0 + }, [ + cB('submenu', { + margin: 0 + }), cB('menu-item', { - transition: 'background-color .3s var(--bezier)', - height: '42px', - marginTop: '6px', - position: 'relative' + margin: 0 }, [ - c('&::after', ` - content: ""; - background-color: transparent; - position: absolute; - left: 8px; - right: 8px; - top: 0; - bottom: 0; - pointer-events: none; - border-radius: var(--border-radius); - transition: background-color .3s var(--bezier); - `), - cNotM('disabled', [ - c('&:active::after', { - backgroundColor: 'var(--item-color-active)' - }) - ]), + c('&::after', { + backgroundColor: 'transparent !important' + }), cM('selected', [ - c('&::after', { - backgroundColor: 'var(--item-color-active)' - }), - cB('menu-item-content', [ - cE('icon', { - color: 'var(--item-icon-color-active)' - }), - cB('menu-item-content-header', { - color: 'var(--item-text-color-active)' - }, [ - cE('extra', { - color: 'var(--item-extra-text-color-active)' - }) - ]) - ]) + cB('menu-item-content', { + borderBottom: '2px solid var(--border-color-horizontal)' + }) ]) ]), - cB('menu-item-content', ` - box-sizing: border-box; - line-height: 1.75; - height: 100%; - display: flex; - align-items: center; - cursor: pointer; - position: relative; - z-index: auto; - padding-right: 12px; - transition: - background-color .3s var(--bezier), - padding-left .3s var(--bezier), - border-color .3s var(--bezier); - `, [ - cM('disabled', { - opacity: '.45', - cursor: 'not-allowed' + cB('menu-item-content', { + padding: '0 20px', + borderBottom: '2px solid transparent' + }, [ + cM('child-active', { + borderBottom: '2px solid var(--border-color-horizontal)' }), - cM('collapsed', [ - cE('arrow', { - transition: ` - transform 0.2s var(--bezier), - opacity 0.2s var(--bezier), - border-color 0.3s var(--bezier) - `, - transform: 'rotate(225deg)' + cNotM('disabled', [ + hoverStyle({ + borderBottom: '2px solid var(--border-color-horizontal)' }) - ]), - cM('uncollapsable', { - cursor: 'default' + ]) + ]) + ]), + cM('collapsed', [ + cB('menu-item', [ + c('&::after', { + backgroundColor: 'transparent !important' + }) + ]), + cB('menu-item-content', [ + cB('menu-item-content-header', { + opacity: 0 }), - cM('child-selected', [ + cE('arrow', { + opacity: 0 + }), + cE('icon', { + color: 'var(--item-icon-color-collapsed)' + }) + ]) + ]), + cB('menu-item', { + transition: 'background-color .3s var(--bezier)', + height: '42px', + marginTop: '6px', + position: 'relative' + }, [ + c('&::after', ` + content: ""; + background-color: transparent; + position: absolute; + left: 8px; + right: 8px; + top: 0; + bottom: 0; + pointer-events: none; + border-radius: var(--border-radius); + transition: background-color .3s var(--bezier); + `), + cNotM('disabled', [ + c('&:active::after', { + backgroundColor: 'var(--item-color-active)' + }) + ]), + cM('selected', [ + c('&::after', { + backgroundColor: 'var(--item-color-active)' + }), + cB('menu-item-content', [ + cE('icon', { + color: 'var(--item-icon-color-active)' + }), cB('menu-item-content-header', { - color: 'var(--item-text-color-child-active)' + color: 'var(--item-text-color-active)' }, [ cE('extra', { - color: 'var(--item-extra-text-color-child-active)' + color: 'var(--item-extra-text-color-active)' }) - ]), - cE('icon', { - color: 'var(--item-icon-color-child-active)' - }) - ]), - cNotM('disabled', [ - cNotM('uncollapsable', [ - hoverStyle(null, [ - cE('icon', { - color: 'var(--item-icon-color-hover)' - }), - cB('menu-item-content-header', { - color: 'var(--item-text-color-hover)' - }, [ - cE('extra', { - color: 'var(--item-extra-text-color-hover)' - }) - ]) - ]) ]) - ]), - cE('icon', ` - color: var(--item-icon-color); - transition: - color .3s var(--bezier), - font-size .3s var(--bezier), - padding-right .3s var(--bezier); - box-sizing: content-box; - flex-shrink: 0; - padding-right: 8px; - display: inline-flex; - align-items: center; - justify-content: center; - `), - cE('arrow', ` - content: ''; - height: 6px; - width: 6px; - position: absolute; - right: 24px; - top: calc(50% - 2px); - transform: rotate(45deg); - transform-origin: 25% 25%; - opacity: 1; - border-left: 2px solid var(--submenu-arrow-color); - border-top: 2px solid var(--submenu-arrow-color); - transition: + ]) + ]) + ]), + cB('menu-item-content', ` + box-sizing: border-box; + line-height: 1.75; + height: 100%; + display: flex; + align-items: center; + cursor: pointer; + position: relative; + z-index: auto; + padding-right: 12px; + transition: + background-color .3s var(--bezier), + padding-left .3s var(--bezier), + border-color .3s var(--bezier); + `, [ + cM('disabled', { + opacity: '.45', + cursor: 'not-allowed' + }), + cM('collapsed', [ + cE('arrow', { + transition: ` transform 0.2s var(--bezier), - opacity 0.2s var(--bezier) .1s, - border-color 0.3s var(--bezier); - `), - cB('menu-item-content-header', ` - transition: - color .3s var(--bezier), - opacity .3s var(--bezier); - opacity: 1; - flex-grow: 1; - flex-shrink: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: var(--item-text-color); - `, [ - cE('extra', ` - white-space: nowrap; - margin-left: 6px; - display: inline-block; - transition: color 0.3s var(--bezier); - font-size: 13px; - color: var(--item-extra-text-color); - `) - ]) + opacity 0.2s var(--bezier), + border-color 0.3s var(--bezier) + `, + transform: 'rotate(225deg)' + }) ]), - cB('submenu', { - cursor: 'pointer', - position: 'relative', - marginTop: '6px' - }, [ - cB('menu-item-content', { - height: '42px' - }), - cB('submenu-children', { - overflow: 'hidden', - padding: 0 + cM('child-active', [ + cB('menu-item-content-header', { + color: 'var(--item-text-color-child-active)' }, [ - fadeInHeightExpandTransition({ - duration: '.2s' + cE('extra', { + color: 'var(--item-extra-text-color-child-active)' }) + ]), + cE('icon', { + color: 'var(--item-icon-color-child-active)' + }) + ]), + cNotM('disabled', [ + hoverStyle(null, [ + cE('icon', { + color: 'var(--item-icon-color-hover)' + }), + cB('menu-item-content-header', { + color: 'var(--item-text-color-hover)' + }, [ + cE('extra', { + color: 'var(--item-extra-text-color-hover)' + }) + ]) ]) ]), - cB('menu-item-group', [ - cB('menu-item-group-title', ` - margin-top: 6px; - color: var(--group-text-color); - cursor: default; + cE('icon', ` + color: var(--item-icon-color); + transition: + color .3s var(--bezier), + font-size .3s var(--bezier), + padding-right .3s var(--bezier); + box-sizing: content-box; + flex-shrink: 0; + padding-right: 8px; + display: inline-flex; + align-items: center; + justify-content: center; + `), + cE('arrow', ` + content: ''; + height: 6px; + width: 6px; + position: absolute; + right: 24px; + top: calc(50% - 2px); + transform: rotate(45deg); + transform-origin: 25% 25%; + opacity: 1; + border-left: 2px solid var(--arrow-color); + border-top: 2px solid var(--arrow-color); + transition: + transform 0.2s var(--bezier), + opacity 0.2s var(--bezier) .1s, + border-color 0.3s var(--bezier); + `), + cB('menu-item-content-header', ` + transition: + color .3s var(--bezier), + opacity .3s var(--bezier); + opacity: 1; + flex-grow: 1; + flex-shrink: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: var(--item-text-color); + `, [ + cE('extra', ` + white-space: nowrap; + margin-left: 6px; + display: inline-block; + transition: color 0.3s var(--bezier); font-size: 13px; - height: 36px; - display: flex; - align-items: center; - transition: - padding-left .3s var(--bezier), - color .3s var(--bezier); + color: var(--item-extra-text-color); `) ]) + ]), + cB('submenu', { + cursor: 'pointer', + position: 'relative', + marginTop: '6px' + }, [ + cB('menu-item-content', { + height: '42px' + }), + cB('submenu-children', { + overflow: 'hidden', + padding: 0 + }, [ + fadeInHeightExpandTransition({ + duration: '.2s' + }) + ]) + ]), + cB('menu-item-group', [ + cB('menu-item-group-title', ` + margin-top: 6px; + color: var(--group-text-color); + cursor: default; + font-size: 13px; + height: 36px; + display: flex; + align-items: center; + transition: + padding-left .3s var(--bezier), + color .3s var(--bezier); + `) ]) ]) diff --git a/src/menu/src/utils.js b/src/menu/src/utils.js index 5d0a27a52..822a3c583 100644 --- a/src/menu/src/utils.js +++ b/src/menu/src/utils.js @@ -12,10 +12,9 @@ const menuItemGroupProps = Object.keys(NMenuItemGroup.props).concat( menuChildProps ) -export function itemRenderer (tmNode, insidePopover = false) { +export function itemRenderer (tmNode) { const { rawNode, key, level } = tmNode const props = { - insidePopover, ...rawNode, extra: rawNode.extra ?? rawNode.titleExtra, key, @@ -33,6 +32,7 @@ export function itemRenderer (tmNode, insidePopover = false) { return h( NSubmenu, keep(props, submenuProps, { + rawNodes: tmNode.rawNode.children, tmNodes: tmNode.children }) )