diff --git a/components/collapse/demo/index.vue b/components/collapse/demo/index.vue
index 37ca57d19..7c6230c6e 100644
--- a/components/collapse/demo/index.vue
+++ b/components/collapse/demo/index.vue
@@ -17,6 +17,7 @@ const md = {
- 对复杂区域进行分组和隐藏,保持页面的整洁。
- '手风琴' 是一种特殊的折叠面板,只允许单个内容区域展开。
+
## 代码演示`,
us: `# When To Use
diff --git a/components/divider/demo/index.vue b/components/divider/demo/index.vue
index b3a4a9197..1ea00c62d 100644
--- a/components/divider/demo/index.vue
+++ b/components/divider/demo/index.vue
@@ -9,6 +9,7 @@ const md = {
## 何时使用
- 对不同章节的文本段落进行分割。
- 对行内文字/链接进行分割,例如表格的操作列。
+
## 代码演示`,
us: `# Divider
A divider line separates different content.
diff --git a/components/index.js b/components/index.js
index 252fd8e88..61d21988d 100644
--- a/components/index.js
+++ b/components/index.js
@@ -76,3 +76,5 @@ const SelectOption = Select.Option
const SelectOptGroup = Select.OptGroup
export { Select, SelectOption, SelectOptGroup }
+export { default as Switch } from './switch'
+
diff --git a/components/message/demo/index.vue b/components/message/demo/index.vue
index d76dc0d5f..c9fe688aa 100644
--- a/components/message/demo/index.vue
+++ b/components/message/demo/index.vue
@@ -11,6 +11,7 @@ const md = {
## 何时使用
- 可提供成功、警告和错误等反馈信息。
- 顶部居中显示并自动消失,是一种不打断用户操作的轻量级提示方式。
+
## 代码演示`,
us: `# Message
Display global messages as feedback in response to user operations.
diff --git a/components/notification/demo/index.vue b/components/notification/demo/index.vue
index c67499a4a..73e548064 100644
--- a/components/notification/demo/index.vue
+++ b/components/notification/demo/index.vue
@@ -16,6 +16,7 @@ const md = {
- 较为复杂的通知内容。
- 带有交互的通知,给出用户下一步的行动点。
- 系统主动推送。
+
## 代码演示`,
us: `# Notification
Display a notification message globally.
diff --git a/components/select/demo/index.vue b/components/select/demo/index.vue
index 52cbffa7a..0cf341cb1 100644
--- a/components/select/demo/index.vue
+++ b/components/select/demo/index.vue
@@ -20,6 +20,7 @@ const md = {
## 何时使用
- 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。
- 当选项少时(少于 5 项),建议直接将选项平铺,使用 [Radio](#/cn/components/radio/) 是更好的选择。
+
## 代码演示`,
us: `# Select
Select component to select value from options.
diff --git a/components/spin/Spin.vue b/components/spin/Spin.vue
index d3f70c676..d01090963 100644
--- a/components/spin/Spin.vue
+++ b/components/spin/Spin.vue
@@ -50,13 +50,13 @@ export default {
}
},
watch: {
- spinning (val) {
- const { delay, stateSpinning, spinning } = this
+ spinning () {
+ const { delay, spinning } = this
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
}
- if (stateSpinning && !spinning) {
+ if (!spinning) {
this.debounceTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), 200)
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
diff --git a/components/spin/demo/delayAndDebounce.md b/components/spin/demo/delayAndDebounce.md
index 35f4f7507..bbd6fb4a3 100644
--- a/components/spin/demo/delayAndDebounce.md
+++ b/components/spin/demo/delayAndDebounce.md
@@ -23,7 +23,7 @@ Specifies a delay for loading state. If `spinning` ends during delay, loading st
可以点击‘切换’按钮,延迟显示 loading 效果。当 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态。
- 切换
+ Loading state:
+```
diff --git a/components/switch/demo/disabled.md b/components/switch/demo/disabled.md
new file mode 100644
index 000000000..36dc4d6fa
--- /dev/null
+++ b/components/switch/demo/disabled.md
@@ -0,0 +1,33 @@
+
+#### 不可用
+Switch 失效状态。
+
+
+
+#### Disabled
+Disabled state of `Switch`.
+
+
+```html
+
+
+
+
+```
diff --git a/components/switch/demo/index.vue b/components/switch/demo/index.vue
new file mode 100644
index 000000000..ba2b6be80
--- /dev/null
+++ b/components/switch/demo/index.vue
@@ -0,0 +1,55 @@
+
diff --git a/components/switch/demo/loading.md b/components/switch/demo/loading.md
new file mode 100644
index 000000000..22a68318b
--- /dev/null
+++ b/components/switch/demo/loading.md
@@ -0,0 +1,19 @@
+
+#### 加载中
+标识开关操作仍在执行中。
+
+
+
+#### Loading
+Mark a pending state of switch.
+
+
+```html
+
+
+
+```
diff --git a/components/switch/demo/size.md b/components/switch/demo/size.md
new file mode 100644
index 000000000..20ca2aa5a
--- /dev/null
+++ b/components/switch/demo/size.md
@@ -0,0 +1,19 @@
+
+#### 两种大小
+`size="small"` 表示小号开关。
+
+
+
+#### Two sizes
+`size="small"` represents a small sized switch.
+
+
+```html
+
+
+
+```
diff --git a/components/switch/demo/text.md b/components/switch/demo/text.md
new file mode 100644
index 000000000..1c7996d9f
--- /dev/null
+++ b/components/switch/demo/text.md
@@ -0,0 +1,24 @@
+
+#### 文字和图标
+带有文字和图标。
+
+
+
+#### Text & icon
+With text and icon.
+
+
+```html
+
+
+
+```
diff --git a/components/switch/index.en-US.md b/components/switch/index.en-US.md
new file mode 100644
index 000000000..e94c5223e
--- /dev/null
+++ b/components/switch/index.en-US.md
@@ -0,0 +1,20 @@
+## API
+
+| Property | Description | Type | Default |
+| -------- | ----------- | ---- | ------- |
+| autoFocus | get focus when component mounted | boolean | false |
+| checked | determine whether the `Switch` is checked | boolean | false |
+| checkedChildren | content to be shown when the state is checked | string\|slot | |
+| defaultChecked | to set the initial state | boolean | false |
+| disabled | Disable switch | boolean | false |
+| loading | loading state of switch | boolean | false |
+| size | the size of the `Switch`, options: `default` `small` | string | default |
+| unCheckedChildren | content to be shown when the state is unchecked | string\|slot | |
+| onChange | a callback function, can be executed when the checked state is changing | Function(checked:Boolean) | |
+
+## Methods
+
+| Name | Description |
+| ---- | ----------- |
+| blur() | remove focus |
+| focus() | get focus |
diff --git a/components/switch/index.vue b/components/switch/index.vue
new file mode 100644
index 000000000..916dca3ae
--- /dev/null
+++ b/components/switch/index.vue
@@ -0,0 +1,75 @@
+
diff --git a/components/switch/index.zh-CN.md b/components/switch/index.zh-CN.md
new file mode 100644
index 000000000..89cf59bd5
--- /dev/null
+++ b/components/switch/index.zh-CN.md
@@ -0,0 +1,20 @@
+## API
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| autoFocus | 组件自动获取焦点 | boolean | false |
+| checked | 指定当前是否选中 | boolean | false |
+| checkedChildren | 选中时的内容 | string\|slot | |
+| defaultChecked | 初始是否选中 | boolean | false |
+| disabled | 是否禁用 | boolean | false |
+| loading | 加载中的开关 | boolean | false |
+| size | 开关大小,可选值:`default` `small` | string | default |
+| unCheckedChildren | 非选中时的内容 | string\|slot | |
+| onChange | 变化时回调函数 | Function(checked:Boolean) | |
+
+## 方法
+
+| 名称 | 描述 |
+| --- | --- |
+| blur() | 移除焦点 |
+| focus() | 获取焦点 |
diff --git a/components/switch/style/index.js b/components/switch/style/index.js
new file mode 100644
index 000000000..cf31ed80f
--- /dev/null
+++ b/components/switch/style/index.js
@@ -0,0 +1,2 @@
+import '../../style/index.less'
+import './index.less'
diff --git a/components/switch/style/index.less b/components/switch/style/index.less
new file mode 100644
index 000000000..987f1a601
--- /dev/null
+++ b/components/switch/style/index.less
@@ -0,0 +1,165 @@
+@import "../../style/themes/default";
+@import "../../style/mixins/index";
+
+@switch-prefix-cls: ~"@{ant-prefix}-switch";
+@switch-duration: .36s;
+
+.@{switch-prefix-cls} {
+ .reset-component;
+ position: relative;
+ display: inline-block;
+ box-sizing: border-box;
+ height: @switch-height;
+ min-width: 44px;
+ line-height: @switch-height - 2px;
+ vertical-align: middle;
+ border-radius: 100px;
+ border: 1px solid transparent;
+ background-color: @disabled-color;
+ cursor: pointer;
+ transition: all @switch-duration;
+ user-select: none;
+
+ &-inner {
+ color: #fff;
+ font-size: @font-size-sm;
+ margin-left: 24px;
+ margin-right: 6px;
+ display: block;
+ }
+
+ &:before,
+ &:after {
+ position: absolute;
+ width: @switch-height - 4px;
+ height: @switch-height - 4px;
+ left: 1px;
+ top: 1px;
+ border-radius: 18px;
+ background-color: @component-background;
+ content: " ";
+ cursor: pointer;
+ transition: all @switch-duration @ease-in-out-circ;
+ }
+
+ &:after {
+ box-shadow: 0 2px 4px 0 rgba(0, 35, 11, .2);
+ }
+
+ &:active:before,
+ &:active:after {
+ width: 24px;
+ }
+
+ &:before {
+ content: "\e64d";
+ font-family: anticon;
+ animation: loadingCircle 1s infinite linear;
+ text-align: center;
+ background: transprent;
+ z-index: 1;
+ display: none;
+ font-size: 12px;
+ }
+
+ &-loading:before {
+ display: inline-block;
+ color: @text-color;
+ }
+
+ &-checked&-loading:before {
+ color: @switch-color;
+ }
+
+ &:focus {
+ box-shadow: 0 0 0 2px fade(@switch-color, 20%);
+ outline: 0;
+ }
+
+ &:focus:hover {
+ box-shadow: none;
+ }
+
+ &-small {
+ height: @switch-sm-height;
+ min-width: 28px;
+ line-height: @switch-sm-height - 2px;
+
+ .@{switch-prefix-cls}-inner {
+ margin-left: 18px;
+ margin-right: 3px;
+ font-size: @font-size-sm;
+ }
+
+ &:before,
+ &:after {
+ width: @switch-sm-height - 4px;
+ height: @switch-sm-height - 4px;
+ }
+
+ &:active:before,
+ &:active:after {
+ width: 16px;
+ }
+ }
+
+ &-small&-checked {
+ &:before,
+ &:after {
+ left: 100%;
+ margin-left: -12.5px;
+ }
+
+ .@{switch-prefix-cls}-inner {
+ margin-left: 3px;
+ margin-right: 18px;
+ }
+ }
+
+ &-small:active&-checked:before,
+ &-small:active&-checked:after {
+ margin-left: -16.5px;
+ }
+
+ &-small&-loading:before {
+ animation: AntSwitchSmallLoadingCircle 1s infinite linear;
+ font-weight: bold;
+ }
+
+ &-checked {
+ background-color: @switch-color;
+
+ .@{switch-prefix-cls}-inner {
+ margin-left: 6px;
+ margin-right: 24px;
+ }
+
+ &:before,
+ &:after {
+ left: 100%;
+ margin-left: -19px;
+ }
+
+ &:active:before,
+ &:active:after {
+ margin-left: -25px;
+ }
+ }
+
+ &-loading,
+ &-disabled {
+ pointer-events: none;
+ opacity: @switch-disabled-opacity;
+ }
+}
+
+@keyframes AntSwitchSmallLoadingCircle {
+ 0% {
+ transform-origin: 50% 50%;
+ transform: rotate(0deg) scale(0.66667);
+ }
+ 100% {
+ transform-origin: 50% 50%;
+ transform: rotate(360deg) scale(0.66667);
+ }
+}
diff --git a/components/vc-switch/PropTypes.js b/components/vc-switch/PropTypes.js
new file mode 100644
index 000000000..7c2a8938f
--- /dev/null
+++ b/components/vc-switch/PropTypes.js
@@ -0,0 +1,15 @@
+import PropTypes from '../_util/vue-types'
+
+export const switchPropTypes = {
+ prefixCls: PropTypes.string,
+ disabled: PropTypes.bool.def(false),
+ checkedChildren: PropTypes.any,
+ unCheckedChildren: PropTypes.any,
+ // onChange: PropTypes.func,
+ // onMouseUp: PropTypes.func,
+ // onClick: PropTypes.func,
+ tabIndex: PropTypes.number,
+ checked: PropTypes.bool.def(false),
+ defaultChecked: PropTypes.bool.def(false),
+ autoFocus: PropTypes.bool.def(false),
+}
diff --git a/components/vc-switch/Switch.vue b/components/vc-switch/Switch.vue
new file mode 100644
index 000000000..3100edbfe
--- /dev/null
+++ b/components/vc-switch/Switch.vue
@@ -0,0 +1,122 @@
+
diff --git a/components/vc-switch/assets/index.less b/components/vc-switch/assets/index.less
new file mode 100644
index 000000000..0f7eb65e1
--- /dev/null
+++ b/components/vc-switch/assets/index.less
@@ -0,0 +1,115 @@
+@switchPrefixCls: rc-switch;
+
+@duration: .3s;
+
+.@{switchPrefixCls} {
+ position: relative;
+ display: inline-block;
+ box-sizing: border-box;
+ width: 44px;
+ height: 22px;
+ line-height: 20px;
+ vertical-align: middle;
+ border-radius: 20px 20px;
+ border: 1px solid #ccc;
+ background-color: #ccc;
+ cursor: pointer;
+ transition: all @duration cubic-bezier(0.35, 0, 0.25, 1);
+
+ &-inner {
+ color: #fff;
+ font-size: 12px;
+ position: absolute;
+ left: 24px;
+ }
+
+ &:after {
+ position: absolute;
+ width: 18px;
+ height: 18px;
+ left: 2px;
+ top: 1px;
+ border-radius: 50% 50%;
+ background-color: #fff;
+ content: " ";
+ cursor: pointer;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
+ transform: scale(1);
+ transition: left @duration cubic-bezier(0.35, 0, 0.25, 1);
+ animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
+ animation-duration: @duration;
+ animation-name: rcSwitchOff;
+ }
+
+ &:hover:after {
+ transform: scale(1.1);
+ animation-name: rcSwitchOn;
+ }
+
+ &:focus {
+ box-shadow: 0 0 0 2px tint(#2db7f5, 80%);
+ outline: none;
+ }
+
+ &-checked {
+ border: 1px solid #87d068;
+ background-color: #87d068;
+
+ .@{switchPrefixCls}-inner {
+ left: 6px;
+ }
+
+ &:after {
+ left: 22px;
+ }
+ }
+
+ &-disabled {
+ cursor: no-drop;
+ background: #ccc;
+ border-color: #ccc;
+
+ &:after {
+ background: #9e9e9e;
+ animation-name: none;
+ cursor: no-drop;
+ }
+
+ &:hover:after {
+ transform: scale(1);
+ animation-name: none;
+ }
+ }
+
+ &-label {
+ display: inline-block;
+ line-height: 20px;
+ font-size: 14px;
+ padding-left: 10px;
+ vertical-align: middle;
+ white-space: normal;
+ pointer-events: none;
+ user-select: text;
+ }
+}
+
+@keyframes rcSwitchOn {
+ 0% {
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.25);
+ }
+ 100% {
+ transform: scale(1.1);
+ }
+}
+
+@keyframes rcSwitchOff {
+ 0% {
+ transform: scale(1.1);
+ }
+ 100% {
+ transform: scale(1);
+ }
+}
diff --git a/components/vc-switch/demo/simple.vue b/components/vc-switch/demo/simple.vue
new file mode 100644
index 000000000..58bbb6bc1
--- /dev/null
+++ b/components/vc-switch/demo/simple.vue
@@ -0,0 +1,35 @@
+
diff --git a/components/vc-switch/index.js b/components/vc-switch/index.js
new file mode 100644
index 000000000..6c35cdcd3
--- /dev/null
+++ b/components/vc-switch/index.js
@@ -0,0 +1,3 @@
+import Switch from './Switch'
+
+export default Switch
diff --git a/contributors.md b/contributors.md
index 465c0b00d..8be397727 100644
--- a/contributors.md
+++ b/contributors.md
@@ -47,12 +47,11 @@ Badge | done
Breadcrumb | done
Card | done
Collapse | done
-LocaleProvider
Progress
Slider
-Spin
+Spin | done
Steps
-Switch
+Switch | done
Table
Timeline
Transfer
diff --git a/examples/demo.js b/examples/demo.js
index dab5ace8d..2e3df11cd 100644
--- a/examples/demo.js
+++ b/examples/demo.js
@@ -23,4 +23,5 @@ export { default as collapse } from 'antd/collapse/demo/index.vue'
export { default as notification } from 'antd/notification/demo/index.vue'
export { default as message } from 'antd/message/demo/index.vue'
export { default as spin } from 'antd/spin/demo/index.vue'
+export { default as switch } from 'antd/switch/demo/index.vue'