feat(switch): add checked, unchecked slots

This commit is contained in:
07akioni 2021-07-24 22:49:44 +08:00
parent ff061c53f2
commit 6942dbe1cc
8 changed files with 126 additions and 17 deletions

View File

@ -5,6 +5,7 @@
### Feats
- `n-time-picker` add `actions` prop, closes [#401](https://github.com/TuSimple/naive-ui/issues/401).
- `n-switch` add `checked`, `unchecked` slots.
## 2.15.6 (2021-07-23)

View File

@ -5,6 +5,7 @@
### Feats
- `n-time-picker` 增加 `actions` 属性, 关闭 [#401](https://github.com/TuSimple/naive-ui/issues/401)
- `n-switch` 增加 `checked`、`unchecked` 插槽
## 2.15.6 (2021-07-23)

View File

@ -0,0 +1,10 @@
# Content
Add content into switch.
```html
<n-switch>
<template #checked>Big wheels keep on turnin'</template>
<template #unchecked>Carry me home to see my kin</template>
</n-switch>
```

View File

@ -7,10 +7,13 @@ I have a Nintendo Switch, but have no time to play. It always make me recall the
```demo
basic
size
content
event
```
## Props
## API
### Switch Props
| Name | Type | Default | Description |
| --- | --- | --- | --- |
@ -19,3 +22,10 @@ event
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | The size of switch. |
| value | `boolean` | `undefined` | Value in controlled mode. |
| on-update:value | `(value: boolean) => void` | `undefined` | Callback when the component's value changes. |
### Switch Slots
| Name | Parameters | Description |
| --------- | ---------- | --------------------------------------- |
| checked | `()` | Content when the switch is checked. |
| unchecked | `()` | Content when the switch is not checked. |

View File

@ -0,0 +1,10 @@
# 内容
向开关中加入内容。
```html
<n-switch>
<template #checked>自然赠予你,树冠 微风 肩头的暴雨</template>
<template #unchecked>片刻后生成,平衡 忠诚 不息的身体</template>
</n-switch>
```

View File

@ -7,10 +7,15 @@
```demo
basic
size
content
event
```
## Props
## API
### Props
### Switch Props
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
@ -19,3 +24,10 @@ event
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | 开关大小 |
| value | `boolean` | `undefined` | 受控模式下的值 |
| on-update:value | `(value: boolean) => void` | `undefined` | 组件值发生变化的回调 |
### Switch Slots
| 名称 | 参数 | 说明 |
| --------- | ---- | ---------------- |
| checked | `()` | 开关激活时的内容 |
| unchecked | `()` | 开关关闭时的内容 |

View File

@ -191,7 +191,8 @@ export default defineComponent({
}
},
render () {
const { mergedClsPrefix, mergedValue } = this
const { mergedClsPrefix, mergedValue, $slots } = this
const { checked: checkedSlot, unchecked: uncheckedSlot } = $slots
return (
<div
role="switch"
@ -213,7 +214,31 @@ export default defineComponent({
onKeyup={this.handleKeyup}
onKeydown={this.handleKeydown}
>
<div class={`${mergedClsPrefix}-switch__rail`} aria-hidden="true" />
<div class={`${mergedClsPrefix}-switch__rail`} aria-hidden="true">
{(checkedSlot || uncheckedSlot) && (
<div
aria-hidden
class={`${mergedClsPrefix}-switch__children-placeholder`}
>
<div class={`${mergedClsPrefix}-switch__rail-placeholder`}>
<div class={`${mergedClsPrefix}-switch__button-placeholder`} />
{checkedSlot?.()}
</div>
<div class={`${mergedClsPrefix}-switch__rail-placeholder`}>
<div class={`${mergedClsPrefix}-switch__button-placeholder`} />
{uncheckedSlot?.()}
</div>
</div>
)}
<div class={`${mergedClsPrefix}-switch__button`}>
<div class={`${mergedClsPrefix}-switch__checked`}>
{checkedSlot?.()}
</div>
<div class={`${mergedClsPrefix}-switch__unchecked`}>
{uncheckedSlot?.()}
</div>
</div>
</div>
</div>
)
}

View File

@ -18,7 +18,7 @@ import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'
// --box-shadow-focus
export default cB('switch', `
height: var(--height);
width: var(--width);
min-width: var(--width);
vertical-align: middle;
user-select: none;
display: inline-flex;
@ -26,6 +26,41 @@ export default cB('switch', `
justify-content: center;
align-items: center;
`, [
cE('children-placeholder', `
height: var(--rail-height);
display: flex;
flex-direction: column;
overflow: hidden;
pointer-events: none;
visibility: hidden;
`),
cE('rail-placeholder', `
display: flex;
flex-wrap: none;
`),
cE('button-placeholder', `
width: calc(1.75 * var(--rail-height));
height: var(--rail-height);
`),
cE('checked, unchecked', `
color: white;
box-sizing: border-box;
position: absolute;
white-space: nowrap;
top: 0;
bottom: 0;
display: flex;
align-items: center;
`),
cE('checked', `
right: 0;
padding-right: calc(1.25 * var(--rail-height) - var(--offset));
`),
cE('unchecked', `
left: 0;
justify-content: flex-end;
padding-left: calc(1.25 * var(--rail-height) - var(--offset));
`),
c('&:focus', [
cE('rail', `
box-shadow: var(--box-shadow-focus);
@ -35,7 +70,7 @@ export default cB('switch', `
cE('rail', {
borderRadius: 'calc(var(--rail-height) / 2)'
}, [
c('&::before', {
cE('button', {
borderRadius: 'calc(var(--button-height) / 2)'
})
])
@ -43,41 +78,46 @@ export default cB('switch', `
cNotM('disabled', [
cM('pressed', [
cE('rail', [
c('&::before', {
cE('button', {
maxWidth: 'var(--button-width-pressed)'
})
])
]),
cE('rail', [
c('&:active::before', {
maxWidth: 'var(--button-width-pressed)'
})
c('&:active', [
cE('button', {
maxWidth: 'var(--button-width-pressed)'
})
])
]),
cM('active', [
cM('pressed', [
cE('rail', [
c('&::before', {
cE('button', {
left: 'calc(100% - var(--offset) - var(--button-width-pressed))'
})
])
]),
cE('rail', [
c('&:active::before', {
left: 'calc(100% - var(--offset) - var(--button-width-pressed))'
})
c('&:active', [
cE('button', {
left: 'calc(100% - var(--offset) - var(--button-width-pressed))'
})
])
])
])
]),
cM('active', [
cE('rail', [
c('&::before', {
cE('button', {
left: 'calc(100% - (var(--rail-height) + var(--button-width)) / 2)'
})
])
]),
cE('rail', `
overflow: hidden;
height: var(--rail-height);
width: var(--rail-width);
min-width: var(--rail-width);
border-radius: var(--rail-border-radius);
cursor: pointer;
position: relative;
@ -86,7 +126,7 @@ export default cB('switch', `
box-shadow .3s var(--bezier);
background-color: var(--rail-color);
`, [
c('&::before', `
cE('button', `
top: var(--offset);
left: var(--offset);
height: var(--button-width);