refactor(divider): new theme impl

This commit is contained in:
07akioni 2020-12-31 20:29:27 +08:00
parent 84c75fb704
commit b7cabf901a
17 changed files with 315 additions and 208 deletions

View File

@ -3,6 +3,7 @@
class="demo"
namespace="naive-ui-doc"
:theme="theme"
:unstable-theme="theme === 'dark' ? darkTheme : undefined"
:language="lang"
>
<n-loading-bar-provider ref="loadingBar">
@ -21,6 +22,7 @@
import { ref, computed } from 'vue'
import Site from './Site.vue'
import { useRoute, useRouter } from 'vue-router'
import { darkTheme } from '../src/styles.new'
export default {
name: 'SiteProvider',
@ -77,7 +79,9 @@ export default {
return {
displayMode: displayModeComputed,
theme: themeRef,
lang: langRef
lang: langRef,
// unstable
darkTheme
}
}
}

View File

@ -95,12 +95,12 @@
"vue-router": "^4.0.0-rc.1"
},
"dependencies": {
"@css-render/plugin-bem": "^0.11.1",
"@css-render/plugin-bem": "^0.12.0",
"@vicons/fluent": "~0.0.3",
"@vicons/ionicons-v4": "~0.0.3",
"@vicons/ionicons-v5": "~0.0.3",
"async-validator": "^3.4.0",
"css-render": "^0.11.1",
"css-render": "^0.12.0",
"date-fns": "^2.9.0",
"evtd": "^0.1.0",
"highlight.js": "^10.4.1",

View File

@ -4,3 +4,5 @@ export { default as themeable } from './themeable'
export { default as configurable } from './configurable'
export { default as withCssr } from './with-cssr'
export { default as registerable } from './registerable'
export { default as useTheme } from './use-theme'
export { default as useConfig } from './use-config'

16
src/_mixins/use-config.js Normal file
View File

@ -0,0 +1,16 @@
import { inject, computed } from 'vue'
export default function useConfig (props) {
const NConfigProvider = inject('NConfigProvider', null)
return {
NConfigProvider,
mergedBordered: computed(() => {
const { bordered } = props
if (bordered !== undefined) return bordered
return NConfigProvider?.mergedBordered || true
}),
namespace () {
return NConfigProvider?.namespace
}
}
}

71
src/_mixins/use-theme.js Normal file
View File

@ -0,0 +1,71 @@
import { inject, computed, onBeforeMount } from 'vue'
import { merge } from 'lodash-es'
/**
* props.unstableTheme:
* { common, self(), peers }
* provider.unstableTheme:
* { common, Button: { common, self(), peers } }
* defaultTheme:
* { common, self(), peers }
*
* props.themeOverrides:
* { { common, self, peers } }
* provider.themeOverrides:
* { common, Button: { common, self, peers } }
*/
export default function useTheme (
resolveId,
mountId,
style,
defaultTheme,
props
) {
onBeforeMount(() => {
style.mount({
target: mountId
})
})
const NConfigProvider = inject('NConfigProvider', {})
const mergedThemeRef = computed(() => {
const {
unstableTheme: { common, self, peers = {} } = {},
unstableThemeOverrides: {
common: commonOverrides,
self: selfOverrides,
peers: peersOverrides = {}
} = {}
} = props
const {
mergedUnstableTheme: {
common: injectedGlobalCommon,
[resolveId]: { injectedCommon, injectedSelf, injectedPeers = {} } = {}
} = {},
mergedUnstableThemeOverrides: {
common: injectedGlobalCommonOverrides,
[resolveId]: {
common: injectedCommonOverrides,
self: injectedSelfOverrides,
peers: injectedPeersOverrides = {}
} = {}
} = {}
} = NConfigProvider
const mergedCommon = merge(
common || injectedCommon || injectedGlobalCommon || defaultTheme.common,
injectedGlobalCommonOverrides,
injectedCommonOverrides,
commonOverrides
)
return {
common: mergedCommon,
self: merge(
(self || injectedSelf || defaultTheme.self)(mergedCommon),
injectedSelfOverrides,
selfOverrides
),
peersTheme: merge(peers, injectedPeers),
peersOverride: merge(peersOverrides, injectedPeersOverrides)
}
})
return mergedThemeRef
}

View File

@ -0,0 +1,4 @@
import { baseDark, baseLight } from '../base/index'
export const commonDark = baseDark.vars
export const commonLight = baseLight.vars

View File

View File

@ -2,16 +2,6 @@ import { h, inject, computed } from 'vue'
import { useMemo } from 'vooks'
import { warn, getSlot } from '../../_utils'
function createStyleMap (styles) {
if (!styles) return undefined
return styles.reduce((map, style) => {
const { theme, name } = style
if (!map[theme]) map[theme] = {}
map[theme][name] = style
return map
}, {})
}
export default {
name: 'ConfigProvider',
alias: ['App'],
@ -37,10 +27,6 @@ export default {
type: String,
default: undefined
},
styles: {
type: Array,
default: undefined
},
tag: {
type: String,
default: 'div'
@ -49,6 +35,15 @@ export default {
type: String,
default: undefined
},
// wip, unstable
unstableTheme: {
type: Object,
default: undefined
},
unstableThemeOverrides: {
type: Object,
default: undefined
},
// deprecated
language: {
type: String,
@ -103,9 +98,18 @@ export default {
const { locale } = props
return locale === undefined ? NConfigProvider?.mergedLocale : locale
}),
mergedStyles: computed(() => {
// TODO, merged styles together
return createStyleMap(props.styles) ?? NConfigProvider?.mergedStyles
// wip, unstable
mergedUnstableTheme: computed(() => {
const { unstableTheme } = props
return unstableTheme === undefined
? NConfigProvider?.unstableTheme
: unstableTheme
}),
mergedUnstableThemeOverrides: computed(() => {
const { unstableThemeOverrides } = props
return unstableThemeOverrides === undefined
? NConfigProvider?.unstableThemeOverrides
: unstableThemeOverrides
}),
// deprecated
mergedLanguage: useMemo(() => {

View File

@ -6,9 +6,9 @@
'n-divider--no-title': !$slots.default,
'n-divider--dashed': dashed,
[`n-divider--title-position-${titlePlacement}`]:
$slots.default && titlePlacement,
[`n-${mergedTheme}-theme`]: mergedTheme
$slots.default && titlePlacement
}"
:style="cssVars"
>
<hr v-if="!vertical" class="n-divider__line n-divider__line--left">
<div v-if="!vertical && $slots.default" class="n-divider__title">
@ -22,13 +22,22 @@
</template>
<script>
import { configurable, themeable, withCssr } from '../../_mixins'
import styles from './styles'
import { computed } from 'vue'
import { useConfig, useTheme } from '../../_mixins'
import { dividerLight } from '../styles'
import style from './styles/index.cssr'
export default {
name: 'Divider',
mixins: [configurable, themeable, withCssr(styles)],
props: {
unstableTheme: {
type: Object,
default: undefined
},
unstableThemeOverrides: {
type: Object,
default: undefined
},
titlePlacement: {
type: String,
default: 'center'
@ -41,6 +50,24 @@ export default {
type: Boolean,
default: false
}
},
setup (props) {
const themeRef = useTheme('Divider', 'Divider', style, dividerLight, props)
return {
...useConfig(props),
cssVars: computed(() => {
const {
common: { cubicBezierEaseInOut },
self: { color, textColor, fontWeight }
} = themeRef.value
return {
'--bezier': cubicBezierEaseInOut,
'--color': color,
'--text-color': textColor,
'--font-weight': fontWeight
}
})
}
}
}
</script>

View File

@ -0,0 +1,92 @@
import { c, cB, cNotM, cE, cM } from '../../../_utils/cssr'
// vars:
// --bezier
// --color
// --text-color
// --font-weight
export default c([
cB(
'divider', `
position: relative;
display: flex;
width: 100%;
box-sizing: border-box;
font-size: 16px;
color: var(--text-color);
transition:
color .3s var(--bezier),
background-color .3s var(--bezier);
`,
[
cNotM('vertical', `
margin-top: 24px;
margin-bottom: 24px;
`,
[
cNotM('no-title', `
display: flex;
align-items: center;
`)
]),
cE('title', `
display: flex;
align-items: center;
margin-left: 12px;
margin-right: 12px;
white-space: nowrap;
font-weight: var(--font-weight);
`),
cM('title-position-left', [
cE('line', [
cM('left', {
width: '28px'
})
])
]),
cM('title-position-right', [
cE('line', [
cM('right', {
width: '28px'
})
])
]),
cM('dashed', [
cE('line', `
background-color: transparent;
height: 0px;
width: 100%;
border-style: dashed;
border-width: 1px 0 0;
`)
]),
cM('vertical', `
display: inline-block;
height: 1em;
margin: 0 8px;
vertical-align: middle;
width: 1px;
`),
cE('line', `
border: none;
transition: background-color .3s var(--bezier), border-color .3s var(--bezier);
height: 1px;
width: 100%;
margin: 0;
`),
cNotM('dashed', [
cE('line', {
backgroundColor: 'var(--color)'
})
]),
cM('dashed', [
cE('line', {
borderColor: 'var(--color)'
})
]),
cM('vertical', {
backgroundColor: 'var(--color)'
})
]
)
])

View File

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

View File

@ -1,122 +0,0 @@
import { c, cTB, cNotM, cE, cM } from '../../../_utils/cssr'
export default c([
({ props }) => {
const { cubicBezierEaseInOut } = props.$global
const {
textColor,
color,
fontWeight
} = props.$local
return [
cTB(
'divider',
{
raw: `
position: relative;
display: flex;
width: 100%;
box-sizing: border-box;
font-size: 16px;
color: ${textColor};
transition:
color .3s ${cubicBezierEaseInOut},
background-color .3s ${cubicBezierEaseInOut};
`
},
[
cNotM('vertical', {
raw: `
margin-top: 24px;
margin-bottom: 24px;
`
},
[
cNotM('no-title', {
raw: `
display: flex;
align-items: center;
`
})
]),
cE('title', {
raw: `
display: flex;
align-items: center;
margin-left: 12px;
margin-right: 12px;
white-space: nowrap;
font-weight: ${fontWeight};
`
}),
cM('title-position-left', [
cE('line', [
cM('left', {
raw: `
width: 28px;
`
})
])
]),
cM('title-position-right', [
cE('line', [
cM('right', {
raw: `
width: 28px;
`
})
])
]),
cM('dashed', [
cE('line', {
raw: `
background-color: transparent;
height: 0px;
width: 100%;
border-style: dashed;
border-width: 1px 0 0;
`
})
]),
cM('vertical', {
raw: `
display: inline-block;
height: 1em;
margin: 0 8px;
vertical-align: middle;
width: 1px;
`
}),
cE('line', {
raw: `
border: none;
transition: background-color .3s ${cubicBezierEaseInOut}, border-color .3s ${cubicBezierEaseInOut};
height: 1px;
width: 100%;
margin: 0;
`
}),
cNotM('dashed', [
cE('line', {
raw: `
background-color: ${color};
`
})
]),
cM('dashed', [
cE('line', {
raw: `
border-color: ${color};
`
})
]),
cM('vertical', {
raw: `
background-color: ${color};
`
})
]
)
]
}
])

View File

@ -1,16 +1,13 @@
import create from '../../_styles/utils/create-component-base'
import { baseDark } from '../../_styles/base'
import { commonDark } from '../../_styles/new-common'
export default create({
theme: 'dark',
name: 'Divider',
peer: [baseDark],
getLocalVars (vars) {
const { textColor1Overlay, dividerColorOverlay } = vars
export default {
common: commonDark,
self (vars) {
const { textColor1Overlay, dividerColorOverlay, fontWeightStrong } = vars
return {
textColor: textColor1Overlay,
color: dividerColorOverlay,
fontWeight: vars.fontWeightStrong
fontWeight: fontWeightStrong
}
}
})
}

View File

@ -1,16 +1,13 @@
import create from '../../_styles/utils/create-component-base'
import { baseLight } from '../../_styles/base'
import { commonLight } from '../../_styles/new-common'
export default create({
theme: 'light',
name: 'Divider',
peer: [baseLight],
getLocalVars (vars) {
const { textColor1, dividerColorOverlay } = vars
export default {
common: commonLight,
self (vars) {
const { textColor1, dividerColorOverlay, fontWeightStrong } = vars
return {
textColor: textColor1,
color: dividerColorOverlay,
fontWeight: vars.fontWeightStrong
fontWeight: fontWeightStrong
}
}
})
}

View File

@ -35,7 +35,7 @@ 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 { dividerDark, dividerLight } from './divider/styles'
// export { dividerDark, dividerLight } from './divider/styles'
export { drawerDark, drawerLight } from './drawer/styles'
export { dropdownDark, dropdownLight } from './dropdown/styles'
export { dynamicInputDark, dynamicInputLight } from './dynamic-input/styles'

7
src/styles.new.js Normal file
View File

@ -0,0 +1,7 @@
import { commonDark } from './_styles/new-common'
import { dividerDark } from './divider/styles'
export const darkTheme = {
common: commonDark,
Divider: dividerDark
}

View File

@ -16,16 +16,20 @@ const unconfigurableStyle = c([
})
]),
cB('tag', [
cE('close', {
borderRadius: '50%'
}, [
c('&:hover', {
backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })
}),
c('&:hover', {
backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })
})
])
cE(
'close',
{
borderRadius: '50%'
},
[
c('&:hover', {
backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })
}),
c('&:hover', {
backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })
})
]
)
]),
cB('message', [
cE('close', [
@ -48,7 +52,8 @@ const unconfigurableStyle = c([
]),
cM('info', [
cB('progress-graph-line-fill', {
background: 'linear-gradient(270deg, #FFAC26 0%, #F2E93D 100%) !important'
background:
'linear-gradient(270deg, #FFAC26 0%, #F2E93D 100%) !important'
}),
cM('circle', [
cB('progress-graph-circle-fill', {
@ -58,7 +63,8 @@ const unconfigurableStyle = c([
]),
cM('success', [
cB('progress-graph-line-fill', {
background: 'linear-gradient(270deg, #4FB233 0%, #AFF25E 100%) !important'
background:
'linear-gradient(270deg, #4FB233 0%, #AFF25E 100%) !important'
}),
cM('circle', [
cB('progress-graph-circle-fill', {
@ -68,7 +74,8 @@ const unconfigurableStyle = c([
]),
cM('warning', [
cB('progress-graph-line-fill', {
background: 'linear-gradient(270deg, #FF66BA 0%, #D92149 100%) !important'
background:
'linear-gradient(270deg, #FF66BA 0%, #D92149 100%) !important'
}),
cM('circle', [
cB('progress-graph-circle-fill', {
@ -78,7 +85,8 @@ const unconfigurableStyle = c([
]),
cM('error', [
cB('progress-graph-line-fill', {
background: 'linear-gradient(270deg, #FF66BA 0%, #D92149 100%) !important'
background:
'linear-gradient(270deg, #FF66BA 0%, #D92149 100%) !important'
}),
cM('circle', [
cB('progress-graph-circle-fill', {
@ -96,14 +104,18 @@ const unconfigurableStyle = c([
])
]),
cM('disabled', [
cE('rail', {
backgroundColor: '#EBEDF0'
}, [
c('&::before', {
backgroundColor: '#EBEDF0',
backgroundImage: 'unset'
})
]),
cE(
'rail',
{
backgroundColor: '#EBEDF0'
},
[
c('&::before', {
backgroundColor: '#EBEDF0',
backgroundImage: 'unset'
})
]
),
cM('active', [
cE('rail', [
c('&::before', {
@ -158,9 +170,7 @@ function tusimpleTheme (naive) {
</defs>`
const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
svgEl.innerHTML = svgDefs
document.body.appendChild(
svgEl
)
document.body.appendChild(svgEl)
const primaryColor = '#4FB233'
const inputColorDisabled = '#EBEDF0'
naive.styles.light.override({
@ -191,9 +201,7 @@ function tusimpleTheme (naive) {
optionColorHover: composite(primaryColor, 'rgba(255, 255, 255, .1)'),
clearIconColor: composite('#FFF', 'rgba(0, 0, 0, .4)')
})
const {
vars
} = naive.styles.light.base
const { vars } = naive.styles.light.base
naive.styles.light.Button.override({
textColorWarning: '#333',
@ -424,9 +432,12 @@ function tusimpleTheme (naive) {
iconColor: 'rgba(0, 0, 0, .8)',
iconColorHover: vars.primaryColor,
iconColorPressed: vars.primaryColorPressed,
boxShadow: '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',
boxShadowHover: '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',
boxShadowPressed: '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)'
boxShadow:
'0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',
boxShadowHover:
'0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',
boxShadowPressed:
'0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)'
})
naive.styles.light.Breadcrumb.override({
fontSize: '16px',
@ -532,6 +543,12 @@ function tusimpleTheme (naive) {
padding: '20px',
fontSize: '16px'
})
naive.styles.light.Typography.override({
headerPrefixWidth3: '15px',
headerPrefixWidth4: '15px',
headerPrefixWidth5: '15px',
headerPrefixWidth6: '15px'
})
}
tusimpleTheme.install = tusimpleTheme