refactor(alert): composition + new theme

This commit is contained in:
07akioni 2020-12-31 21:40:54 +08:00
parent 66a2fa2353
commit 7f4f28c43c
10 changed files with 206 additions and 176 deletions

View File

@ -39,7 +39,11 @@ export default function useTheme (
const {
mergedUnstableTheme: {
common: injectedGlobalCommon,
[resolveId]: { injectedCommon, injectedSelf, injectedPeers = {} } = {}
[resolveId]: {
common: injectedCommon,
self: injectedSelf,
peers: injectedPeers = {}
} = {}
} = {},
mergedUnstableThemeOverrides: {
common: injectedGlobalCommonOverrides,
@ -60,13 +64,14 @@ export default function useTheme (
injectedCommonOverrides,
commonOverrides
)
const mergedSelf = merge(
(self || injectedSelf || defaultTheme.self || {})(mergedCommon),
injectedSelfOverrides,
selfOverrides
)
return {
common: mergedCommon,
self: merge(
(self || injectedSelf || defaultTheme.self || {})(mergedCommon),
injectedSelfOverrides,
selfOverrides
),
self: mergedSelf,
peersTheme: merge(peers, injectedPeers),
peersOverride: merge(peersOverrides, injectedPeersOverrides)
}

View File

@ -9,4 +9,5 @@ export {
} from './vue'
export { warn, warnOnce } from './naive'
export { formatLength } from './css'
export { createKey } from './cssr'
export * from './composable'

View File

@ -5,12 +5,9 @@
class="n-alert"
:class="{
[`n-alert--${type}-type`]: true,
'n-alert--no-icon': showIcon === false,
[`n-${mergedTheme}-theme`]: mergedTheme
}"
:style="{
...mergedStyle
'n-alert--no-icon': showIcon === false
}"
:style="cssVars"
>
<div v-if="closable" class="n-alert__close" @click="handleCloseClick">
<n-icon>
@ -49,11 +46,13 @@
</template>
<script>
import { ref, computed } from 'vue'
import { NIcon } from '../../icon'
import { NFadeInExpandTransition } from '../../_base'
import { configurable, themeable, withCssr } from '../../_mixins'
import { warn } from '../../_utils'
import styles from './styles'
import { useTheme } from '../../_mixins'
import { warn, createKey } from '../../_utils'
import { alertLight } from '../styles'
import style from './styles/index.cssr'
// icons
import {
@ -75,8 +74,15 @@ export default {
ErrorIcon,
CloseIcon
},
mixins: [configurable, themeable, withCssr(styles)],
props: {
unstableTheme: {
type: Object,
default: undefined
},
unstableThemeOverrides: {
type: Object,
default: undefined
},
title: {
type: String,
default: undefined
@ -116,28 +122,61 @@ export default {
default: undefined
}
},
data () {
return {
visible: true
}
},
methods: {
doAfterLeave () {
setup (props) {
const themeRef = useTheme('Alert', 'Alert', style, alertLight, props)
const cssVars = computed(() => {
const {
common: { cubicBezierEaseInOut },
self
} = themeRef.value
const {
fontSize,
borderRadius,
titleFontWeight,
lineHeight,
contentTextColor,
titleTextColor
} = self
const { type } = props
return {
'--bezier': cubicBezierEaseInOut,
'--color': self[createKey('color', type)],
'--close-color': self[createKey('closeColor', type)],
'--close-color-hover': self[createKey('closeColorHover', type)],
'--close-color-pressed': self[createKey('closeColorPressed', type)],
'--icon-color': self[createKey('iconColor', type)],
'--border': self[createKey('border', type)],
'--title-text-color': titleTextColor,
'--content-text-color': contentTextColor,
'--line-height': lineHeight,
'--border-radius': borderRadius,
'--font-size': fontSize,
'--title-font-weight': titleFontWeight
}
})
const visibleRef = ref(true)
const doAfterLeave = () => {
const {
onAfterLeave,
onAfterHide // deprecated
} = this
} = props
if (onAfterLeave) onAfterLeave()
if (onAfterHide) onAfterHide()
},
handleCloseClick () {
Promise.resolve(this.onClose()).then((result) => {
}
const handleCloseClick = () => {
Promise.resolve(props.onClose()).then((result) => {
if (result === false) return
this.visible = false
visibleRef.value = false
})
},
handleAfterLeave () {
this.doAfterLeave()
}
const handleAfterLeave = () => {
doAfterLeave()
}
return {
visible: visibleRef,
handleCloseClick,
handleAfterLeave,
cssVars
}
}
}

View File

@ -0,0 +1,115 @@
import { c, cB, cE, cM } from '../../../_utils/cssr'
import fadeInHeightExpandTranstion from '../../../_styles/transitions/fade-in-height-expand'
// vars:
// --bezier
// --color
// --close-color
// --close-color-hover
// --close-color-pressed
// --icon-color
// --border
// --title-text-color
// --content-text-color
// --line-height
// --border-radius
// --font-size
// --title-font-weight
export default cB('alert', {
lineHeight: 'var(--line-height)',
borderRadius: 'var(--border-radius)',
position: 'relative',
transition: 'background-color .3s var(--bezier)',
backgroundColor: 'var(--color)',
textAlign: 'start'
}, [
cE('close', {
color: 'var(--close-color)'
}, [
c('&:hover', {
color: 'var(--close-color-hover)'
}),
c('&:active', {
color: 'var(--close-color-pressed)'
})
]),
cE('icon', {
color: 'var(--icon-color)'
}),
cB('alert-body', {
border: 'var(--border)'
}, [
cE('title', {
color: 'var(--title-text-color)'
}),
cE('content', {
color: 'var(--content-text-color)'
})
]),
fadeInHeightExpandTranstion({
originalTransition: 'transform .3s var(--bezier)',
enterToProps: {
transform: 'scale(1)'
},
leaveToProps: {
transform: 'scale(0.9)'
}
}),
cE('icon', `
position: absolute;
left: 12px;
top: 14px;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
`, [
cB('icon', {
fontSize: '26px'
})
]),
cE('close', `
position: absolute;
right: 16px;
font-size: 14px;
top: 14px;
width: 1em;
height: 1em;
line-height: 0;
transition: color .3s var(--bezier);
`, [
cB('icon', {
cursor: 'pointer'
})
]),
cB('alert-body', {
borderRadius: 'var(--border-radius)',
padding: '15px 15px 15px 47px',
transition: 'border-color .3s var(--bezier)'
}, [
cE('title', {
transition: 'color .3s var(--bezier)',
fontSize: '16px',
lineHeight: '19px',
fontWeight: 'var(--title-font-weight)'
}, [
c('& +', [
cE('content', {
marginTop: '9px'
})
])
]),
cE('content', {
transition: 'color .3s var(--bezier)',
fontSize: 'var(--font-size)'
})
]),
cE('icon', {
transition: 'color .3s var(--bezier)'
}),
cM('no-icon', [
cB('alert-body', {
paddingLeft: '19px'
})
])
])

View File

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

View File

@ -1,117 +0,0 @@
import { c, cTB, cB, cE, cM, createKey } from '../../../_utils/cssr'
import fadeInHeightExpandTranstion from '../../../_styles/transitions/fade-in-height-expand'
export default c([
({ props }) => {
const {
$global: { cubicBezierEaseInOut },
$local
} = props
const { borderRadius, titleFontWeight, lineHeight, fontSize } = $local
return cTB('alert', {
lineHeight,
borderRadius,
position: 'relative',
transition: `background-color .3s ${cubicBezierEaseInOut}`
}, [
['default', 'info', 'success', 'warning', 'error'].map(type => cM(type + '-type', {
backgroundColor: $local[createKey('color', type)],
textAlign: 'start'
}, [
cE('close', {
color: $local[createKey('closeColor', type)]
}, [
c('&:hover', {
color: $local[createKey('closeColorHover', type)]
}),
c('&:active', {
color: $local[createKey('closeColorPressed', type)]
})
]),
cE('icon', {
color: $local[createKey('iconColor', type)]
}),
cB('alert-body', {
border: $local[createKey('border', type)]
}, [
cE('title', {
color: $local[createKey('titleTextColor', type)]
}),
cE('content', {
color: $local[createKey('contentTextColor', type)]
})
])
])),
fadeInHeightExpandTranstion({
originalTransition: `transform .3s ${cubicBezierEaseInOut}`,
enterToProps: {
transform: 'scale(1)'
},
leaveToProps: {
transform: 'scale(0.9)'
}
}),
cE('icon', {
raw: `
position: absolute;
left: 12px;
top: 14px;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
`
}, [
cB('icon', {
fontSize: '26px'
})
]),
cE('close', {
raw: `
position: absolute;
right: 16px;
font-size: 14px;
top: 14px;
width: 1em;
height: 1em;
line-height: 0;
transition: color .3s ${cubicBezierEaseInOut};
`
}, [
cB('icon', {
cursor: 'pointer'
})
]),
cB('alert-body', {
borderRadius,
padding: '15px 15px 15px 47px',
transition: `border-color .3s ${cubicBezierEaseInOut}`
}, [
cE('title', {
transition: `color .3s ${cubicBezierEaseInOut}`,
fontSize: '16px',
lineHeight: '19px',
fontWeight: titleFontWeight
}, [
c('& +', [
cE('content', {
marginTop: '9px'
})
])
]),
cE('content', {
transition: `color .3s ${cubicBezierEaseInOut}`,
fontSize
})
]),
cE('icon', {
transition: `color .3s ${cubicBezierEaseInOut}`
}),
cM('no-icon', [
cB('alert-body', {
paddingLeft: '19px'
})
])
])
}
])

View File

@ -1,13 +1,9 @@
import create from '../../_styles/utils/create-component-base'
import { baseDark } from '../../_styles/base'
import { iconDark } from '../../icon/styles'
import { changeColor } from 'seemly'
import { commonDark } from '../../_styles/new-common'
export default create({
theme: 'dark',
name: 'Alert',
peer: [baseDark, iconDark],
getLocalVars (vars) {
export default {
common: commonDark,
self (vars) {
const {
lineHeight,
borderRadius,
@ -76,4 +72,4 @@ export default create({
closeColorPressedError: closeColorPressedOverlay
}
}
})
}

View File

@ -1,13 +1,9 @@
import create from '../../_styles/utils/create-component-base'
import { baseLight } from '../../_styles/base'
import { iconLight } from '../../icon/styles'
import { composite, changeColor } from 'seemly'
import { changeColor, composite } from 'seemly'
import { commonLight } from '../../_styles/new-common'
export default create({
theme: 'light',
name: 'Alert',
peer: [baseLight, iconLight],
getLocalVars (vars) {
export default {
common: commonLight,
self (vars) {
const {
lineHeight,
borderRadius,
@ -94,4 +90,4 @@ export default create({
closeColorPressedError: closeColorPressed
}
}
})
}

View File

@ -18,7 +18,7 @@ export { baseWaveDark, baseWaveLight } from './_base/wave/styles'
// exposed style
export { baseDark, baseLight } from './_styles/base'
// export { affixDark, affixLight } from './affix/styles'
export { alertDark, alertLight } from './alert/styles'
// export { alertDark, alertLight } from './alert/styles'
export { anchorDark, anchorLight } from './anchor/styles'
export { autoCompleteDark, autoCompleteLight } from './auto-complete/styles'
export { avatarDark, avatarLight } from './avatar/styles'

View File

@ -1,7 +1,11 @@
import { commonDark } from './_styles/new-common'
import { dividerDark } from './divider/styles'
import { alertDark } from './alert/styles'
import { affixDark } from './affix/styles'
export const darkTheme = {
common: commonDark,
Affix: affixDark,
Alert: alertDark,
Divider: dividerDark
}