refactor(switch): new theme

This commit is contained in:
07akioni 2021-01-07 23:14:58 +08:00
parent a9993db485
commit b847d9f441
9 changed files with 195 additions and 169 deletions

View File

@ -71,7 +71,7 @@ export { baseDark, baseLight } from './_styles/base'
// export { spinDark, spinLight } from './spin/styles'
// export { statisticDark, statisticLight } from './statistic/styles'
// export { stepsDark, stepsLight } from './steps/styles'
export { switchDark, switchLight } from './switch/styles'
// export { switchDark, switchLight } from './switch/styles'
export { tableDark, tableLight } from './table/styles'
export { tabsDark, tabsLight } from './tabs/styles'
export { tagDark, tagLight } from './tag/styles'

View File

@ -52,6 +52,7 @@ import { spaceDark } from './space/styles'
import { spinDark } from './spin/styles'
import { statisticDark } from './statistic/styles'
import { stepsDark } from './steps/styles'
import { switchDark } from './switch/styles'
export const darkTheme = {
common: commonDark,
@ -107,5 +108,6 @@ export const darkTheme = {
Space: spaceDark,
Spin: spinDark,
Statistic: statisticDark,
Steps: stepsDark
Steps: stepsDark,
Switch: switchDark
}

View File

@ -2,12 +2,12 @@
<div
class="n-switch"
:class="{
[`n-${mergedTheme}-theme`]: mergedTheme,
[`n-switch--${mergedSize}-size`]: true,
'n-switch--active': mergedValue,
'n-switch--disabled': disabled
'n-switch--disabled': disabled,
'n-switch--round': round
}"
:tabindex="!disabled ? 0 : false"
:style="cssVars"
@click="handleClick"
@focus="handleFocus"
@blur="handleBlur"
@ -17,15 +17,16 @@
</template>
<script>
import { ref, toRef } from 'vue'
import { ref, toRef, defineComponent, computed } from 'vue'
import { depx, pxfy } from 'seemly'
import { useMergedState } from 'vooks'
import { configurable, themeable, useFormItem, withCssr } from '../../_mixins'
import { call, warn } from '../../_utils'
import styles from './styles'
import { useFormItem, useTheme } from '../../_mixins'
import { call, warn, createKey } from '../../_utils'
import style from './styles/index.cssr.js'
import { switchLight } from '../styles'
export default {
export default defineComponent({
name: 'Switch',
mixins: [configurable, themeable, withCssr(styles)],
props: {
size: {
type: String,
@ -43,6 +44,10 @@ export default {
type: Boolean,
default: false
},
round: {
type: Boolean,
default: true
},
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:value': {
type: [Function, Array],
@ -62,6 +67,9 @@ export default {
}
},
setup (props) {
const themeRef = useTheme('Switch', 'Switch', style, switchLight, props)
const formItem = useFormItem(props)
const { mergedSize: mergedSizeRef } = formItem
const uncontrolledValueRef = ref(props.defaultValue)
const controlledValueRef = toRef(props, 'value')
const mergedValueRef = useMergedState(
@ -69,9 +77,53 @@ export default {
uncontrolledValueRef
)
return {
...formItem,
mergedValue: mergedValueRef,
uncontrolledValue: uncontrolledValueRef,
...useFormItem(props)
cssVars: computed(() => {
const { value: size } = mergedSizeRef
const {
self: {
opacityDisabled,
railColor,
railColorActive,
buttonBoxShadow,
buttonColor,
[createKey('buttonHeight', size)]: buttonHeight,
[createKey('buttonWidth', size)]: buttonWidth,
[createKey('buttonWidthPressed', size)]: buttonWidthPressed,
[createKey('railHeight', size)]: railHeight,
[createKey('railWidth', size)]: railWidth,
[createKey('railBorderRadius', size)]: railBorderRadius,
[createKey('buttonBorderRadius', size)]: buttonBorderRadius
},
common: { cubicBezierEaseInOut }
} = themeRef.value
const offset = pxfy((depx(railHeight) - depx(buttonHeight)) / 2)
const height = pxfy(Math.max(depx(railHeight), depx(buttonHeight)))
const width =
depx(railHeight) > depx(buttonHeight)
? railWidth
: pxfy(depx(railWidth) + depx(buttonHeight) - depx(railHeight))
return {
'--bezier': cubicBezierEaseInOut,
'--button-border-radius': buttonBorderRadius,
'--button-box-shadow': buttonBoxShadow,
'--button-color': buttonColor,
'--button-width': buttonWidth,
'--button-width-pressed': buttonWidthPressed,
'--button-height': buttonHeight,
'--height': height,
'--offset': offset,
'--opacity-disabled': opacityDisabled,
'--rail-border-radius': railBorderRadius,
'--rail-color': railColor,
'--rail-color-active': railColorActive,
'--rail-height': railHeight,
'--rail-width': railWidth,
'--width': width
}
})
}
},
methods: {
@ -110,5 +162,5 @@ export default {
this.doBlur(e)
}
}
}
})
</script>

View File

@ -0,0 +1,99 @@
import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'
// vars:
// --bezier
// --button-border-radius
// --button-box-shadow
// --button-color
// --button-width
// --button-width-pressed
// --height
// --offset
// --rail-border-radius
// --rail-color
// --rail-color-active
// --rail-height
// --rail-width
// --width
export default cB('switch', `
height: var(--height);
width: var(--width);
vertical-align: middle;
user-select: none;
display: inline-flex;
outline: none;
justify-content: center;
align-items: center;
`, [
cM('round', [
cE('rail', {
borderRadius: 'calc(var(--rail-height) / 2)'
}, [
c('&::before', {
borderRadius: 'calc(var(--button-height) / 2)'
})
])
]),
cNotM('disabled', [
cE('rail', [
c('&:active::before', {
maxWidth: 'var(--button-width-pressed)'
})
]),
cM('active', [
cE('rail', [
c('&:active::before', {
left: 'calc(100% - var(--offset) - var(--button-width-pressed))'
})
])
])
]),
cM('active', [
cE('rail', [
c('&::before', {
left: 'calc(100% - (var(--rail-height) + var(--button-width)) / 2)'
})
])
]),
cE('rail', `
height: var(--rail-height);
width: var(--rail-width);
border-radius: var(--rail-border-radius);
cursor: pointer;
position: relative;
transition: background-color .3s var(--bezier);
background-color: var(--rail-color);
`, [
c('&::before', `
top: var(--offset);
left: var(--offset);
height: var(--button-width);
width: var(--button-width-pressed);
max-width: var(--button-width);
border-radius: var(--button-border-radius);
background-color: var(--button-color);
box-shadow: var(--button-box-shadow);
box-sizing: border-box;
cursor: inherit;
content: "";
position: absolute;
transition:
background-color .3s var(--bezier),
left .3s var(--bezier),
opacity .3s var(--bezier),
max-width .3s var(--bezier),
box-shadow .3s var(--bezier);
`)
]),
cM('active', [
cE('rail', {
backgroundColor: 'var(--rail-color-active)'
})
]),
cM('disabled', [
cE('rail', `
cursor: not-allowed;
opacity: .5;
`)
])
])

View File

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

View File

@ -1,122 +0,0 @@
import { c, cE, cM, cTB, cNotM, createKey } from '../../../_utils/cssr'
import { depx, pxfy } from 'seemly'
export default c([
({ props }) => {
const {
$global: {
cubicBezierEaseInOut
},
$local
} = props
const {
railColor,
railColorActive,
buttonBoxShadow,
buttonColor
} = $local
return cTB('switch', {
raw: `
vertical-align: middle;
user-select: none;
display: inline-flex;
outline: none;
justify-content: center;
align-items: center;
`
}, [
['small', 'medium', 'large'].map(size => {
const railHeight = $local[createKey('railHeight', size)]
const railWidth = $local[createKey('railWidth', size)]
const buttonHeight = $local[createKey('buttonHeight', size)]
const buttonWidth = $local[createKey('buttonWidth', size)]
const buttonWidthPressed = $local[createKey('buttonWidthPressed', size)]
const offset = pxfy((depx(railHeight) - depx(buttonHeight)) / 2)
const height = pxfy(Math.max(depx(railHeight), depx(buttonHeight)))
const width = depx(railHeight) > depx(buttonHeight) ? railWidth : pxfy(
depx(railWidth) + depx(buttonHeight) - depx(railHeight)
)
return cM(`${size}-size`, {
height,
width
}, [
cE('rail', {
height: railHeight,
width: railWidth,
borderRadius: $local[createKey('railBorderRadius', size)]
}, [
c('&::before', {
top: offset,
left: offset,
height: buttonWidth,
width: buttonWidthPressed,
maxWidth: buttonWidth,
borderRadius: $local[createKey('buttonBorderRadius', size)]
})
]),
cNotM('disabled', [
cE('rail', [
c('&:active::before', {
maxWidth: buttonWidthPressed
})
]),
cM('active', [
cE('rail', [
c('&:active::before', {
left: `calc(100% - ${offset} - ${buttonWidthPressed})`
})
])
])
]),
cM('active', [
cE('rail', [
c('&::before', {
left: `calc(100% - (${railHeight} + ${buttonWidth}) / 2)`
})
])
])
])
}),
cE('rail', {
raw: `
cursor: pointer;
position: relative;
transition: background-color .3s ${cubicBezierEaseInOut};
background-color: ${railColor};
`
}, [
c('&::before', {
raw: `
background-color: ${buttonColor};
box-sizing: border-box;
cursor: inherit;
content: "";
position: absolute;
transition:
background-color .3s ${cubicBezierEaseInOut},
left .3s ${cubicBezierEaseInOut},
opacity .3s ${cubicBezierEaseInOut},
max-width .3s ${cubicBezierEaseInOut},
box-shadow .3s ${cubicBezierEaseInOut};
`
}),
c('&::before', {
boxShadow: buttonBoxShadow
})
]),
cM('active', [
cE('rail', {
backgroundColor: railColorActive
})
]),
cM('disabled', [
cE('rail', {
raw: `
cursor: not-allowed;
opacity: .5;
`
})
])
])
}
])

View File

@ -13,11 +13,5 @@ export default {
railHeightLarge: '26px',
railWidthSmall: '32px',
railWidthMedium: '40px',
railWidthLarge: '48px',
railBorderRadiusSmall: '9px',
railBorderRadiusMedium: '11px',
railBorderRadiusLarge: '13px',
buttonBorderRadiusSmall: '7px',
buttonBorderRadiusMedium: '9px',
buttonBorderRadiusLarge: '11px'
railWidthLarge: '48px'
}

View File

@ -1,20 +1,25 @@
import create from '../../_styles/utils/create-component-base'
import commonVars from './_common'
import { baseDark } from '../../_styles/base'
import { commonDark } from '../../_styles/new-common'
export default create({
theme: 'dark',
export default {
name: 'Switch',
peer: [baseDark],
getLocalVars (vars) {
const { primaryColorSuppl } = vars
common: commonDark,
self (vars) {
const { primaryColorSuppl, opacityDisabled, borderRadius } = vars
const railOverlayColor = 'rgba(255, 255, 255, .20)'
return {
...commonVars,
opacityDisabled,
railColor: railOverlayColor,
railColorActive: primaryColorSuppl,
buttonBoxShadow: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',
buttonColor: '#FFF'
buttonColor: '#FFF',
railBorderRadiusSmall: borderRadius,
railBorderRadiusMedium: borderRadius,
railBorderRadiusLarge: borderRadius,
buttonBorderRadiusSmall: borderRadius,
buttonBorderRadiusMedium: borderRadius,
buttonBorderRadiusLarge: borderRadius
}
}
})
}

View File

@ -1,21 +1,26 @@
import create from '../../_styles/utils/create-component-base'
import commonVars from './_common'
import { baseLight } from '../../_styles/base'
import { commonLight } from '../../_styles/new-common'
export default create({
theme: 'light',
export default {
name: 'Switch',
peer: [baseLight],
getLocalVars (vars) {
const { primaryColor } = vars
common: commonLight,
self (vars) {
const { primaryColor, opacityDisabled, borderRadius } = vars
const railOverlayColor = 'rgba(0, 0, 0, .14)'
return {
...commonVars,
opacityDisabled,
railColor: railOverlayColor,
railColorActive: primaryColor,
buttonBoxShadow:
'0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',
buttonColor: '#FFF'
buttonColor: '#FFF',
railBorderRadiusSmall: borderRadius,
railBorderRadiusMedium: borderRadius,
railBorderRadiusLarge: borderRadius,
buttonBorderRadiusSmall: borderRadius,
buttonBorderRadiusMedium: borderRadius,
buttonBorderRadiusLarge: borderRadius
}
}
})
}