mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-03-31 14:20:53 +08:00
refactor(dropdown): new theme
This commit is contained in:
parent
cf2b58b304
commit
35e296f9a8
@ -1,16 +1,24 @@
|
||||
import { h, computed, ref, toRef, getCurrentInstance } from 'vue'
|
||||
import {
|
||||
defineComponent,
|
||||
h,
|
||||
computed,
|
||||
ref,
|
||||
toRef,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import { TreeMate } from 'treemate'
|
||||
import { configurable, themeable, withCssr } from '../../_mixins'
|
||||
import { NPopover } from '../../popover'
|
||||
import NDropdownMenu from './DropdownMenu.js'
|
||||
import {
|
||||
useMergedState,
|
||||
useFalseUntilTruthy,
|
||||
useKeyboard,
|
||||
useMemo
|
||||
} from 'vooks'
|
||||
import { keep, call } from '../../_utils'
|
||||
import styles from './styles'
|
||||
import { useTheme } from '../../_mixins'
|
||||
import { NPopover } from '../../popover'
|
||||
import { keep, call, createKey } from '../../_utils'
|
||||
import { dropdownLight } from '../styles'
|
||||
import NDropdownMenu from './DropdownMenu.js'
|
||||
import style from './styles/index.cssr.js'
|
||||
|
||||
const treemateOptions = {
|
||||
getKey (node) {
|
||||
@ -61,9 +69,8 @@ const dropdownProps = {
|
||||
|
||||
const popoverPropKeys = Object.keys(NPopover.props)
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'Dropdown',
|
||||
mixins: [configurable, themeable, withCssr(styles)],
|
||||
provide () {
|
||||
return {
|
||||
NDropdown: this
|
||||
@ -150,6 +157,13 @@ export default {
|
||||
keyboardEnabledRef
|
||||
)
|
||||
|
||||
const themeRef = useTheme(
|
||||
'Dropdown',
|
||||
'Dropdown',
|
||||
style,
|
||||
dropdownLight,
|
||||
props
|
||||
)
|
||||
return {
|
||||
// data
|
||||
tm: treemateRef,
|
||||
@ -167,7 +181,48 @@ export default {
|
||||
mergedShow: mergedShowRef,
|
||||
// methods
|
||||
getPath: getPathRef,
|
||||
getFirstAvailableNode: getFirstAvailableNodeRef
|
||||
getFirstAvailableNode: getFirstAvailableNodeRef,
|
||||
cssVars: computed(() => {
|
||||
const { size } = props
|
||||
const {
|
||||
common: { cubicBezierEaseInOut },
|
||||
self: {
|
||||
padding,
|
||||
color,
|
||||
dividerColor,
|
||||
borderRadius,
|
||||
boxShadow,
|
||||
suffixColor,
|
||||
prefixColor,
|
||||
optionColorHover,
|
||||
optionTextColor,
|
||||
[createKey('optionIconSuffixWidth', size)]: optionIconSuffixWidth,
|
||||
[createKey('optionSuffixWidth', size)]: optionSuffixWidth,
|
||||
[createKey('optionIconPrefixWidth', size)]: optionIconPrefixWidth,
|
||||
[createKey('optionPrefixWidth', size)]: optionPrefixWidth,
|
||||
[createKey('fontSize', size)]: fontSize,
|
||||
[createKey('optionHeight', size)]: optionHeight
|
||||
}
|
||||
} = themeRef.value
|
||||
return {
|
||||
'--bezier': cubicBezierEaseInOut,
|
||||
'--font-size': fontSize,
|
||||
'--option-color-hover': optionColorHover,
|
||||
'--divider-color': dividerColor,
|
||||
'--color': color,
|
||||
'--padding': padding,
|
||||
'--border-radius': borderRadius,
|
||||
'--box-shadow': boxShadow,
|
||||
'--option-height': optionHeight,
|
||||
'--option-prefix-width': optionPrefixWidth,
|
||||
'--option-icon-prefix-width': optionIconPrefixWidth,
|
||||
'--option-suffix-width': optionSuffixWidth,
|
||||
'--option-icon-suffix-width': optionIconSuffixWidth,
|
||||
'--option-text-color': optionTextColor,
|
||||
'--prefix-color': prefixColor,
|
||||
'--suffix-color': suffixColor
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -265,10 +320,11 @@ export default {
|
||||
trigger: this.$slots.default,
|
||||
default: () => {
|
||||
return h(NDropdownMenu, {
|
||||
tmNodes: this.tmNodes
|
||||
tmNodes: this.tmNodes,
|
||||
style: this.cssVars
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -3,7 +3,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DropdownDivider'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { h } from 'vue'
|
||||
import { defineComponent, h } from 'vue'
|
||||
import NDropdownOption from './DropdownOption'
|
||||
import NDropdownDivider from './DropdownDivider.vue'
|
||||
import { isSubmenuNode } from './utils'
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'DropdownMenu',
|
||||
inject: ['NDropdown'],
|
||||
provide () {
|
||||
@ -14,7 +14,7 @@ export default {
|
||||
props: {
|
||||
tmNodes: {
|
||||
type: Array,
|
||||
require: true
|
||||
required: true
|
||||
},
|
||||
parentKey: {
|
||||
type: [String, Number],
|
||||
@ -31,18 +31,12 @@ export default {
|
||||
},
|
||||
render () {
|
||||
const {
|
||||
NDropdown: { size, mergedTheme }
|
||||
NDropdown: { size }
|
||||
} = this
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
class: [
|
||||
'n-dropdown-menu',
|
||||
`n-dropdown-menu--${size}-size`,
|
||||
{
|
||||
[`n-${mergedTheme}-theme`]: mergedTheme
|
||||
}
|
||||
]
|
||||
class: ['n-dropdown-menu', `n-dropdown-menu--${size}-size`]
|
||||
},
|
||||
[
|
||||
this.tmNodes.map((tmNode) => {
|
||||
@ -60,4 +54,4 @@ export default {
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { h, computed, inject, ref, Transition } from 'vue'
|
||||
import { h, computed, inject, ref, Transition, defineComponent } from 'vue'
|
||||
import { VBinder, VTarget, VFollower } from 'vueuc'
|
||||
import { render } from '../../_utils'
|
||||
import { ChevronRightIcon } from '../../_base/icons'
|
||||
@ -8,7 +8,7 @@ import { useDelayedTrue } from '../../_utils/composable'
|
||||
import NDropdownMenu from './DropdownMenu'
|
||||
import { isSubmenuNode } from './utils'
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'DropdownOption',
|
||||
provide () {
|
||||
return {
|
||||
@ -252,4 +252,4 @@ export default {
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
113
src/dropdown/src/styles/index.cssr.js
Normal file
113
src/dropdown/src/styles/index.cssr.js
Normal file
@ -0,0 +1,113 @@
|
||||
import { cB, cM, cE } from '../../../_utils/cssr'
|
||||
import fadeInScaleUpTransition from '../../../_styles/transitions/fade-in-scale-up'
|
||||
|
||||
// vars:
|
||||
// --bezier
|
||||
// --font-size
|
||||
// --option-color-hover
|
||||
// --divider-color
|
||||
// --color
|
||||
// --padding
|
||||
// --border-radius
|
||||
// --box-shadow
|
||||
// --option-height
|
||||
// --option-prefix-width
|
||||
// --option-icon-prefix-width
|
||||
// --option-suffix-width
|
||||
// --option-icon-suffix-width
|
||||
// --option-text-color
|
||||
// --prefix-color
|
||||
// --suffix-color
|
||||
export default cB('dropdown-menu', {
|
||||
padding: 'var(--padding)',
|
||||
backgroundColor: 'var(--color)',
|
||||
borderRadius: 'var(--border-radius)',
|
||||
boxShadow: 'var(--box-shadow)',
|
||||
transition: `
|
||||
background-color .3s var(--bezier),
|
||||
box-shadow .3s var(--bezier)
|
||||
`
|
||||
}, [
|
||||
fadeInScaleUpTransition(),
|
||||
cB('dropdown-option', [
|
||||
cB('dropdown-option-body', {
|
||||
display: 'flex',
|
||||
height: 'var(--option-height)',
|
||||
lineHeight: 'var(--option-height)',
|
||||
fontSize: 'var(--font-size)',
|
||||
color: 'var(--option-text-color)',
|
||||
transition: 'color .3s var(--bezier)'
|
||||
}, [
|
||||
cE('prefix', {
|
||||
width: 'var(--option-prefix-width)',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}, [
|
||||
cM('show-icon', {
|
||||
width: 'var(--option-icon-prefix-width)'
|
||||
}),
|
||||
cB('icon', {
|
||||
transition: 'color .3s var(--bezier)',
|
||||
color: 'var(--prefix-color)',
|
||||
fontSize: '16px'
|
||||
})
|
||||
]),
|
||||
cE('label', {
|
||||
whiteSpace: 'nowrap',
|
||||
flex: 1
|
||||
}),
|
||||
cE('suffix', {
|
||||
boxSizing: 'border-box',
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
minWidth: 'var(--option-suffix-width)',
|
||||
padding: '0 8px'
|
||||
}, [
|
||||
cM('has-submenu', {
|
||||
width: 'var(--option-icon-suffix-width)'
|
||||
}),
|
||||
cB('icon', {
|
||||
transition: 'color .3s var(--bezier)',
|
||||
color: 'var(--suffix-color)',
|
||||
fontSize: '16px'
|
||||
})
|
||||
])
|
||||
])
|
||||
]),
|
||||
cB('dropdown-divider', {
|
||||
transition: 'background-color .3s var(--bezier)',
|
||||
backgroundColor: 'var(--divider-color)',
|
||||
height: '1px',
|
||||
margin: '4px 0'
|
||||
}),
|
||||
cB('dropdown-option', {
|
||||
position: 'relative'
|
||||
}, [
|
||||
cB('dropdown-option-body', {
|
||||
cursor: 'default'
|
||||
}, [
|
||||
cM('pending', {
|
||||
backgroundColor: 'var(--option-color-hover)'
|
||||
})
|
||||
]),
|
||||
cB('dropdown-offset-container', {
|
||||
pointerEvents: 'none',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: '-4px',
|
||||
bottom: '-4px'
|
||||
}),
|
||||
cB('dropdown-menu', {
|
||||
pointerEvents: 'all'
|
||||
}),
|
||||
cB('dropdown-menu-wrapper', {
|
||||
transformOrigin: 'inherit',
|
||||
width: 'fit-content'
|
||||
})
|
||||
])
|
||||
])
|
@ -1,9 +0,0 @@
|
||||
import baseStyle from './themed-base.cssr.js'
|
||||
|
||||
export default [
|
||||
{
|
||||
key: 'mergedTheme',
|
||||
watch: ['mergedTheme'],
|
||||
CNode: baseStyle
|
||||
}
|
||||
]
|
@ -1,111 +0,0 @@
|
||||
import { c, cTB, cB, cM, cE, createKey } from '../../../_utils/cssr'
|
||||
import fadeInScaleUpTransition from '../../../_styles/transitions/fade-in-scale-up'
|
||||
|
||||
export default c([
|
||||
({ props }) => {
|
||||
const local = props.$local
|
||||
const {
|
||||
color,
|
||||
prefixColor,
|
||||
suffixColor,
|
||||
dividerColor,
|
||||
padding,
|
||||
boxShadow,
|
||||
borderRadius,
|
||||
optionColorHover
|
||||
} = local
|
||||
return [
|
||||
cTB('dropdown-menu', {
|
||||
padding,
|
||||
backgroundColor: color,
|
||||
borderRadius,
|
||||
boxShadow
|
||||
}, [
|
||||
fadeInScaleUpTransition(),
|
||||
[
|
||||
'small',
|
||||
'medium',
|
||||
'large',
|
||||
'huge'
|
||||
].map(size => cM(`${size}-size`, [
|
||||
cB('dropdown-option', [
|
||||
cB('dropdown-option-body', {
|
||||
display: 'flex',
|
||||
height: local[createKey('optionHeight', size)],
|
||||
lineHeight: local[createKey('optionHeight', size)],
|
||||
fontSize: local[createKey('fontSize', size)]
|
||||
}, [
|
||||
cE('prefix', {
|
||||
width: local[createKey('optionPrefixWidth', size)],
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}, [
|
||||
cM('show-icon', {
|
||||
width: local[createKey('optionIconPrefixWidth', size)]
|
||||
}),
|
||||
cB('icon', {
|
||||
color: prefixColor,
|
||||
fontSize: '16px'
|
||||
})
|
||||
]),
|
||||
cE('label', {
|
||||
whiteSpace: 'nowrap',
|
||||
flex: 1
|
||||
}),
|
||||
cE('suffix', {
|
||||
boxSizing: 'border-box',
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
minWidth: local[createKey('optionSuffixWidth', size)],
|
||||
padding: '0 8px'
|
||||
}, [
|
||||
cM('has-submenu', {
|
||||
width: local[createKey('optionIconSuffixWidth', size)]
|
||||
}),
|
||||
cB('icon', {
|
||||
color: suffixColor,
|
||||
fontSize: '16px'
|
||||
})
|
||||
])
|
||||
])
|
||||
])
|
||||
])),
|
||||
cB('dropdown-divider', {
|
||||
backgroundColor: dividerColor,
|
||||
height: '1px',
|
||||
margin: '4px 0'
|
||||
}),
|
||||
cB('dropdown-option', {
|
||||
position: 'relative'
|
||||
}, [
|
||||
cB('dropdown-option-body', {
|
||||
cursor: 'default'
|
||||
}, [
|
||||
cM('pending', {
|
||||
backgroundColor: optionColorHover
|
||||
})
|
||||
]),
|
||||
cB('dropdown-offset-container', {
|
||||
pointerEvents: 'none',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: '-4px',
|
||||
bottom: '-4px'
|
||||
}),
|
||||
cB('dropdown-menu', {
|
||||
pointerEvents: 'all'
|
||||
}),
|
||||
cB('dropdown-menu-wrapper', {
|
||||
transformOrigin: 'inherit',
|
||||
width: 'fit-content'
|
||||
})
|
||||
])
|
||||
])
|
||||
]
|
||||
}
|
||||
])
|
@ -1,12 +1,10 @@
|
||||
import create from '../../_styles/utils/create-component-base'
|
||||
import { commonDark } from '../../_styles/new-common'
|
||||
import commonVariables from './_common'
|
||||
import { baseDark } from '../../_styles/base'
|
||||
|
||||
export default create({
|
||||
theme: 'dark',
|
||||
export default {
|
||||
name: 'Dropdown',
|
||||
peer: [baseDark],
|
||||
getLocalVars (vars) {
|
||||
common: commonDark,
|
||||
self (vars) {
|
||||
const {
|
||||
textColor2,
|
||||
boxShadow2,
|
||||
@ -29,6 +27,7 @@ export default create({
|
||||
optionHeightMedium: heightMedium,
|
||||
optionHeightLarge: heightLarge,
|
||||
optionHeightHuge: heightHuge,
|
||||
optionTextColor: textColor2,
|
||||
color: popoverColor,
|
||||
dividerColor: dividerColorOverlay,
|
||||
borderRadius,
|
||||
@ -42,4 +41,4 @@ export default create({
|
||||
fontSizeHuge
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
import create from '../../_styles/utils/create-component-base'
|
||||
import commonVariables from './_common'
|
||||
import { baseLight } from '../../_styles/base'
|
||||
import { commonLight } from '../../_styles/new-common'
|
||||
|
||||
export default create({
|
||||
theme: 'light',
|
||||
export default {
|
||||
name: 'Dropdown',
|
||||
peer: [baseLight],
|
||||
getLocalVars (vars) {
|
||||
common: commonLight,
|
||||
self (vars) {
|
||||
const {
|
||||
textColor2,
|
||||
boxShadow2,
|
||||
@ -29,6 +27,7 @@ export default create({
|
||||
optionHeightMedium: heightMedium,
|
||||
optionHeightLarge: heightLarge,
|
||||
optionHeightHuge: heightHuge,
|
||||
optionTextColor: textColor2,
|
||||
color: popoverColor,
|
||||
dividerColor,
|
||||
borderRadius,
|
||||
@ -42,4 +41,4 @@ export default create({
|
||||
fontSizeHuge
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ export { baseDark, baseLight } from './_styles/base'
|
||||
// export { dialogDark, dialogLight } from './dialog/styles'
|
||||
// export { dividerDark, dividerLight } from './divider/styles'
|
||||
// export { drawerDark, drawerLight } from './drawer/styles'
|
||||
export { dropdownDark, dropdownLight } from './dropdown/styles'
|
||||
// export { dropdownDark, dropdownLight } from './dropdown/styles'
|
||||
export { dynamicInputDark, dynamicInputLight } from './dynamic-input/styles'
|
||||
export { dynamicTagsDark, dynamicTagsLight } from './dynamic-tags/styles'
|
||||
export { elementDark, elementLight } from './element/styles'
|
||||
|
@ -19,6 +19,7 @@ import { descriptionsDark } from './descriptions/styles'
|
||||
import { dialogDark } from './dialog/styles'
|
||||
import { dividerDark } from './divider/styles'
|
||||
import { drawerDark } from './drawer/styles'
|
||||
import { dropdownDark } from './dropdown/styles'
|
||||
|
||||
export const darkTheme = {
|
||||
common: commonDark,
|
||||
@ -41,5 +42,6 @@ export const darkTheme = {
|
||||
Descriptions: descriptionsDark,
|
||||
Dialog: dialogDark,
|
||||
Divider: dividerDark,
|
||||
Drawer: drawerDark
|
||||
Drawer: drawerDark,
|
||||
Dropdown: dropdownDark
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user