mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): el-switch add inline content support (#4091)
* refactor(components): el-swtich custom texts and icons * fix: test * fix: font size * fix: example margin * feat(components): el-switch add inline-prompt support * revert: paly * docs: update icons * feat: add inner text * fix: switch test * refactor: icon inline
This commit is contained in:
@@ -7,6 +7,14 @@ lang: en-US
|
||||
|
||||
Switch is used for switching between two opposing states.
|
||||
|
||||
<style lang="scss">
|
||||
.example-showcase {
|
||||
.el-switch + .el-switch {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
## Basic usage
|
||||
|
||||
:::demo Bind `v-model` to a `Boolean` typed variable. The `active-color` and `inactive-color` attribute decides the background color in two states.
|
||||
@@ -17,6 +25,8 @@ switch/basic
|
||||
|
||||
## Text description
|
||||
|
||||
You can add `active-text` and `inactive-text` attribute to show texts. use `inline-prompt` attribute to control text is displayed inside dot.
|
||||
|
||||
:::demo You can add `active-text` and `inactive-text` attribute to show texts.
|
||||
|
||||
switch/text-description
|
||||
@@ -31,7 +41,7 @@ Use the `active-icon` and `active-icon` attribute to add icon. You can pass eith
|
||||
|
||||
:::
|
||||
|
||||
:::demo You can add `active-icon` and `active-icon` attribute to show icons.
|
||||
:::demo You can add `active-icon` and `inactive-icon` attribute to show icons. use `inline-prompt` attribute to control icon is displayed inside dot.
|
||||
|
||||
switch/custom-icons
|
||||
|
||||
@@ -77,6 +87,7 @@ switch/prevent-switching
|
||||
| disabled | whether Switch is disabled | boolean | — | false |
|
||||
| loading | whether Switch is in loading state | boolean | — | false |
|
||||
| width | width of Switch | number | — | 40 |
|
||||
| inline-prompt | whether icon or text is displayed inside dot | boolean | — | false |
|
||||
| active-icon | component of the icon displayed when in `on` state, overrides `active-text` | string / Component | — | — |
|
||||
| inactive-icon | component of the icon displayed when in `off` state, overrides `inactive-text` | string / Component | — | — |
|
||||
| active-text | text displayed when in `on` state | string | — | — |
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
<template>
|
||||
<el-switch v-model="value" :active-icon="active" :inactive-icon="inactive">
|
||||
<el-switch v-model="value1" :active-icon="active" :inactive-icon="inactive">
|
||||
</el-switch>
|
||||
<br />
|
||||
<el-switch
|
||||
v-model="value2"
|
||||
style="margin-left: 24px"
|
||||
inline-prompt
|
||||
:active-icon="active"
|
||||
:inactive-icon="inactive"
|
||||
>
|
||||
</el-switch>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { CircleCheckFilled, CircleCloseFilled } from '@element-plus/icons'
|
||||
import { Check, Close } from '@element-plus/icons'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: true,
|
||||
active: CircleCheckFilled,
|
||||
inactive: CircleCloseFilled,
|
||||
value1: true,
|
||||
value2: true,
|
||||
active: Check,
|
||||
inactive: Close,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,14 +5,25 @@
|
||||
inactive-text="Pay by year"
|
||||
>
|
||||
</el-switch>
|
||||
<br />
|
||||
<el-switch
|
||||
v-model="value2"
|
||||
style="display: block"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
active-text="Pay by month"
|
||||
inactive-text="Pay by year"
|
||||
/>
|
||||
<br />
|
||||
<el-switch v-model="value3" inline-prompt active-text="是" inactive-text="否">
|
||||
</el-switch>
|
||||
<el-switch
|
||||
v-model="value4"
|
||||
inline-prompt
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
active-text="Y"
|
||||
inactive-text="N"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -21,6 +32,8 @@ export default {
|
||||
return {
|
||||
value1: true,
|
||||
value2: true,
|
||||
value3: true,
|
||||
value4: true,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -24,6 +24,25 @@ describe('Switch.vue', () => {
|
||||
expect(leftLabelWrapper.text()).toEqual('off')
|
||||
})
|
||||
|
||||
test('inline prompt', () => {
|
||||
const wrapper = mount(Switch, {
|
||||
props: {
|
||||
inlinePrompt: true,
|
||||
activeText: 'on',
|
||||
inactiveText: 'off',
|
||||
activeColor: '#0f0',
|
||||
inactiveColor: '#f00',
|
||||
width: 100,
|
||||
},
|
||||
})
|
||||
const vm = wrapper.vm
|
||||
const coreEl = vm.$el.querySelector('.el-switch__core')
|
||||
expect(coreEl.style.backgroundColor).toEqual('rgb(255, 0, 0)')
|
||||
expect(coreEl.style.width).toEqual('100px')
|
||||
const leftLabelWrapper = wrapper.find('.el-switch__inner span')
|
||||
expect(leftLabelWrapper.text()).toEqual('o')
|
||||
})
|
||||
|
||||
test('switch with icons', () => {
|
||||
const wrapper = mount(Switch, {
|
||||
props: {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
@keydown.enter="switchValue"
|
||||
/>
|
||||
<span
|
||||
v-if="inactiveIcon || inactiveText"
|
||||
v-if="!inlinePrompt && (inactiveIcon || inactiveText)"
|
||||
:class="[
|
||||
'el-switch__label',
|
||||
'el-switch__label--left',
|
||||
@@ -37,12 +37,48 @@
|
||||
class="el-switch__core"
|
||||
:style="{ width: (width || 40) + 'px' }"
|
||||
>
|
||||
<div v-if="inlinePrompt" class="el-switch__inner">
|
||||
<template v-if="activeIcon || inactiveIcon">
|
||||
<el-icon
|
||||
v-if="activeIcon"
|
||||
class="is-icon"
|
||||
:class="checked ? 'is-show' : 'is-hide'"
|
||||
>
|
||||
<component :is="activeIcon" />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-if="inactiveIcon"
|
||||
class="is-icon"
|
||||
:class="!checked ? 'is-show' : 'is-hide'"
|
||||
>
|
||||
<component :is="inactiveIcon" />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template v-else-if="activeText || inactiveIcon">
|
||||
<span
|
||||
v-if="activeText"
|
||||
class="is-text"
|
||||
:class="checked ? 'is-show' : 'is-hide'"
|
||||
:aria-hidden="!checked"
|
||||
>
|
||||
{{ activeText.substr(0, 1) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="inactiveText"
|
||||
class="is-text"
|
||||
:class="!checked ? 'is-show' : 'is-hide'"
|
||||
:aria-hidden="checked"
|
||||
>
|
||||
{{ inactiveText.substr(0, 1) }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="el-switch__action">
|
||||
<el-icon v-if="loading" class="is-loading"><loading /></el-icon>
|
||||
</div>
|
||||
</span>
|
||||
<span
|
||||
v-if="activeIcon || activeText"
|
||||
v-if="!inlinePrompt && (activeIcon || activeText)"
|
||||
:class="[
|
||||
'el-switch__label',
|
||||
'el-switch__label--right',
|
||||
@@ -56,6 +92,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
@@ -119,6 +156,10 @@ export default defineComponent({
|
||||
type: Number,
|
||||
default: 40,
|
||||
},
|
||||
inlinePrompt: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
activeIcon: {
|
||||
type: [String, Object] as PropType<string | Component>,
|
||||
default: '',
|
||||
|
||||
@@ -49,7 +49,10 @@
|
||||
display: inline-block;
|
||||
}
|
||||
.#{$namespace}-icon {
|
||||
vertical-align: text-bottom;
|
||||
height: inherit;
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +80,27 @@
|
||||
background-color var(--el-transition-duration);
|
||||
vertical-align: middle;
|
||||
|
||||
.#{$namespace}-switch__inner {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
transition: all var(--el-transition-duration);
|
||||
width: var(--el-switch-button-size);
|
||||
height: var(--el-switch-button-size);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
left: 50%;
|
||||
|
||||
.is-icon,
|
||||
.is-text {
|
||||
color: var(--el-color-white);
|
||||
transition: opacity var(--el-transition-duration);
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$namespace}-switch__action {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
@@ -90,6 +114,25 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--el-switch-off-color);
|
||||
|
||||
.is-icon,
|
||||
.is-text {
|
||||
transition: opacity var(--el-transition-duration);
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.is-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.is-show {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.is-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +145,10 @@
|
||||
margin-left: calc(-1px - var(--el-switch-button-size));
|
||||
color: var(--el-switch-on-color);
|
||||
}
|
||||
.#{$namespace}-switch__inner {
|
||||
left: 50%;
|
||||
margin-left: calc(-1px - var(--el-switch-button-size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user