feat(components): [el-switch] switch add size prop (#5101)

* feat: switch add size

* feat: update

* feat: update
This commit is contained in:
kooriookami
2022-01-07 15:43:53 +08:00
committed by GitHub
parent 9e53873742
commit fb76382dd1
7 changed files with 122 additions and 28 deletions

View File

@ -15,6 +15,14 @@ switch/basic
:::
## Sizes
:::demo
switch/sizes
:::
## 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.
@ -73,25 +81,26 @@ switch/prevent-switching
## Attributes
| Attribute | Description | Type | Accepted Values | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | --------------- | ------- |
| model-value / v-model | binding value, it should be equivalent to either `active-value` or `inactive-value`, by default it's `boolean` type | boolean / string / number | — | — |
| 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, only the first character will be rendered for text | 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 | — | — |
| inactive-text | text displayed when in `off` state | string | — | — |
| active-value | switch value when in `on` state | boolean / string / number | — | true |
| inactive-value | switch value when in `off` state | boolean / string / number | — | false |
| active-color | background color when in `on` state | string | — | #409EFF |
| inactive-color | background color when in `off` state | string | — | #C0CCDA |
| border-color | border color of the switch | string | — | — |
| name | input name of Switch | string | — | — |
| validate-event | whether to trigger form validation | boolean | — | true |
| before-change | before-change hook before the switch state changes. If `false` is returned or a `Promise` is returned and then is rejected, will stop switching | function | — | — |
| Attribute | Description | Type | Accepted Values | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | ----------------------- | ------- |
| model-value / v-model | binding value, it should be equivalent to either `active-value` or `inactive-value`, by default it's `boolean` type | boolean / string / number | — | — |
| disabled | whether Switch is disabled | boolean | — | false |
| loading | whether Switch is in loading state | boolean | — | false |
| size | size of Switch | string | large / default / small | default |
| width | width of Switch | number | — | 40 |
| inline-prompt | whether icon or text is displayed inside dot, only the first character will be rendered for text | 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 | — | — |
| inactive-text | text displayed when in `off` state | string | — | — |
| active-value | switch value when in `on` state | boolean / string / number | — | true |
| inactive-value | switch value when in `off` state | boolean / string / number | — | false |
| active-color | background color when in `on` state | string | — | #409EFF |
| inactive-color | background color when in `off` state | string | — | #C0CCDA |
| border-color | border color of the switch | string | — | — |
| name | input name of Switch | string | — | — |
| validate-event | whether to trigger form validation | boolean | — | true |
| before-change | before-change hook before the switch state changes. If `false` is returned or a `Promise` is returned and then is rejected, will stop switching | function | — | — |
## Events

View File

@ -0,0 +1,23 @@
<template>
<el-switch
v-model="value"
size="large"
active-text="Open"
inactive-text="Close"
/>
<br />
<el-switch v-model="value" active-text="Open" inactive-text="Close" />
<br />
<el-switch
v-model="value"
size="small"
active-text="Open"
inactive-text="Close"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value = ref(true)
</script>

View File

@ -24,6 +24,15 @@ describe('Switch.vue', () => {
expect(leftLabelWrapper.text()).toEqual('off')
})
test('size', () => {
const wrapper = mount(Switch, {
props: {
size: 'large',
},
})
expect(wrapper.find('.el-switch--large').exists()).toBe(true)
})
test('inline prompt', () => {
const wrapper = mount(Switch, {
props: {

View File

@ -5,8 +5,10 @@ import {
INPUT_EVENT,
} from '@element-plus/utils/constants'
import { isBool, isNumber, isString } from '@element-plus/utils/util'
import { isValidComponentSize } from '@element-plus/utils/validators'
import type { ComponentSize } from '@element-plus/utils/types'
import type Switch from './switch.vue'
import type { Component, ExtractPropTypes } from 'vue'
import type { Component, ExtractPropTypes, PropType } from 'vue'
export const switchProps = buildProps({
modelValue: {
@ -81,6 +83,10 @@ export const switchProps = buildProps({
beforeChange: {
type: definePropType<() => Promise<boolean> | boolean>(Function),
},
size: {
type: String as PropType<ComponentSize>,
validator: isValidComponentSize,
},
} as const)
export type SwitchProps = ExtractPropTypes<typeof switchProps>

View File

@ -1,7 +1,6 @@
<template>
<div
class="el-switch"
:class="{ 'is-disabled': switchDisabled, 'is-checked': checked }"
:class="switchKls"
role="switch"
:aria-checked="checked"
:aria-disabled="switchDisabled"
@ -105,7 +104,7 @@ import {
CHANGE_EVENT,
INPUT_EVENT,
} from '@element-plus/utils/constants'
import { useDisabled, useFormItem } from '@element-plus/hooks'
import { useDisabled, useFormItem, useSize } from '@element-plus/hooks'
import { switchProps, switchEmits } from './switch'
const COMPONENT_NAME = 'ElSwitch'
@ -121,10 +120,19 @@ export default defineComponent({
const { formItem } = useFormItem()
const switchDisabled = useDisabled(computed(() => props.loading))
const switchSize = useSize()
const isModelValue = ref(props.modelValue !== false)
const input = ref<HTMLInputElement>()
const core = ref<HTMLSpanElement>()
const prefix = 'el-switch'
const switchKls = computed(() => [
prefix,
`${prefix}--${switchSize.value}`,
switchDisabled.value ? 'is-disabled' : '',
checked.value ? 'is-checked' : '',
])
watch(
() => props.modelValue,
() => {
@ -235,6 +243,7 @@ export default defineComponent({
core,
switchDisabled,
checked,
switchKls,
handleChange,
switchValue,
focus,

View File

@ -615,7 +615,6 @@ $switch: map.merge(
(
'on-color': var(--el-color-primary),
'off-color': var(--el-border-color-base),
'font-size': var(--el-font-size-base),
'core-border-radius': 10px,
'width': 40px,
'height': 20px,

View File

@ -4,6 +4,26 @@
@use 'mixins/var' as *;
@use 'common/var' as *;
$switch-height: () !default;
$switch-height: map.merge(
(
'large': 40px,
'default': 32px,
'small': 24px,
),
$switch-height
);
$switch-font-size: () !default;
$switch-font-size: map.merge(
(
'large': 14px,
'default': 14px,
'small': 12px,
),
$switch-font-size
);
@include b(switch) {
@include set-component-css-var('switch', $switch);
}
@ -12,9 +32,9 @@
display: inline-flex;
align-items: center;
position: relative;
font-size: var(--el-switch-font-size);
font-size: map.get($switch-font-size, 'default');
line-height: var(--el-switch-height);
height: var(--el-switch-height);
height: map.get($switch-height, 'default');
vertical-align: middle;
@include when(disabled) {
& .#{$namespace}-switch__core,
@ -27,7 +47,7 @@
transition: var(--el-transition-duration-fast);
height: var(--el-switch-height);
display: inline-block;
font-size: var(--el-switch-font-size);
font-size: map.get($switch-font-size, 'default');
font-weight: 500;
cursor: pointer;
vertical-align: middle;
@ -45,11 +65,12 @@
}
& * {
line-height: 1;
font-size: var(--el-switch-font-size);
font-size: map.get($switch-font-size, 'default');
display: inline-block;
}
.#{$namespace}-icon {
height: inherit;
svg {
vertical-align: middle;
}
@ -140,11 +161,13 @@
.#{$namespace}-switch__core {
border-color: var(--el-switch-on-color);
background-color: var(--el-switch-on-color);
.#{$namespace}-switch__action {
left: 100%;
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));
@ -163,6 +186,7 @@
left: 10px;
}
}
&.#{$namespace}-switch__label--right {
span {
right: 10px;
@ -175,4 +199,19 @@
& .label-fade-leave-active {
opacity: 0;
}
@each $size in (large, small) {
@include m($size) {
font-size: map.get($switch-font-size, $size);
height: map.get($switch-height, $size);
@include e(label) {
font-size: map.get($switch-font-size, $size);
& * {
font-size: map.get($switch-font-size, $size);
}
}
}
}
}