diff --git a/components/spin/demo/full-page-load.md b/components/spin/demo/full-page-load.md
new file mode 100644
index 0000000000..2d65f8b94d
--- /dev/null
+++ b/components/spin/demo/full-page-load.md
@@ -0,0 +1,25 @@
+# 基本用法
+
+- order: 2
+
+区块加载。
+
+---
+
+````jsx
+
+var Spin = antd.Spin;
+var container = document.getElementById('components-spin-demo-full-page-load');
+
+var pageStyle = {
+ paddingBottom: '60px',
+ paddingTop: '60px',
+ textAlign: 'center'
+}
+
+React.render(
+
+
+
, container);
+
+````
\ No newline at end of file
diff --git a/components/spin/demo/page-element.md b/components/spin/demo/page-element.md
new file mode 100644
index 0000000000..846e195b29
--- /dev/null
+++ b/components/spin/demo/page-element.md
@@ -0,0 +1,36 @@
+# 基本用法
+
+- order: 0
+
+作为页面元素使用。
+
+---
+
+````jsx
+var Spin = antd.Spin;
+var container = document.getElementById('components-spin-demo-page-element');
+
+var divStyle = {
+ textAlign: 'center',
+ width: '100%',
+ backgroundColor: 'rgba(0,0,0,0.05)',
+ borderRadius: '4px',
+ marginBottom: '20px',
+ padding: '.66em 1.5em',
+ margin: '20px 0'
+}
+
+React.render(
+ , container);
+
+````
\ No newline at end of file
diff --git a/components/spin/index.jsx b/components/spin/index.jsx
new file mode 100644
index 0000000000..2e00e710ed
--- /dev/null
+++ b/components/spin/index.jsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { classSet } from 'rc-util';
+
+let AntSpin = React.createClass({
+ getDefaultProps() {
+ return {
+ size: 'sm',
+ type: 'default'
+ };
+ },
+
+ propTypes: {
+ className: React.PropTypes.string,
+ size: React.PropTypes.oneOf(['sm', 'md', 'lg']),
+ type: React.PropTypes.oneOf(['default', 'primary', 'inverted'])
+ },
+
+ render() {
+ const props = this.props;
+
+ let className = classSet({
+ spin: 1,
+ [`spin-${props.type}`]: 1,
+ [`spin-${props.size}`]: 1,
+ [props.className]: !!props.className
+ });
+
+ return (
+
+
+
+
+
+ );
+ }
+});
+
+export default AntSpin;
diff --git a/components/spin/index.md b/components/spin/index.md
new file mode 100644
index 0000000000..4f2036e97f
--- /dev/null
+++ b/components/spin/index.md
@@ -0,0 +1,20 @@
+# Spin
+
+- category: Components
+- chinese: 加载动画
+- type: 展示
+
+---
+
+用于页面和区块的loading状态。
+
+## 何时使用
+
+页面局部处于等待数据渲染时。
+
+## API
+
+| 参数 | 类型 | 默认值 |说明 |
+|------------|----------------|-------------|--------------|
+| size | enum | sm | spin组件中点的大小,可选值为sm md lg
+| type | enum | default | spin组件中点的而色值,可选值为default primary inverted
\ No newline at end of file
diff --git a/index.js b/index.js
index 3fc96e5c7e..2ec648f13a 100644
--- a/index.js
+++ b/index.js
@@ -44,7 +44,8 @@ const antd = {
Badge: require('./components/badge'),
Menu: require('./components/menu'),
Timeline: require('./components/timeline'),
- Icon: require('./components/iconfont')
+ Icon: require('./components/iconfont'),
+ Spin: require('./components/spin')
};
// deprecate antd.confirm
diff --git a/style/components/index.less b/style/components/index.less
index 56e01b1cbb..318fc647b2 100644
--- a/style/components/index.less
+++ b/style/components/index.less
@@ -34,3 +34,4 @@
@import "affix";
@import "badge";
@import "timeline";
+@import "spin";
diff --git a/style/components/spin.less b/style/components/spin.less
new file mode 100644
index 0000000000..6074b7fcf9
--- /dev/null
+++ b/style/components/spin.less
@@ -0,0 +1,70 @@
+@import "../mixins/index";
+
+// root of component
+// ------------------------------
+
+.spin {
+ display: inline-block;
+ font-size: @spin-dot-size;
+ height: @spin-dot-size;
+ position: relative;
+ text-align: center;
+ vertical-align: middle;
+}
+
+// dots
+// ------------------------------
+
+.spin-dot {
+ .animation(pulse 1s infinite ease-in-out);
+ .square(1em);
+ border-radius: 50%;
+ display: inline-block;
+ vertical-align: top;
+}
+&.spin-dot-second {
+ .animation-delay(200ms);
+ margin-left: 1em;
+}
+&.spin-dot-third {
+ .animation-delay(400ms);
+ margin-left: 1em;
+}
+
+// Types
+// ------------------------------
+
+// default
+.spin-default > .spin-dot { background-color: @spin-dot-default; }
+
+// primary
+.spin-primary > .spin-dot { background-color: @spin-dot-primary; }
+
+// inverted
+.spin-inverted > .spin-dot { background-color: @spin-dot-inverted; }
+
+
+// Sizes
+// ------------------------------
+
+// small
+.spin-sm {
+ font-size: @spin-dot-size-sm;
+ height: @spin-dot-size-sm;
+}
+
+// large
+.spin-lg {
+ font-size: @spin-dot-size-lg;
+ height: @spin-dot-size-lg;
+}
+
+// pulse
+@-webkit-keyframes pulse {
+ 0%, 80%, 100% { opacity: 0; }
+ 40% { opacity: 1; }
+}
+@keyframes pulse {
+ 0%, 80%, 100% { opacity: 0; }
+ 40% { opacity: 1; }
+}
diff --git a/style/themes/default/custom.less b/style/themes/default/custom.less
index 9f1cdda637..85f8aeb3f6 100644
--- a/style/themes/default/custom.less
+++ b/style/themes/default/custom.less
@@ -138,3 +138,14 @@
@form-item-margin-bottom : 24px;
@overlay-shadow : 0 0 4px rgba(0, 0, 0, 0.17);
+
+// Spin
+// --------------------------------
+@spin-dot-default : #999;
+@spin-dot-inverted : #fff;
+@spin-dot-primary : #2db7f5;
+
+@spin-dot-size : 8px;
+@spin-dot-size-sm : @spin-dot-size / 2;
+@spin-dot-size-lg : @spin-dot-size * 2;
+