refactor(dropdown): new theme

This commit is contained in:
07akioni 2021-01-03 03:26:05 +08:00
parent cf2b58b304
commit 35e296f9a8
11 changed files with 209 additions and 164 deletions

View File

@ -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
})
}
}
)
}
}
})

View File

@ -3,7 +3,9 @@
</template>
<script>
export default {
import { defineComponent } from 'vue'
export default defineComponent({
name: 'DropdownDivider'
}
})
</script>

View File

@ -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 {
]
)
}
}
})

View File

@ -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 {
]
)
}
}
})

View 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'
})
])
])

View File

@ -1,9 +0,0 @@
import baseStyle from './themed-base.cssr.js'
export default [
{
key: 'mergedTheme',
watch: ['mergedTheme'],
CNode: baseStyle
}
]

View File

@ -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'
})
])
])
]
}
])

View File

@ -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
}
}
})
}

View File

@ -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
}
}
})
}

View File

@ -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'

View File

@ -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
}