refactor(dialog): new theme

This commit is contained in:
07akioni 2021-01-03 00:16:06 +08:00
parent e11c97453b
commit 41d62c15b9
11 changed files with 233 additions and 209 deletions

View File

@ -2,12 +2,11 @@
<div
class="n-dialog"
:class="{
[`n-${mergedTheme}-theme`]: mergedTheme,
'n-dialog--bordered': bordered,
[`n-dialog--icon-${mergedIconPlacement}`]: true,
[`n-dialog--${type}-type`]: type
}"
:style="mergedStyle"
:style="cssVars"
>
<n-icon v-if="closable" class="n-dialog__close" @click="handleCloseClick">
<close-icon />
@ -46,7 +45,7 @@
<slot name="action">
<n-button
v-if="negativeText"
:theme="theme"
:theme="'light'"
ghost
size="small"
@click="handleNegativeClick"
@ -54,7 +53,7 @@
<render :render="negativeText" />
</n-button>
<n-button
:theme="theme"
:theme="'light'"
:disabled="loading === true"
:loading="loading"
size="small"
@ -69,8 +68,9 @@
</template>
<script>
import { configurable, themeable, withCssr } from '../../_mixins'
import { render } from '../../_utils'
import { defineComponent, computed } from 'vue'
import { useTheme } from '../../_mixins'
import { render, createKey } from '../../_utils'
import { NIcon } from '../../icon'
import { NButton } from '../../button'
import {
@ -80,9 +80,10 @@ import {
WarningIcon,
ErrorIcon
} from '../../_base/icons'
import styles from './styles/index.js'
import { dialogLight } from '../styles'
import style from './styles/index.cssr.js'
export default {
export default defineComponent({
name: 'Dialog',
alias: [
'NimbusConfirmCard', // deprecated
@ -98,7 +99,6 @@ export default {
InfoIcon,
render
},
mixins: [configurable, themeable, withCssr(styles)],
props: {
icon: {
type: Function,
@ -157,6 +157,66 @@ export default {
default: undefined
}
},
setup (props) {
const themeRef = useTheme('Dialog', 'Dialog', style, dialogLight, props)
return {
cssVars: computed(() => {
const { type, iconPlacement } = props
const {
common: { cubicBezierEaseInOut },
self: {
fontSize,
lineHeight,
border,
titleTextColor,
textColor,
color,
closeColor,
closeColorHover,
closeColorPressed,
borderRadius,
titleFontWeight,
titleFontSize,
padding,
iconSize,
actionSpace,
contentMargin,
closeSize,
[iconPlacement === 'top'
? 'iconMarginIconTop'
: 'iconMargin']: iconMargin,
[iconPlacement === 'top'
? 'closeMarginIconTop'
: 'closeMargin']: closeMargin,
[createKey('iconColor', type)]: iconColor
}
} = themeRef.value
return {
'--font-size': fontSize,
'--icon-color': iconColor,
'--bezier': cubicBezierEaseInOut,
'--close-margin': closeMargin,
'--icon-margin': iconMargin,
'--icon-size': iconSize,
'--close-size': closeSize,
'--close-color': closeColor,
'--close-color-hover': closeColorHover,
'--close-color-pressed': closeColorPressed,
'--color': color,
'--text-color': textColor,
'--border-radius': borderRadius,
'--padding': padding,
'--line-height': lineHeight,
'--border': border,
'--content-margin': contentMargin,
'--title-font-size': titleFontSize,
'--title-font-weight': titleFontWeight,
'--title-text-color': titleTextColor,
'--action-space': actionSpace
}
})
}
},
computed: {
mergedIconPlacement () {
return (
@ -193,5 +253,5 @@ export default {
if (onClose) onClose()
}
}
}
})
</script>

View File

@ -28,10 +28,11 @@
<script>
// use absolute path to make sure no circular ref of style
// this -> modal-index -> modal-style
import { defineComponent } from 'vue'
import NModal from '../../modal/src/Modal'
import NDialog from './Dialog.vue'
export default {
export default defineComponent({
name: 'DialogEnvironment',
components: {
NModal,
@ -107,5 +108,5 @@ export default {
this.show = false
}
}
}
})
</script>

View File

@ -1,17 +1,11 @@
import { Fragment, ref, h, reactive } from 'vue'
import { defineComponent, Fragment, ref, h, reactive } from 'vue'
import { createId } from 'seemly'
import { omit } from '../../_utils'
import DialogEnvironment from './DialogEnvironment.vue'
import { useClicked, useClickPosition } from 'vooks'
export default {
export default defineComponent({
name: 'DialogProvider',
props: {
to: {
type: [String, Object],
default: undefined
}
},
provide () {
return {
dialog: {
@ -23,6 +17,12 @@ export default {
}
}
},
props: {
to: {
type: [String, Object],
default: undefined
}
},
setup () {
const dialogListRef = ref([])
return {
@ -75,4 +75,4 @@ export default {
this.$slots.default()
])
}
}
})

View File

@ -0,0 +1,124 @@
import { c, cB, cE, cM, insideModal } from '../../../_utils/cssr'
// vars:
// --icon-color
// --bezier
// --close-margin
// --icon-margin
// --icon-size
// --close-size
// --close-color
// --close-color-hover
// --close-color-pressed
// --color
// --text-color
// --border-radius
// --padding
// --line-height
// --border
// --content-margin
// --title-font-size
// --title-font-weight
// --title-text-color
// --action-space
export default c([
cB(
'dialog', `
line-height: var(--line-height);
position: relative;
background: var(--color);
color: var(--text-color);
box-sizing: border-box;
margin: auto;
border-radius: var(--border-radius);
padding: var(--padding);
transition:
border-color .3s var(--bezier),
background-color .3s var(--bezier),
color .3s var(--bezier);
`,
[
cE('icon', {
color: 'var(--icon-color)'
}),
cM('bordered', {
border: 'var(--border)'
}),
cM('icon-top', [
cE('close', {
margin: 'var(--close-margin)'
}),
cE('icon', {
margin: 'var(--icon-margin)'
}),
cE('content', {
textAlign: 'center'
}),
cE('title', {
justifyContent: 'center'
}),
cE('action', {
justifyContent: 'center'
})
]),
cM('icon-left', [
cE('icon', {
margin: 'var(--icon-margin)'
})
]),
cE('close', `
font-size: var(--close-size);
cursor: pointer;
position: absolute;
right: 0;
top: 0;
color: var(--close-color);
margin: var(--close-margin);
transition: .3s color var(--bezier);
`,
[
c('&:hover', {
color: 'var(--close-color-hover)'
}),
c('&:active', {
color: 'var(--close-color-pressed)'
})
]),
cE('content', `
font-size: var(--font-size);
margin: var(--content-margin);
position: relative;
`),
cE('action', `
display: flex;
justify-content: flex-end;
`, [
c('> *:not(:last-child)', {
marginRight: 'var(--action-space)'
})
]),
cE('icon', {
fontSize: 'var(--icon-size)',
transition: 'color .3s var(--bezier)'
}),
cE('title', `
transition: color .3s var(--bezier);
display: flex;
align-items: center;
font-size: var(--title-font-size);
font-weight: var(--title-font-weight);
color: var(--title-text-color);
`),
cB('dialog-icon-container', {
display: 'flex',
justifyContent: 'center'
})
]
),
insideModal(
cB('dialog', `
width: 446px;
max-width: calc(100vw - 32px);
`)
)
])

View File

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

View File

@ -1,158 +0,0 @@
import { c, cTB, cB, cE, cM, createKey } from '../../../_utils/cssr'
export default c([
({ props }) => {
const {
$global: {
cubicBezierEaseInOut
},
$local
} = props
const {
actionSpace,
contentMargin,
iconSize,
iconMargin,
iconMarginIconTop,
padding,
headerTextColor,
textColor,
color,
border,
borderRadius,
headerFontWeight,
headerFontSize,
closeSize,
closeMargin,
closeMarginIconTop,
closeColor,
closeColorHover,
closeColorPressed,
fontSize,
lineHeight
} = $local
const dialogStyle = cTB(
'dialog',
{
raw: `
line-height: ${lineHeight};
position: relative;
background: ${color};
color: ${textColor};
box-sizing: border-box;
margin: auto;
border-radius: ${borderRadius};
padding: ${padding};
transition:
border-color .3s ${cubicBezierEaseInOut},
background-color .3s ${cubicBezierEaseInOut},
color .3s ${cubicBezierEaseInOut};
`
},
[
[
'info',
'success',
'warning',
'error'
].map(type => cM(`${type}-type`, [
cE('icon', {
color: $local[createKey('iconColor', type)]
})
])),
cM('bordered', {
border
}),
cM('icon-top', [
cE('close', {
margin: closeMarginIconTop
}),
cE('icon', {
margin: iconMarginIconTop
}),
cE('content', {
textAlign: 'center'
}),
cE('title', {
justifyContent: 'center'
}),
cE('action', {
justifyContent: 'center'
})
]),
cM('icon-left', [
cE('icon', {
margin: iconMargin
})
]),
cE('close', {
raw: `
font-size: ${closeSize};
margin: ${padding};
cursor: pointer;
position: absolute;
right: 0;
top: 0;
color: ${closeColor};
margin: ${closeMargin};
transition: .3s color ${cubicBezierEaseInOut};
`
},
[
c('&:hover', {
color: closeColorHover
}),
c('&:active', {
color: closeColorPressed
})
]),
cE('content', {
raw: `
font-size: ${fontSize};
margin: ${contentMargin};
position: relative;
`
}),
cE('action', {
raw: `
display: flex;
justify-content: flex-end;
`
}, [
c('> *:not(:last-child)', {
marginRight: actionSpace
})
]),
cE('icon', {
fontSize: iconSize,
transition: `color .3s ${cubicBezierEaseInOut}`
}),
cE('title', {
raw: `
transition: color .3s ${cubicBezierEaseInOut};
display: flex;
align-items: center;
font-size: ${headerFontSize};
font-weight: ${headerFontWeight};
color: ${headerTextColor}
`
}),
cB('dialog-icon-container', {
display: 'flex',
justifyContent: 'center'
})
]
)
return [
dialogStyle,
cB('modal', [
cB('dialog', {
raw: `
width: 446px;
max-width: calc(100vw - 32px);
`
})
])
]
}
])

View File

@ -1,5 +1,5 @@
export default {
headerFontSize: '18px',
titleFontSize: '18px',
padding: '16px 28px 20px 28px',
iconSize: '28px',
actionSpace: '12px',

View File

@ -1,14 +1,16 @@
import create from '../../_styles/utils/create-component-base'
import commonVars from './_common'
import { baseDark } from '../../_styles/base'
import { iconDark } from '../../icon/styles'
import { buttonDark } from '../../button/styles'
import { commonDark } from '../../_styles/new-common'
export default create({
theme: 'dark',
export default {
name: 'Dialog',
peer: [baseDark, iconDark, buttonDark],
getLocalVars (vars) {
common: commonDark,
peers: {
Icon: iconDark,
Button: buttonDark
},
self (vars) {
const {
textColor1Overlay,
textColor2Overlay,
@ -31,7 +33,7 @@ export default create({
fontSize,
lineHeight,
border: `1px solid ${dividerColorOverlay}`,
headerTextColor: textColor1Overlay,
titleTextColor: textColor1Overlay,
textColor: textColor2Overlay,
color: modalColor,
closeColor: closeColorOverlay,
@ -42,7 +44,7 @@ export default create({
iconColorWarning: warningColor,
iconColorError: errorColor,
borderRadius,
headerFontWeight: fontWeightStrong
titleFontWeight: fontWeightStrong
}
}
})
}

View File

@ -1,14 +1,16 @@
import create from '../../_styles/utils/create-component-base'
import commonVars from './_common'
import { baseLight } from '../../_styles/base'
import { iconLight } from '../../icon/styles'
import { buttonLight } from '../../button/styles'
import { commonLight } from '../../_styles/new-common'
export default create({
theme: 'light',
export default {
name: 'Dialog',
peer: [baseLight, iconLight, buttonLight],
getLocalVars (vars) {
common: commonLight,
peers: {
Icon: iconLight,
Button: buttonLight
},
self (vars) {
const {
textColor1,
textColor2,
@ -31,7 +33,7 @@ export default create({
fontSize,
lineHeight,
border: `1px solid ${dividerColor}`,
headerTextColor: textColor1,
titleTextColor: textColor1,
textColor: textColor2,
color: cardColor,
closeColor: closeColor,
@ -42,7 +44,7 @@ export default create({
iconColorWarning: warningColor,
iconColorError: errorColor,
borderRadius,
headerFontWeight: fontWeightStrong
titleFontWeight: fontWeightStrong
}
}
})
}

View File

@ -34,7 +34,7 @@ export { baseDark, baseLight } from './_styles/base'
// export { dataTableDark, dataTableLight } from './data-table/styles'
// export { datePickerDark, datePickerLight } from './date-picker/styles'
// export { descriptionsDark, descriptionsLight } from './descriptions/styles'
export { dialogDark, dialogLight } from './dialog/styles'
// export { dialogDark, dialogLight } from './dialog/styles'
// export { dividerDark, dividerLight } from './divider/styles'
export { drawerDark, drawerLight } from './drawer/styles'
export { dropdownDark, dropdownLight } from './dropdown/styles'

View File

@ -9,7 +9,6 @@ import { badgeDark } from './badge/styles'
import { breadcrumbDark } from './breadcrumb/styles'
import { buttonDark } from './button/styles'
import { cardDark } from './card/styles'
import { dividerDark } from './divider/styles'
import { cascaderDark } from './cascader/styles'
import { checkboxDark } from './checkbox/styles'
import { codeDark } from './code/styles'
@ -17,6 +16,8 @@ import { collapseDark } from './collapse/styles'
import { dataTableDark } from './data-table/styles'
import { datePickerDark } from './date-picker/styles'
import { descriptionsDark } from './descriptions/styles'
import { dialogDark } from './dialog/styles'
import { dividerDark } from './divider/styles'
export const darkTheme = {
common: commonDark,
@ -37,5 +38,6 @@ export const darkTheme = {
DataTable: dataTableDark,
DatePicker: datePickerDark,
Descriptions: descriptionsDark,
Dialog: dialogDark,
Divider: dividerDark
}