This commit is contained in:
罗宪 2015-07-02 13:57:35 +08:00
commit d6960bdcd7
71 changed files with 2005 additions and 457 deletions

10
.gitignore vendored
View File

@ -18,12 +18,10 @@ Thumbs.db
node_modules/ node_modules/
.buildpath .buildpath
.settings .settings
.yml npm-debug.log
data
nohup.out nohup.out
.spmjspid _site
dist
lib
elasticsearch-* elasticsearch-*
config/base.yaml config/base.yaml
_site
npm-debug.log
dist

View File

@ -1,7 +1,39 @@
*.iml
.idea/
.ipr
.iws
*~
~*
*.diff
*.patch
*.bak
.DS_Store
Thumbs.db
.project
.*proj
.svn/
*.swp
*.swo
*.log
node_modules/
.buildpath
.settings
npm-debug.log
nohup.out
_site
dist
lib
elasticsearch-*
config/base.yaml
**/*.md **/*.md
docs docs
node_modules node_modules
theme theme
static static
_site
site site
components
dist
/*.js
*.yml
CNAME

View File

@ -6,6 +6,21 @@
![](https://t.alipayobjects.com/images/rmsweb/T11aVgXc4eXXXXXXXX.svg) ![](https://t.alipayobjects.com/images/rmsweb/T11aVgXc4eXXXXXXXX.svg)
## 使用
### 静态使用
script 直接引用 `dist/antd.js` `dist/antd.css` 后,通过全局变量 antd 使用
### npm
`npm install antd` 后,使用示例
```js
require('antd/style/index.less');
require('antd/lib/datepicker');
```
## 特性 ## 特性
- 丰富实用的 UI 组件。 - 丰富实用的 UI 组件。
@ -47,5 +62,11 @@ $ npm run deploy
#### 构建 #### 构建
```bash ```bash
$ webpack $ npm run build
```
#### 发布到 npm
```bash
$ npm run pub
``` ```

View File

@ -1,26 +0,0 @@
# Accordion
- category: Components
- chinese: 折叠面板
---
游学远方 习礼知书广人网
原是女身暗掩装
校有规训令确 不允许巾帼求学
淑贤女子属深闺居暗房
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -0,0 +1,20 @@
# 基本
- order: 0
最简单的用法,存在 `href` 表示可点。
---
````jsx
var Breadcrumb = require('antd/components/breadcrumb');
React.render(
<Breadcrumb>
<Breadcrumb.Item>首页</Breadcrumb.Item>
<Breadcrumb.Item href="">应用中心</Breadcrumb.Item>
<Breadcrumb.Item href="">应用列表</Breadcrumb.Item>
<Breadcrumb.Item>某应用</Breadcrumb.Item>
</Breadcrumb>
, document.getElementById('components-breadcrumb-demo-basic'));
````

View File

@ -0,0 +1,27 @@
# 带有图标的
- order: 1
图标放在文字前面。
---
````jsx
var Breadcrumb = antd.Breadcrumb;
React.render(
<Breadcrumb>
<Breadcrumb.Item href="">
<i className="anticon anticon-user"></i>
</Breadcrumb.Item>
<Breadcrumb.Item href="">
<i className="anticon anticon-folder-open"></i>
应用列表
</Breadcrumb.Item>
<Breadcrumb.Item>
应用
</Breadcrumb.Item>
</Breadcrumb>
, document.getElementById('components-breadcrumb-demo-withicon'));
````

View File

@ -0,0 +1,36 @@
'use strict';
import React from 'react';
let prefixCls = 'ant-breadcrumb';
let BreadcrumbItem = React.createClass({
render() {
var link = <a className={prefixCls + '-link'} {...this.props}>{this.props.children}</a>;
var slash = <span className={prefixCls + '-slash'}>/</span>;
if (typeof this.props.href === 'undefined') {
link = <span className={prefixCls + '-link'} {...this.props}>{this.props.children}</span>;
}
if (this.props.last) {
slash = '';
}
return <span>{link} {slash}</span>;
}
});
let Breadcrumb = React.createClass({
render() {
if (this.props.children.length > 0) {
var last = this.props.children[this.props.children.length - 1];
last.props.last = true;
}
return (
<div className={prefixCls}>
{this.props.children}
</div>
);
}
});
Breadcrumb.Item = BreadcrumbItem;
export default Breadcrumb;

View File

@ -1,26 +1,14 @@
# BreadCrumb # Breadcrumb
- category: CSS - category: Components
- chinese: 面包屑 - chinese: 面包屑
--- ---
游学远方 习礼知书广人网 显示当前页面在系统层级结构中的位置,并能向上返回。
原是女身暗掩装 ## 何时使用
校有规训令确 不允许巾帼求学 - 当系统拥有超过两级以上的层级结构时;
- 当需要告知用户“你在哪里”时;
淑贤女子属深闺居暗房 - 当需要向上导航的功能时。
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -2,42 +2,44 @@
- order: 4 - order: 4
图标一般放在文字前面,也可以单独存在。
--- ---
````html ````html
<button class="ant-btn ant-btn-primary ant-btn-circle ant-btn-lg"> <button class="ant-btn ant-btn-primary ant-btn-circle ant-btn-lg">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
<button class="ant-btn ant-btn-primary ant-btn-lg"> <button class="ant-btn ant-btn-primary ant-btn-lg">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
<span>大按钮</span> 大按钮
</button> </button>
<button class="ant-btn ant-btn-primary ant-btn-circle"> <button class="ant-btn ant-btn-primary ant-btn-circle">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
<button class="ant-btn ant-btn-primary"> <button class="ant-btn ant-btn-primary">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
<span>中按钮</span> 中按钮
</button> </button>
<button class="ant-btn ant-btn-primary ant-btn-circle ant-btn-sm"> <button class="ant-btn ant-btn-primary ant-btn-circle ant-btn-sm">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
<button class="ant-btn ant-btn-primary ant-btn-sm"> <button class="ant-btn ant-btn-primary ant-btn-sm">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
<span>小按钮</span> 小按钮
</button> </button>
<p></p> <p></p>
<button class="ant-btn ant-btn-ghost ant-btn-circle-outline ant-btn-lg"> <button class="ant-btn ant-btn-ghost ant-btn-circle-outline ant-btn-lg">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
<button class="ant-btn ant-btn-ghost ant-btn-circle-outline"> <button class="ant-btn ant-btn-ghost ant-btn-circle-outline">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
<button class="ant-btn ant-btn-circle-outline ant-btn-sm"> <button class="ant-btn ant-btn-circle-outline ant-btn-sm">
<span class="anticon anticon-search"></span> <i class="anticon anticon-search"></i>
</button> </button>
```` ````

View File

@ -0,0 +1,13 @@
# Collapse
- category: Components
- chinese: 折叠面板
---
可以折叠/展开的内容区域。
## 何时使用
- 对复杂区域进行分组和隐藏,保持页面的整洁。
- `手风琴` 是一种特殊的折叠面板,只允许单个内容区域展开。

View File

@ -7,6 +7,7 @@
--- ---
````jsx ````jsx
// or require('antd/components/datepicker');
var Datepicker = antd.Datepicker; var Datepicker = antd.Datepicker;
React.render( React.render(

View File

@ -21,33 +21,42 @@ defaultCalendarValue.setTime(Date.now());
export default React.createClass({ export default React.createClass({
getInitialState() { getInitialState() {
var value;
if (this.props.value) {
value = new GregorianCalendar(zhCn);
value.setTime(new Date(this.props.value).valueOf());
}
return { return {
value: '' value: value
}; };
}, },
componentWillReceiveProps(nextProps) {
if ('value' in nextProps) {
var value = new GregorianCalendar(zhCn);
value.setTime(new Date(nextProps.value).valueOf());
this.setState({
value: value
});
}
},
getDefaultProps() { getDefaultProps() {
return { return {
format: 'yyyy-MM-dd', format: 'yyyy-MM-dd',
placeholder: '请选择日期' placeholder: '请选择日期',
transitionName: 'slide-up',
onSelect: function () {}
}; };
}, },
componentDidMount() { handleChange(v) {
let state = {}; this.setState({
if (this.props.value) { value: v
let value = new GregorianCalendar(zhCn); });
value.setTime(new Date(this.props.value)); this.props.onSelect(new Date(v.getTime()));
state.value = value;
}
state.disabled = this.props.disabled || function() {};
this.setState(state);
},
handleChange() {
this.props.onSelect(new Date(this.state.value.getTime()));
}, },
render() { render() {
let calendar = ( var calendar = (
<Calendar <Calendar
disabledDate={this.state.disabled} disabledDate={this.props.disabled}
locale={CalendarLocale} locale={CalendarLocale}
orient={['top', 'left']} orient={['top', 'left']}
defaultValue={defaultCalendarValue} defaultValue={defaultCalendarValue}
@ -58,12 +67,13 @@ export default React.createClass({
); );
return ( return (
<Datepicker <Datepicker
transitionName={this.props.transitionName}
trigger={<span className="ant-calendar-picker-icon" />} trigger={<span className="ant-calendar-picker-icon" />}
calendar={calendar} calendar={calendar}
formatter={new DateTimeFormat(this.props.format)} formatter={new DateTimeFormat(this.props.format)}
value={this.state.value} value={this.state.value}
prefixCls="ant-calendar-picker" prefixCls="ant-calendar-picker"
onChange={this.props.onSelect}> onChange={this.handleChange}>
<input placeholder={this.props.placeholder} className="ant-calendar-picker-input"/> <input placeholder={this.props.placeholder} className="ant-calendar-picker-input"/>
</Datepicker> </Datepicker>
); );

View File

@ -23,6 +23,7 @@
| value | 日期 | string | 无 | | value | 日期 | string | 无 |
| format | 展示的日期格式 | string | "yyyy-MM-dd" | | format | 展示的日期格式 | string | "yyyy-MM-dd" |
| disabled | 不可选择的日期 | function | 无 | | disabled | 不可选择的日期 | function | 无 |
| transitionName | 动画名称 | String.可取 'slide-up' | 无. |
| onSelect | 选择日期的回调 | function | 无 | | onSelect | 选择日期的回调 | function | 无 |
| showTime | 显示时间选择条 | boolean | false | | showTime | 显示时间选择条 | boolean | false |

View File

@ -0,0 +1,20 @@
# 基本
- order: 0
数字输入框
---
````jsx
var InputNumber = antd.InputNumber;
function onChange(v){
console.log('changed',v);
}
React.render(
<div><InputNumber min={1} max={10} defaultValue={3} onChange={onChange} style={{width:100}}/></div>
, document.getElementById('components-input-number-demo-basic'));
````

View File

@ -0,0 +1,15 @@
var InputNumber = require('rc-input-number');
var React = require('react');
var AntInputNumber = React.createClass({
getDefaultProps() {
return {
prefixCls: 'ant-input-number'
};
},
render() {
return <InputNumber {...this.props}/>;
}
});
module.exports = AntInputNumber;

View File

@ -0,0 +1,27 @@
# InputNumber
- category: Components
- chinese: 数字输入框
---
通过鼠标或键盘,输入范围内的数值。
## 何时使用
- 当需要获取标准数值时。
## API
属性如下
| 成员 | 说明 | 类型 | 默认值 |
|-------------|----------------|--------------------|--------------|
| min | 最小值 | Number | -Infinity |
| max | 最大值 | Number | Infinity |
| value | 当前值 | Number | |
| step | 每次改变步数 | Number | 1 |
| defaultValue | 初始值 | Number | |
| onChange | 变化回调 | Function | |
| disabled | 禁用 | Boolean | |
| style | 根节点样式 | Object |

View File

@ -1,26 +0,0 @@
# InputNumber
- category: Components
- chinese: 数字输入框
---
游学远方 习礼知书广人网
原是女身暗掩装
校有规训令确 不允许巾帼求学
淑贤女子属深闺居暗房
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -5,22 +5,9 @@
--- ---
游学远方 习礼知书广人网 全局展示操作反馈信息。
原是女身暗掩装 ## 何时使用
校有规训令确 不允许巾帼求学 - 可提供成功、警告和错误等反馈信息。
- 顶部居中显示并自动消失,是一种不打断用户操作的轻量级提示方式。
淑贤女子属深闺居暗房
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -19,12 +19,18 @@ module.exports = function (props) {
function onCancel() { function onCancel() {
var cancelFn = props.onCancel; var cancelFn = props.onCancel;
if (cancelFn) { if (cancelFn) {
var ret;
if (cancelFn.length) { if (cancelFn.length) {
cancelFn(close); ret = cancelFn(close);
} else { } else {
cancelFn(); ret = cancelFn();
if (!ret) {
close(); close();
} }
}
if (ret && ret.then) {
ret.then(close);
}
} else { } else {
close(); close();
} }
@ -33,12 +39,18 @@ module.exports = function (props) {
function onOk() { function onOk() {
var okFn = props.onOk; var okFn = props.onOk;
if (okFn) { if (okFn) {
var ret;
if (okFn.length) { if (okFn.length) {
okFn(close); ret = okFn(close);
} else { } else {
okFn(); ret = okFn();
if (!ret) {
close(); close();
} }
}
if (ret && ret.then) {
ret.then(close);
}
} else { } else {
close(); close();
} }

View File

@ -28,6 +28,9 @@ var Test = React.createClass({
}, },
handleCancel() { handleCancel() {
console.log('点击了取消'); console.log('点击了取消');
this.setState({
visible: false
});
}, },
render() { render() {
return <div> return <div>

View File

@ -0,0 +1,30 @@
# 确认对话框
- order: 5
使用 `confirm()` 可以快捷地弹出确认框。onCancel/onOk 返回 promise 可以延迟关闭
---
````jsx
var confirm = antd.confirm;
function showConfirm(){
confirm({
title: '您是否确认要删除这项内容',
content: '一些解释',
onOk: function() {
alert('1 秒后关闭');
return new Promise(function(resolve){
setTimeout(resolve,1000);
});
},
onCancel: function() {}
});
}
React.render(
<button className="ant-btn" onClick={showConfirm}>
确认对话框
</button>, document.getElementById('components-modal-demo-confirm-promise'));
````

View File

@ -34,6 +34,9 @@ var Test = React.createClass({
}, },
handleCancel() { handleCancel() {
console.log('点击了取消'); console.log('点击了取消');
this.setState({
visible: false
});
}, },
render() { render() {
return <div> return <div>

View File

@ -13,7 +13,8 @@ var Modal = React.createClass({
}, },
handleCancel() { handleCancel() {
this.refs.d.requestClose(); var d = this.refs.d;
d.requestClose();
}, },
getDefaultProps() { getDefaultProps() {

View File

@ -34,7 +34,7 @@
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 |
|------------|----------------|------------------|--------------| |------------|----------------|------------------|--------------|
| title | 标题 | React.Element or String | 无 | | title | 标题 | React.Element or String | 无 |
| onOk | 点击确定回调,参数为关闭函数 | function | 无 | | onOk | 点击确定回调,参数为关闭函数,返回 promise 时 resolve 后自动关闭 | function | 无 |
| onCancel | 取消回调,参数为关闭函数 | function | 无 | | onCancel | 取消回调,参数为关闭函数,返回 promise 时 resolve 后自动关闭 | function | 无 |
| width | 宽度 | String or Number | 375 | | width | 宽度 | String or Number | 375 |
| iconClassName | 图标样式名 | String | anticon-exclamation-circle | | iconClassName | 图标样式名 | String | anticon-exclamation-circle |

View File

@ -0,0 +1,226 @@
# 基本
- order: 0
动画效果示例。
---
````jsx
var cssAnimation = antd.cssAnimation;
var motions = [];
motions = motions.concat([[{
name: '淡入',
value: 'fade',
direction: 'enter',
type: '渐隐'
}, {
name: '淡出',
value: 'fade',
direction: 'leave',
type: '渐隐'
}]]);
motions = motions.concat([[{
name: '中心放大',
value: 'zoom',
direction: 'enter',
type: '缩放'
}, {
name: '中心缩小',
value: 'zoom',
direction: 'leave',
type: '缩放'
}, {
name: '上方放大',
value: 'zoom-up',
direction: 'enter',
type: '缩放'
}, {
name: '上方缩小',
value: 'zoom-up',
direction: 'leave',
type: '缩放'
}, {
name: '下方放大',
value: 'zoom-down',
direction: 'enter',
type: '缩放'
}, {
name: '下方缩小',
value: 'zoom-down',
direction: 'leave',
type: '缩放'
}, {
name: '左方放大',
value: 'zoom-left',
direction: 'enter',
type: '缩放'
}, {
name: '左方缩小',
value: 'zoom-left',
direction: 'leave',
type: '缩放'
}, {
name: '右方放大',
value: 'zoom-right',
direction: 'enter',
type: '缩放'
}, {
name: '右方缩小',
value: 'zoom-right',
direction: 'leave',
type: '缩放'
}]]);
motions = motions.concat([[{
name: '上方滑入',
value: 'move-up',
direction: 'enter',
type: '移动'
}, {
name: '上方滑出',
value: 'move-up',
direction: 'leave',
type: '移动'
}, {
name: '下方滑入',
value: 'move-down',
direction: 'enter',
type: '移动'
}, {
name: '下方滑出',
value: 'move-down',
direction: 'leave',
type: '移动'
}, {
name: '左方滑入',
value: 'move-left',
direction: 'enter',
type: '移动'
}, {
name: '左方滑出',
value: 'move-left',
direction: 'leave',
type: '移动'
}, {
name: '右方滑入',
value: 'move-right',
direction: 'enter',
type: '移动'
}, {
name: '右方滑入',
value: 'move-right',
direction: 'leave',
type: '移动'
}]]);
motions = motions.concat([[{
name: '上方展开',
value: 'slide-up',
direction: 'enter',
type: '伸缩'
}, {
name: '上方缩回',
value: 'slide-up',
direction: 'leave',
type: '伸缩'
}, {
name: '下方展开',
value: 'slide-down',
direction: 'enter',
type: '伸缩'
}, {
name: '下方缩回',
value: 'slide-down',
direction: 'leave',
type: '伸缩'
}, {
name: '左方展开',
value: 'slide-left',
direction: 'enter',
type: '伸缩'
}, {
name: '左方缩回',
value: 'slide-left',
direction: 'leave',
type: '伸缩'
}, {
name: '右方展开',
value: 'slide-right',
direction: 'enter',
type: '伸缩'
}, {
name: '右方缩回',
value: 'slide-right',
direction: 'leave',
type: '伸缩'
}]]);
motions = motions.concat([[{
name: '摇摆',
value: 'swing',
direction: 'enter',
type: '其他'
}]]);
var leave='-leave';
var Test = React.createClass({
handleChange(e) {
var value = e.target.value;
if(value){
this.demoNode.style.visibility='';
cssAnimation(this.demoNode, value, () => {
if(value.slice(-leave.length)===leave){
this.demoNode.style.visibility='hidden';
}
});
}
},
componentDidMount() {
this.demoNode = React.findDOMNode(this.refs.demo);
},
render() {
var options = [<option value="">请选择预设动画</option>].concat(motions.map(function (m) {
var opts = m.map(function (m2) {
return <option value={m2.value + "-" + m2.direction}>{m2.name + " " + m2.value}</option>
});
return <optgroup label={m[0].type}>{opts}</optgroup>;
}));
return <div>
<div className="motion-container">
<div ref="demo" className="motion-example">栗子</div>
</div>
<div className="motion-select">
<select onChange={this.handleChange}>{options}</select>
</div>
</div>;
}
});
React.render(<Test/>, document.getElementById('components-motion-demo-basic'));
````
<style>
.motion-container {
height: 150px;
line-height: 150px;
text-align: center;
margin-bottom: 20px;
}
.motion-example {
background: #4AAFDE;
width: 140px;
height: 140px;
line-height: 140px;
font-size: 18px;
color: #fff;
text-align: center;
display: inline-block !important;
border-radius: 8px;
font-weight: bold;
}
.motion-select {
text-align: center;
}
.code-boxes-col-2-1 {
width:100%;
}
</style>

View File

@ -6,3 +6,20 @@
--- ---
## 组件的动画
通过设置组件的 transitionName 指定组件动画
| 组件 | 中文名 | 采用动画 |
|--------------|---------------------|-------------------------------------------------|
| popover | 气泡浮出层 | `zoom-up` `zoom-down` `zoom-left` `zoom-right` |
| popconfirm | 气泡确认框 | `zoom-up` `zoom-down` `zoom-left` `zoom-right` |
| tooltip | 文字提示框 | `zoom-up` `zoom-down` `zoom-left` `zoom-right` |
| modal | 弹出框 | `zoom` |
| confirm | 弹出确认框 | `zoom` |
| message | 信息提示条 | `move-up` |
| dropdown | 下拉菜单 | `slide-up` |
| select | 选择框 | `slide-up` |
| datepicker | 日期选择框 | `slide-up` |

View File

@ -5,22 +5,9 @@
--- ---
游学远方 习礼知书广人网 采用分页的形式分隔长列表,每次只加载一个页面。
原是女身暗掩装 ## 何时使用
校有规训令确 不允许巾帼求学 - 当加载/渲染所有数据将花费很多时间时;
- 可切换页码浏览数据。
淑贤女子属深闺居暗房
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -0,0 +1,22 @@
# 基本
- order: 0
最简单的用法。
---
````jsx
var Popconfirm = antd.Popconfirm;
function confirm() {
console.log('点击了确定');
}
React.render(
<Popconfirm title="确定要删除这个任务吗?" onConfirm={confirm}>
<a href="javascript:;">删除</a>
</Popconfirm>
, document.getElementById('components-popconfirm-demo-basic'));
````

View File

@ -0,0 +1,37 @@
# 位置
- order: 1
位置有四个方向。
---
````jsx
var Popconfirm = antd.Popconfirm;
var text = '确认文案';
function confirm() {
console.log('点击了确定');
}
React.render(<div>
<Popconfirm placement="left" title={text} onConfirm={confirm}>
<a href="javascript:;">左边</a>
</Popconfirm>
<Popconfirm placement="right" title={text} onConfirm={confirm}>
<a href="javascript:;">右边</a>
</Popconfirm>
<Popconfirm placement="top" title={text} onConfirm={confirm}>
<a href="javascript:;">上边</a>
</Popconfirm>
<Popconfirm placement="bottom" title={text} onConfirm={confirm}>
<a href="javascript:;">下边</a>
</Popconfirm>
</div>, document.getElementById('components-popconfirm-demo-placement'));
````
<style>
.code-box-demo .ant-popover-wrap > a {
margin-right: 1em;
}
</style>

View File

@ -0,0 +1,67 @@
'use strict';
import React from 'react';
import Tooltip from 'rc-tooltip';
const prefixCls = 'ant-popover';
export default React.createClass({
getInitialState() {
return {
visible: false
};
},
getDefaultProps() {
return {
transitionName: '',
placement: 'top',
trigger: 'click',
onConfirm: function() {},
onCancel: function() {}
};
},
confirm: function() {
this.props.onConfirm.call(this);
this.setState({
visible: false
});
},
cancel: function() {
this.props.onCancel.call(this);
this.setState({
visible: false
});
},
render() {
const overlay = <div>
<div className={prefixCls + '-content'}>
<p className={prefixCls + '-message'}>
<i className="anticon anticon-exclamation-circle"></i>
{this.props.title}
</p>
<div className={prefixCls + '-buttons'}>
<button onClick={this.confirm} className="ant-btn ant-btn-primary ant-btn-sm"> </button>
<button onClick={this.cancel} className="ant-btn ant-btn-sm"> </button>
</div>
</div>
</div>;
const transitionName = ({
top: 'zoom-down',
bottom: 'zoom-up',
left: 'zoom-right',
right: 'zoom-left'
})[this.props.placement];
return (
<Tooltip placement={this.props.placement}
prefixCls={prefixCls}
renderPopupToBody={false}
transitionName={transitionName}
visible={this.state.visible}
trigger={this.props.trigger}
overlay={overlay}>
{this.props.children}
</Tooltip>
);
}
});

View File

@ -5,22 +5,20 @@
--- ---
游学远方 习礼知书广人网 点击元素,弹出气泡式的确认框。
原是女身暗掩装 ## 何时使用
校有规训令确 不允许巾帼求学 目标元素的操作需要用户进一步的确认时,在目标元素附近弹出浮层提示,询问用户。
淑贤女子属深闺居暗房 `confirm` 弹出的全屏居中模态对话框相比,交互形式更轻量。
人在远方 处身书斋感迷茫
尤幸与山伯结党 ## API
夜唱诗昼画作 赏雨看星说文学 | 参数 | 说明 | 类型 | 默认值 |
|-----------|------------------------------------------|---------------|--------|
热情暗生不可自抗 | placement | 气泡框位置,可选 `top/left/right/bottom` | string | top |
| title | 确认框的描述 | string | 无 |
怕坦率将心声交代 怕草率泄露祝英台 | onConfirm | 点击确认的回调 | function | 无 |
| onCancel | 卡片内容 | function | 无 |
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -35,4 +35,3 @@ React.render(<div>
margin-right: 1em; margin-right: 1em;
} }
</style> </style>

View File

@ -13,7 +13,7 @@ export default React.createClass({
}; };
}, },
render() { render() {
var overlay = <div> const overlay = <div>
<div className={prefixCls + '-title'}> <div className={prefixCls + '-title'}>
{this.props.title} {this.props.title}
</div> </div>

View File

@ -0,0 +1,12 @@
# Slider
- category: Components
- chinese: 滑动输入条
---
滑动型输入器,展示当前值和可选范围。
## 何时使用
当用户需要在数值区间/自定义区间内进行选择时,输入值可为连续或离散值。

View File

@ -1,6 +0,0 @@
# Step
- category: Components
- chinese: 步骤
---

View File

@ -0,0 +1,36 @@
# 自定义图标步进条
- order: 2
通过设置`Steps.Step`的`icon`属性,可以启用自定义图标。
---
<style>
.my-step-icon {
width: 35px;
height: 35px;
font-size: 35px;
line-height: 1;
position: relative;
top: -9px;
}
.my-step-icon > img {
width: 45px;
height: 45px;
}
</style>
````jsx
var Steps = antd.Steps;
var Step = Steps.Step;
var container = document.getElementById('components-steps-demo-custom-icon');
var imgIcon = <div className='my-step-icon'><img src='https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg'/></div>
React.render(<Steps>
<Step status='finish' title='步骤1' icon={<div className='my-step-icon'><span className='anticon anticon-cloud'></span></div>}></Step>
<Step status='process' title='步骤2' icon={imgIcon}></Step>
<Step status='wait' title='步骤3' icon={<div className='my-step-icon'><span className='anticon anticon-github'></span></div>}></Step>
</Steps>, container);
````

View File

@ -0,0 +1,40 @@
# 基本用法
- order: 0
简单的步骤条。
---
````jsx
var Steps = antd.Steps;
var Step = Steps.Step;
var container = document.getElementById('components-steps-demo-simple');
var steps = [{
status: 'finish',
title: '已完成',
description: '这里是多信息的描述啊'
}, {
status: 'process',
title: '进行中',
description: '这里是多信息的耶哦耶哦哦耶哦耶哦耶哦耶哦耶'
}, {
status: 'wait',
title: '待运行',
description: '这里是多信息的描述啊描述啊描述啊'
}, {
status: 'wait',
title: '待运行',
description: '这里是多信息的描述啊'
}].map(function(s, i) {
return (<Step
key={i}
status={s.status}
title={s.title}
description={s.description}></Step>
);
});
React.render(<Steps>{steps}</Steps>, container);
````

View File

@ -0,0 +1,35 @@
# 迷你版
- order: 1
迷你版的步进条,通过设置`<Steps size='small'>`启用.
---
````jsx
var Steps = antd.Steps;
var Step = Steps.Step;
var container = document.getElementById('components-steps-demo-small-size');
var steps = [{
status: 'finish',
title: '已完成'
}, {
status: 'process',
title: '进行中'
}, {
status: 'wait',
title: '待运行'
}, {
status: 'wait',
title: '待运行'
}].map(function(s, i) {
return (<Step
key={i}
status={s.status}
title={s.title}>
</Step>);
});
React.render(<Steps size="small">{steps}</Steps>, container);
````

View File

@ -0,0 +1,71 @@
# 切换到下一步
- order: 3
随机生成3~6个步骤初始随机进行到其中一个步骤。
---
<style>
.my-step-form {
width: 100%;
}
.my-step-form > div {
margin-bottom: 20px;
}
.my-step-container {
width: 100%;
}
</style>
````jsx
var container = document.getElementById('components-steps-demo-step-next');
var steps = (function generateRandomSteps() {
var n = Math.floor(Math.random() * 3) + 3;
var arr = [];
for (var i = 0; i < n; i++ ) {
arr.push({
title: '步骤' + (i+1)
});
}
return arr;
})();
var MyForm = React.createClass({
getInitialState() {
return {
currentStep: Math.floor(Math.random() * steps.length)
}
},
nextStep() {
var s = this.state.currentStep + 1;
if (s === steps.length) {
s = 0;
}
this.setState({
currentStep: s
});
},
render() {
var cs = this.state.currentStep;
return (<form className='my-step-form'>
<div>当前正在执行第{cs + 1}步</div>
<div className='my-step-container'><Steps>
{steps.map(function(s, i) {
return <Steps.Step
key={i}
status={cs === i ? 'process' : (cs > i ? 'finish' : 'wait')}
title={s.title}
></Steps.Step>
})}
</Steps></div>
<div>表单输入A<input /></div>
<div>表单输入B<input /></div>
<div>表单输入C<input /></div>
<div><span className='ant-btn' onClick={this.nextStep}>下一步</span></div>
</form>)
}
});
React.render(<MyForm></MyForm>, container);
````

View File

@ -0,0 +1,21 @@
'use strict';
var React = require('react');
var Steps = require('rc-steps');
var AntSteps = React.createClass({
getDefaultProps() {
return {
prefixCls: 'ant-steps',
size: 'default'
};
},
render() {
return (<Steps size={this.props.size} prefixCls={this.props.prefixCls}>
{this.props.children}
</Steps>);
}
});
AntSteps.Step = Steps.Step;
module.exports = AntSteps;

39
components/steps/index.md Normal file
View File

@ -0,0 +1,39 @@
# Steps
- category: Components
- chinese: 步骤条
- order: 8
- cols: 1
---
引导用户按照流程完成任务的导航条。
## 何时使用
当任务复杂或者存在先后关系时,将其分解成一系列步骤,从而简化任务。
## API
### Steps
步进条的整体
| 参数 | 说明 | 类型 | 可选值 |默认值 |
|-----------|------------------------------------------|------------|-------|--------|
| size | 可选参数,指定大小(目前只支持普通和迷你两种大小) | string | small, default | default |
### Steps.Step
步进条的每一个步
| 参数 | 说明 | 类型 | 可选值 |默认值 |
|-----------|------------------------------------------|------------|-------|--------|
| status | 必要参数,指定状态 | string | wait, process, finish | 无 |
| title | 必要参数,标题 | string/jsx | 无 | 无 |
| description | 可选参数,步骤的详情描述 | string/jsx | 无 | 空 |
| icon | 可选参数步骤的Icon。如果不指定则使用默认的样式。 | string/jsx | 无 | 空 |
## Todo
* 竖状步进条

View File

View File

@ -0,0 +1,13 @@
# Switch
- category: Components
- chinese: 开关
---
开关选择器。
## 何时使用
- 需要表示开关状态/两种状态之间的切换时;
- 和 `checkbox `的区别是,切换 `switch` 会直接触发状态改变,而 `checkbox` 一般用于状态标记,需要和提交操作配合。

View File

@ -1,26 +1,13 @@
# Table # Table
- category: Components - category: Components
- chinese: 数据表格 - chinese: 表格
--- ---
游学远方 习礼知书广人网 展示行列数据。
原是女身暗掩装 ## 何时使用
校有规训令确 不允许巾帼求学 - 当有大量结构化的数据需要展现时;
- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。
淑贤女子属深闺居暗房
人在远方 处身书斋感迷茫
尤幸与山伯结党
夜唱诗昼画作 赏雨看星说文学
热情暗生不可自抗
怕坦率将心声交代 怕草率泄露祝英台
若擦肩强避开 然後视线骤改 不敢笑逐颜开

View File

@ -10,7 +10,16 @@ var antd = {
Progress: require('./components/progress'), Progress: require('./components/progress'),
Popover: require('./components/popover'), Popover: require('./components/popover'),
Select: require('./components/select'), Select: require('./components/select'),
confirm: require('./components/modal/confirm') Breadcrumb: require('./components/breadcrumb'),
Popconfirm: require('./components/popconfirm'),
confirm: require('./components/modal/confirm'),
Steps: require('./components/steps'),
InputNumber: require('./components/input-number'),
cssAnimation: require('css-animation')
}; };
module.exports = window.antd = antd; module.exports = antd;
if (typeof window !== undefined) {
window.antd = antd;
}

View File

@ -12,18 +12,22 @@
"url": "https://github.com/ant-design/ant-design/issues" "url": "https://github.com/ant-design/ant-design/issues"
}, },
"dependencies": { "dependencies": {
"css-animation": "~1.0.3",
"gregorian-calendar": "~3.0.0", "gregorian-calendar": "~3.0.0",
"gregorian-calendar-format": "~3.0.1", "gregorian-calendar-format": "~3.0.1",
"rc-calendar": "~3.9.0", "rc-calendar": "~3.10.0",
"rc-dialog": "~4.3.2", "rc-dialog": "~4.3.5",
"rc-dropdown": "~1.0.2", "rc-dropdown": "~1.1.1",
"rc-input-number": "~2.0.0",
"rc-menu": "~3.4.0", "rc-menu": "~3.4.0",
"rc-progress": "~1.0.0", "rc-progress": "~1.0.0",
"rc-select": "~3.5.0", "rc-select": "~4.0.0",
"rc-steps": "~1.1.0",
"rc-tabs": "~5.1.0", "rc-tabs": "~5.1.0",
"rc-tooltip": "~2.1.1" "rc-tooltip": "~2.2.3"
}, },
"devDependencies": { "devDependencies": {
"babel": "~5.6.14",
"babel-core": "~5.4.7", "babel-core": "~5.4.7",
"babel-loader": "~5.1.3", "babel-loader": "~5.1.3",
"buildbranch": "0.0.3", "buildbranch": "0.0.3",
@ -44,7 +48,9 @@
"webpack-dev-middleware": "~1.0.11" "webpack-dev-middleware": "~1.0.11"
}, },
"scripts": { "scripts": {
"babel": "rm -rf lib && babel components --out-dir lib",
"build": "npm run clean && webpack && nico build", "build": "npm run clean && webpack && nico build",
"pub": "npm run babel && npm publish && tnpm sync antd",
"start": "npm run clean && nico server --watch", "start": "npm run clean && nico server --watch",
"clean": "rm -rf _site", "clean": "rm -rf _site",
"deploy": "npm run build && node deploy.js", "deploy": "npm run build && node deploy.js",

View File

@ -3,7 +3,7 @@
<div id="{{post.meta.id}}"></div> <div id="{{post.meta.id}}"></div>
{{ post.html }} {{ post.html }}
</div> </div>
<div class="code-box-meta"> <div class="code-box-meta markdown">
<div class="code-box-title">{{ post.title }}</div> <div class="code-box-title">{{ post.title }}</div>
{{ post.meta.description }} {{ post.meta.description }}
<span class="collapse anticon anticon-circle-o-right"></span> <span class="collapse anticon anticon-circle-o-right"></span>

View File

@ -6,6 +6,32 @@
{% block scripts %} {% block scripts %}
<script src="/dist/antd.js"></script> <script src="/dist/antd.js"></script>
<script>
window.require = function(path) {
var result = window;
if (path.indexOf('antd') < 0 ||
path.indexOf('antd/components/') < 0) {
throw 'There should not have modules here 1.';
}
var namespaces = path.split('/');
namespaces.forEach(function(key, i) {
if (i === namespaces.length - 1) {
key = capitalizeFirstLetter(key);
}
if (key !== 'components') {
if (result[key]) {
result = result[key];
} else {
throw 'There should not have modules here 2.';
}
}
});
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
return result;
};
</script>
{% endblock %} {% endblock %}
{% block aside %} {% block aside %}

View File

@ -10,16 +10,25 @@
</h2> </h2>
<div class="code-boxes clearfix"> <div class="code-boxes clearfix">
{%- set items = resource.pages|find_demo_in_component(post.meta.directory) %} {%- set items = resource.pages|find_demo_in_component(post.meta.directory) %}
<div class="code-boxes-col"> {%- if post.meta.cols == 1 %}
<div class="code-boxes-col-1-1">
{%- for item in items %}
{%- set post = item.meta.filepath|parsePost %}
{%- include "code.html" %}
{%- endfor %}
</div>
{%- else %}
<div class="code-boxes-col-2-1">
{%- for item in items|odd %} {%- for item in items|odd %}
{%- set post = item.meta.filepath|parsePost %} {%- set post = item.meta.filepath|parsePost %}
{%- include "code.html" %} {%- include "code.html" %}
{%- endfor %} {%- endfor %}
</div> </div>
<div class="code-boxes-col"> <div class="code-boxes-col-2-1">
{%- for item in items|even %} {%- for item in items|even %}
{%- set post = item.meta.filepath|parsePost %} {%- set post = item.meta.filepath|parsePost %}
{%- include "code.html" %} {%- include "code.html" %}
{%- endfor %} {%- endfor %}
</div> </div>
{%- endif %}
</div> </div>

View File

@ -13,9 +13,7 @@
{% block styles %}{% endblock %} {% block styles %}{% endblock %}
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
<link rel="stylesheet" href="/static/tomorrow.css"> <link rel="stylesheet" href="/static/tomorrow.css">
<script src="https://a.alipayobjects.com/jquery/jquery/1.11.1/jquery.js"></script> <script src="https://a.alipayobjects.com/??jquery/jquery/1.11.1/jquery.js,es5-shim/4.0.5/es5-shim.js,es5-shim/4.0.5/es5-sham.js,html5shiv/3.7.2/src/html5shiv.js,react/0.13.3/react.js,bluebird/2.9.30/bluebird.js"></script>
<!-- react -->
<script src="https://a.alipayobjects.com/react/0.13.2/react.js"></script>
<script src="/static/script.js"></script> <script src="/static/script.js"></script>
{% block scripts %}{% endblock %} {% block scripts %}{% endblock %}
</head> </head>
@ -25,6 +23,7 @@
<img width="60" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg"> <img width="60" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg">
{{ config.site.name }} {{ config.site.name }}
</a> </a>
<div class="search"> <div class="search">
<form> <form>
<input type="text" placeholder="search"> <input type="text" placeholder="search">

View File

@ -2,6 +2,7 @@ var _ = require('lodash');
module.exports = function(nico) { module.exports = function(nico) {
var exports = {}; var exports = {};
var categories;
exports.reader = function(post) { exports.reader = function(post) {
var filepath = post.meta.filepath.toLowerCase(); var filepath = post.meta.filepath.toLowerCase();
@ -37,15 +38,14 @@ module.exports = function(nico) {
return ret; return ret;
}, },
get_components_categories: function(posts) { get_components_categories: function(posts) {
return _.uniq(Object.keys(posts).map(function(key) { categories = categories || _.uniq(Object.keys(posts).map(function(key) {
var item = posts[key]; var item = posts[key];
if (item.meta.template !== 'component') { if (item.meta.template !== 'component') {
return; return;
} }
return item.meta.category; return item.meta.category;
})).sort(function(a, b) { }));
return a - b; return categories;
});
}, },
find_demo_in_component: function(pages, directory) { find_demo_in_component: function(pages, directory) {
var ret = []; var ret = [];

View File

@ -57,7 +57,7 @@ body {
} }
body { body {
font-family: "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", Arial, sans-serif; font-family: Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans-serif;
line-height: 1.5; line-height: 1.5;
color: #888; color: #888;
font-size: 14px; font-size: 14px;
@ -399,6 +399,8 @@ footer {
border-top: 1px solid #eee; border-top: 1px solid #eee;
font-size: 16px; font-size: 16px;
background: #fff; background: #fff;
position: relative;
z-index: 1;
} }
footer ul { footer ul {
@ -445,6 +447,7 @@ footer ul li > a {
background: #F9F9F9; background: #F9F9F9;
padding-top: 10px; padding-top: 10px;
margin-bottom: 50px; margin-bottom: 50px;
float: left;
} }
.aside-container>ul>li { .aside-container>ul>li {
@ -508,13 +511,11 @@ footer ul li > a {
} }
.main-wrapper { .main-wrapper {
display: -webkit-flex;
display: flex;
background: #f9f9f9; background: #f9f9f9;
} }
.main-container { .main-container {
width: calc(100% - 260px); margin-left: 260px;
padding: 30px 40px 120px; padding: 30px 40px 120px;
-webkit-animation: xRightMatrix .5s ease-out; -webkit-animation: xRightMatrix .5s ease-out;
animation: xRightMatrix .5s ease-out; animation: xRightMatrix .5s ease-out;
@ -1638,13 +1639,17 @@ footer ul li > a {
color: #3B4357; color: #3B4357;
} }
.code-boxes-col { .code-boxes-col-1-1 {
width: 75%;
}
.code-boxes-col-2-1 {
width: 50%; width: 50%;
float: left; float: left;
padding-right: 15px; padding-right: 15px;
} }
.code-boxes-col:last-child { .code-boxes-col-2-1:last-child {
padding-right: 0; padding-right: 0;
} }
@ -1681,6 +1686,7 @@ footer ul li > a {
padding: 12px 15px; padding: 12px 15px;
border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px;
transition: background-color 0.4s ease; transition: background-color 0.4s ease;
width: 100%;
} }
.code-box-meta h4, .code-box-meta h4,
@ -1731,6 +1737,7 @@ footer ul li > a {
transform: rotate(90deg); transform: rotate(90deg);
transition: all 0.3s ease; transition: all 0.3s ease;
color: #999; color: #999;
background: #fff;
} }
.code-box.expand .collapse { .code-box.expand .collapse {

View File

@ -0,0 +1,30 @@
@breadcrumbPrefixCls: ant-breadcrumb;
.@{breadcrumbPrefixCls} {
color: #999;
font-size: 12px;
a&-link {
color: #666;
}
> span:last-child {
font-weight: bold;
color: #666;
}
&-slash {
margin: 0 8px;
color: #d9d9d9;
}
.anticon {
font-size: 14px;
position: relative;
top: -1px;
}
.anticon + span {
margin-left: 6px;
}
}

View File

@ -44,7 +44,35 @@
opacity: .2; opacity: .2;
text-decoration: none; text-decoration: none;
&-x {
position: absolute;
display: inline-block;
font-style: normal;
vertical-align: baseline;
text-align: center;
text-transform: none;
text-rendering: auto;
// 更好地渲染字体
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0px;
-moz-osx-font-smoothing: grayscale;
width: 12px;
height: 12px;
font-size: 12px;
line-height: 12px;
color:#000;
top:18px;
right: 18px;
&:before {
content:"\e61e";
display: block;
font-family: "anticon" !important;
}
}
&:hover { &:hover {
color:#000;
opacity: 1; opacity: 1;
filter: alpha(opacity=100); filter: alpha(opacity=100);
text-decoration: none; text-decoration: none;

View File

@ -11,3 +11,6 @@
@import "form"; @import "form";
@import "loading"; @import "loading";
@import "progress"; @import "progress";
@import "steps";
@import "breadcrumb";
@import "inputNumber";

View File

@ -0,0 +1,115 @@
@inputNumberPrefixCls: ant-input-number;
@import "../mixins/iconfont";
.@{inputNumberPrefixCls} {
margin: 0;
padding: 0;
line-height: 26px;
font-size: 12px;
height: 26px;
display: inline-block;
vertical-align: middle;
border: 1px solid #D9D9D9;
border-radius: 5px;
&-handler {
text-align: center;
line-height: 12px;
height: 12px;
overflow: hidden;
}
&-handler-up-inner, &-handler-down-inner {
color: #666666;
user-select: none;
-webkit-user-select: none;
}
&:hover {
border-color: #23c0fa;
.@{inputNumberPrefixCls}-handler-up, .@{inputNumberPrefixCls}-handler-wrap {
border-color: #23c0fa;
}
}
&-disabled:hover {
border-color: #d9d9d9;
.@{inputNumberPrefixCls}-handler-up, .@{inputNumberPrefixCls}-handler-wrap {
border-color: #d9d9d9;
}
}
&-input-wrap {
overflow: hidden;
height: 26px;
}
&-input {
width: 100%;
text-align: center;
outline: 0;
-moz-appearance: textfield;
line-height: 26px;
height: 24px;
transition: all 0.3s ease;
color: #666666;
border: 0;
border-radius: 5px;
padding: 0;
}
&-handler-wrap {
float: right;
border-left: 1px solid #D9D9D9;
width: 20px;
height: 26px;
}
&-handler-up {
border-bottom: 1px solid #D9D9D9;
&-inner {
.iconfont-mixin();
top:-2px;
&:before {
content: "\e611";
transform: rotate(270deg) scale(0.8);
}
}
}
&-handler-down {
&-inner {
.iconfont-mixin();
&:before {
content: "\e611";
transform: rotate(90deg) scale(0.8);
}
}
}
.handler-disabled() {
opacity: 0.72;
&:hover {
color: #999;
border-color: #d9d9d9;
}
}
&-handler-down-disabled, &-handler-up-disabled {
.handler-disabled();
}
&-disabled {
.@{inputNumberPrefixCls}-input {
opacity: 0.72;
cursor: not-allowed;
background-color: #f3f3f3;
}
.@{inputNumberPrefixCls}-handler {
.handler-disabled();
}
}
}

View File

@ -123,23 +123,22 @@
padding: 8px; padding: 8px;
} }
&-descrition { &-message {
[icon] { padding: 8px 8px 12px 8px;
font-size: 14px;
.anticon {
font-size: 16px; font-size: 16px;
margin-right: 2px; margin-right: 6px;
line-height: 18px; line-height: 18px;
} color: #FC8C6E;
[icon='warn-circle'] {
color: #F9C35A;
} }
} }
&-buttons { &-buttons {
text-align: right; text-align: right;
margin-top: 12px; margin-bottom: 8px;
button { button {
margin-left: 2px; margin-left: 5px;
} }
} }

170
style/components/steps.less Normal file
View File

@ -0,0 +1,170 @@
@import "../mixins/index";
@stepsPrefixClass: ~"@{css-prefix}steps";
@active-color: #3fc7fa;
@wait-color: #e9e9e9;
.transition(@transition) {
-webkit-transition: @transition;
-o-transition: @transition;
transition: @transition;
}
.@{stepsPrefixClass} {
font-size: 0;
width: 100%;
line-height: 1.5;
.@{stepsPrefixClass}-item {
position: relative;
display: inline-block;
&.@{stepsPrefixClass}-status-wait {
.@{stepsPrefixClass}-head {
border-color: @wait-color;
background-color: #fff;
> .@{stepsPrefixClass}-icon {
color: @wait-color;
}
}
}
&.@{stepsPrefixClass}-status-process {
.@{stepsPrefixClass}-head {
border-color: @active-color;
background-color: @active-color;
> .@{stepsPrefixClass}-icon {
color: #fff;
}
}
}
&.@{stepsPrefixClass}-status-finish {
.@{stepsPrefixClass}-head {
border-color: @active-color;
background-color: #fff;
> .@{stepsPrefixClass}-icon {
color: @active-color;
}
}
}
&.@{stepsPrefixClass}-custom {
.@{stepsPrefixClass}-head {
background: none;
border: 0;
}
&.@{stepsPrefixClass}-status-process {
.@{stepsPrefixClass}-title {
color: @active-color;
}
}
}
}
.@{stepsPrefixClass}-head, .@{stepsPrefixClass}-main, .@{stepsPrefixClass}-tail {
display: inline-block;
vertical-align: top;
}
.@{stepsPrefixClass}-head {
border:2px solid @wait-color;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
border-radius: 24px;
font-size: 13px;
margin-right: 12px;
.transition(background-color 0.1s ease);
.transition(border-color 0.1s ease);
> .@{stepsPrefixClass}-icon {
line-height: 1;
display: inline-block;
vertical-align: text-top;
color: #3fc7fa;
position: relative;
}
}
.@{stepsPrefixClass}-main {
max-width: 75px;
margin-top: 3px;
}
.@{stepsPrefixClass}-title {
font-size: 14px;
margin-bottom: 4px;
color: #666;
font-weight: bold;
}
.@{stepsPrefixClass}-description {
font-size: 12px;
color: #999;
}
.@{stepsPrefixClass}-tail {
width: 0;
position: relative;
top: 12px;
padding:0 10px;
> i {
display: inline-block;
background: @wait-color;
height: 2px;
border-radius: 1px;
width: 100%;
}
}
&.@{stepsPrefixClass}-small {
.@{stepsPrefixClass}-head {
border:1px solid @wait-color;
width: 18px;
height: 18px;
line-height: 18px;
text-align: center;
border-radius: 18px;
font-size: 10px;
margin-right: 10px;
}
.@{stepsPrefixClass}-main {
max-width: 75px;
margin-top: 0;
}
.@{stepsPrefixClass}-title {
font-size: 12px;
margin-bottom: 4px;
color: #666;
font-weight: bold;
}
.@{stepsPrefixClass}-description {
font-size: 10px;
color: #999;
}
.@{stepsPrefixClass}-tail {
top: 8px;
padding:0 8px;
> i {
height: 1px;
border-radius: 1px;
width: 100%;
}
}
}
&.@{stepsPrefixClass}-init, &.@{stepsPrefixClass}-init.@{stepsPrefixClass}-small {
.@{stepsPrefixClass}-tail {
padding: 0;
}
}
&.@{stepsPrefixClass}-small .@{stepsPrefixClass}-item.@{stepsPrefixClass}-custom .@{stepsPrefixClass}-head, .@{stepsPrefixClass}-item.@{stepsPrefixClass}-custom .@{stepsPrefixClass}-head {
width: inherit;
height: inherit;
line-height: inherit;
border-radius: 0;
border: 0;
background: none;
}
}

View File

@ -1,3 +1,5 @@
@import "../mixins/iconfont";
// font-face // font-face
// @icon-url 字体源文件的地址 // @icon-url 字体源文件的地址
@font-face { @font-face {
@ -10,22 +12,7 @@
} }
.@{iconfont-css-prefix} { .@{iconfont-css-prefix} {
position: relative; .iconfont-mixin();
display: inline-block;
font-style: normal;
vertical-align: baseline;
text-align: center;
text-transform: none;
text-rendering: auto;
// 更好地渲染字体
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0px;
-moz-osx-font-smoothing: grayscale;
&:before {
display: block;
font-family: "anticon" !important;
}
} }
// 方向性图标 // 方向性图标
.@{iconfont-css-prefix}-step-backward:before {content:"\e662";} .@{iconfont-css-prefix}-step-backward:before {content:"\e662";}

View File

@ -1,156 +1,31 @@
.effect() { .motion-common() {
animation-duration: 0.25s; animation-duration: .24s;
animation-fill-mode: both; animation-fill-mode: both;
display: block !important; display: block !important;
} }
.zoom-enter { .make-motion(@className, @keyframeName) {
opacity: 0; .@{className}-enter {
.effect(); .motion-common();
animation-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
animation-play-state: paused; animation-play-state: paused;
} }
.@{className}-leave {
.zoom-leave { .motion-common();
.effect();
animation-timing-function: cubic-bezier(0.6, -0.3, 0.74, 0.05);
animation-play-state: paused; animation-play-state: paused;
} }
.@{className}-enter.@{className}-enter-active {
.zoom-enter.zoom-enter-active { animation-name: ~"@{keyframeName}In";
animation-name: zoomIn;
animation-play-state: running; animation-play-state: running;
} }
.@{className}-leave.@{className}-leave-active {
.zoom-leave.zoom-leave-active { animation-name: ~"@{keyframeName}Out";
animation-name: zoomOut;
animation-play-state: running; animation-play-state: running;
} }
@keyframes zoomIn {
0% {
opacity: 0;
transform-origin: 50% 50%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 50% 50%;
transform: scale(1, 1);
}
}
@keyframes zoomOut {
0% {
opacity: 1;
transform-origin: 50% 50%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 50% 50%;
transform: scale(0, 0);
}
} }
.slide-up-enter { @import "motion/fade";
.effect(); @import "motion/move";
transform-origin: 0 0; @import "motion/other";
opacity: 0; @import "motion/slide";
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1); @import "motion/swing";
animation-play-state: paused; @import "motion/zoom";
}
.slide-up-leave {
.effect();
transform-origin: 0 0;
opacity: 1;
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
animation-play-state: paused;
}
.slide-up-enter.slide-up-enter-active {
animation-name: slideUpIn;
animation-play-state: running;
}
.slide-up-leave.slide-up-leave-active {
animation-name: slideUpOut;
animation-play-state: running;
}
@keyframes slideUpIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
}
@keyframes slideUpOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
}
.fade-enter {
opacity: 0;
.effect();
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
animation-play-state: paused;
}
.fade-leave {
.effect();
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
animation-play-state: paused;
}
.fade-enter.fade-enter-active {
animation-name: fadeIn;
animation-play-state: running;
}
.fade-leave.fade-leave-active {
animation-name: fadeOut;
animation-play-state: running;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes loadingCircle {
0% {
transform-origin: 50% 50%;
transform: rotate(0deg);
}
100% {
transform-origin: 50% 50%;
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,40 @@
.fade-enter {
opacity: 0;
.motion-common();
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
animation-play-state: paused;
}
.fade-leave {
.motion-common();
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
animation-play-state: paused;
}
.fade-enter.fade-enter-active {
animation-name: fadeIn;
animation-play-state: running;
}
.fade-leave.fade-leave-active {
animation-name: fadeOut;
animation-play-state: running;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

119
style/core/motion/move.less Normal file
View File

@ -0,0 +1,119 @@
.move-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter {
opacity: 0;
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1);
}
.@{className}-leave {
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
}
}
.move-motion(move-up, moveUp);
.move-motion(move-down, moveDown);
.move-motion(move-left, moveLeft);
.move-motion(move-right, moveRight);
@keyframes moveDownIn {
0% {
transform-origin: 0 0;
transform: translateY(100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
}
@keyframes moveDownOut {
0% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateY(100%);
opacity: 0;
}
}
@keyframes moveLeftIn {
0% {
transform-origin: 0 0;
transform: translateX(-100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
}
@keyframes moveLeftOut {
0% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes moveRightIn {
0% {
opacity: 0;
transform-origin: 0 0;
transform: translateX(100%);
}
100% {
opacity: 1;
transform-origin: 0 0;
transform: translateX(0%);
}
}
@keyframes moveRightOut {
0% {
transform-origin: 0 0;
transform: translateX(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateX(100%);
opacity: 0;
}
}
@keyframes moveUpIn {
0% {
transform-origin: 0 0;
transform: translateY(-100%);
opacity: 0;
}
100% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
}
@keyframes moveUpOut {
0% {
transform-origin: 0 0;
transform: translateY(0%);
opacity: 1;
}
100% {
transform-origin: 0 0;
transform: translateY(-100%);
opacity: 0;
}
}

View File

@ -0,0 +1,10 @@
@keyframes loadingCircle {
0% {
transform-origin: 50% 50%;
transform: rotate(0deg);
}
100% {
transform-origin: 50% 50%;
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,119 @@
.slide-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter {
opacity: 0;
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1);
}
.@{className}-leave {
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
}
}
.slide-motion(slide-up, slideUp);
.slide-motion(slide-down, slideDown);
.slide-motion(slide-left, slideLeft);
.slide-motion(slide-right, slideRight);
@keyframes slideUpIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
}
@keyframes slideUpOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
}
@keyframes slideDownIn {
0% {
opacity: 0;
transform-origin: 100% 100%;
transform: scaleY(0);
}
100% {
opacity: 1;
transform-origin: 100% 100%;
transform: scaleY(1);
}
}
@keyframes slideDownOut {
0% {
opacity: 1;
transform-origin: 100% 100%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 100% 100%;
transform: scaleY(0);
}
}
@keyframes slideLeftIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleX(0);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleX(1);
}
}
@keyframes slideLeftOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleX(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleX(0);
}
}
@keyframes slideRightIn {
0% {
opacity: 0;
transform-origin: 100% 0%;
transform: scaleX(0);
}
100% {
opacity: 1;
transform-origin: 100% 0%;
transform: scaleX(1);
}
}
@keyframes slideRightOut {
0% {
opacity: 1;
transform-origin: 100% 0%;
transform: scaleX(1);
}
100% {
opacity: 0;
transform-origin: 100% 0%;
transform: scaleX(0);
}
}

View File

@ -0,0 +1,30 @@
.swing-motion(@className, @keyframeName) {
.@{className}-enter {
.motion-common();
animation-play-state: paused;
}
.@{className}-enter.@{className}-enter-active {
animation-name: ~"@{keyframeName}In";
animation-play-state: running;
}
}
.swing-motion(swing, swing);
@keyframes swingIn {
0%, 100% {
transform: translateX(0px);
}
20% {
transform: translateX(-10px);
}
40% {
transform: translateX(10px);
}
60% {
transform: translateX(-5px);
}
80% {
transform: translateX(5px);
}
}

146
style/core/motion/zoom.less Normal file
View File

@ -0,0 +1,146 @@
.zoom-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter {
opacity: 0;
animation-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
.@{className}-leave {
animation-timing-function: cubic-bezier(0.6, -0.3, 0.74, 0.05);
}
}
.zoom-motion(zoom, zoom);
.zoom-motion(zoom-up, zoomUp);
.zoom-motion(zoom-down, zoomDown);
.zoom-motion(zoom-left, zoomLeft);
.zoom-motion(zoom-right, zoomRight);
@keyframes zoomIn {
0% {
opacity: 0;
transform-origin: 50% 50%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 50% 50%;
transform: scale(1, 1);
}
}
@keyframes zoomOut {
0% {
opacity: 1;
transform-origin: 50% 50%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 50% 50%;
transform: scale(0, 0);
}
}
@keyframes zoomUpIn {
0% {
opacity: 0;
transform-origin: 50% 0%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 50% 0%;
transform: scale(1, 1);
}
}
@keyframes zoomUpOut {
0% {
opacity: 1;
transform-origin: 50% 0%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 50% 0%;
transform: scale(0, 0);
}
}
@keyframes zoomLeftIn {
0% {
opacity: 0;
transform-origin: 0% 50%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 0% 50%;
transform: scale(1, 1);
}
}
@keyframes zoomLeftOut {
0% {
opacity: 1;
transform-origin: 0% 50%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 0% 50%;
transform: scale(0, 0);
}
}
@keyframes zoomRightIn {
0% {
opacity: 0;
transform-origin: 100% 50%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 100% 50%;
transform: scale(1, 1);
}
}
@keyframes zoomRightOut {
0% {
opacity: 1;
transform-origin: 100% 50%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 100% 50%;
transform: scale(0, 0);
}
}
@keyframes zoomDownIn {
0% {
opacity: 0;
transform-origin: 50% 100%;
transform: scale(0, 0);
}
100% {
opacity: 1;
transform-origin: 50% 100%;
transform: scale(1, 1);
}
}
@keyframes zoomDownOut {
0% {
opacity: 1;
transform-origin: 50% 100%;
transform: scale(1, 1);
}
100% {
opacity: 0;
transform-origin: 50% 100%;
transform: scale(0, 0);
}
}

View File

@ -10,11 +10,11 @@
.button-color(@color; @background; @border); .button-color(@color; @background; @border);
&:hover { &:hover {
.opacity(.7); .button-color(lighten(@color, 30%, 'relative'); lighten(@background, 30%, 'relative'); lighten(@border, 30%, 'relative'));
} }
&:active, &:active,
&.active { &.active {
.opacity(.8); .button-color(lighten(@color, 20%, 'relative'); lighten(@background, 20%, 'relative'); lighten(@border, 20%, 'relative'));
} }
&:active, &:active,
&.active { &.active {
@ -28,7 +28,6 @@
&:hover, &:hover,
&:active, &:active,
&.active { &.active {
.opacity(1);
.button-color(@btn-disable-color; @btn-disable-bg; @btn-disable-border); .button-color(@btn-disable-color; @btn-disable-bg; @btn-disable-border);
} }
} }
@ -139,7 +138,7 @@
&:hover, &:hover,
&:active, &:active,
&.active { &.active {
.button-color(@btn-primary-color; @btn-primary-bg; @btn-primary-border); color: @btn-primary-color;
} }
} }
@ -147,10 +146,12 @@
.btn-default() { .btn-default() {
.button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);
&:hover, &:hover {
.button-color(lighten(@primary-color, 30%, 'relative'); @white; lighten(@primary-color, 30%, 'relative'));
}
&:active, &:active,
&.active { &.active {
.button-color(@primary-color; @white; @primary-color); .button-color(lighten(@primary-color, 20%, 'relative'); @white; lighten(@primary-color, 20%, 'relative'));
} }
} }
@ -158,10 +159,12 @@
.btn-ghost() { .btn-ghost() {
.button-variant(@btn-ghost-color, @btn-ghost-bg, @btn-ghost-border); .button-variant(@btn-ghost-color, @btn-ghost-bg, @btn-ghost-border);
&:hover, &:hover {
.button-color(lighten(@primary-color, 30%, 'relative'); @white; lighten(@primary-color, 30%, 'relative'));
}
&:active, &:active,
&.active { &.active {
.button-color(@primary-color; @white; @primary-color); .button-color(lighten(@primary-color, 20%, 'relative'); @white; lighten(@primary-color, 20%, 'relative'));
} }
} }
@ -205,16 +208,24 @@
background-color: @primary-color; background-color: @primary-color;
} }
&:not([disabled]):hover { &:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]).active {
> .@{iconfont-css-prefix} { > .@{iconfont-css-prefix} {
color: @btn-primary-color; color: @btn-primary-color;
} }
} }
&:not([disabled]):hover:before { &:not([disabled]):hover:before,
&:not([disabled]):active:before,
&:not([disabled]).active:before {
.opacity(1); .opacity(1);
.scale(1, 1); .scale(1, 1);
}
&:not([disabled]):active:before,
&:not([disabled]).active:before {
background-color: lighten(@primary-color, 20%, 'relative');
} }
} }

View File

@ -0,0 +1,14 @@
.iconfont-mixin() {
position: relative;
display: inline-block;
font-style: normal;
vertical-align: baseline;
text-align: center;
text-transform: none;
text-rendering: auto;
&:before {
display: block;
font-family: "anticon" !important;
}
}

View File

@ -7,7 +7,7 @@
// ------ Base & Require ------ // ------ Base & Require ------
@body-background : #fff; @body-background : #fff;
@font-family : "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", Arial, sans-serif; @font-family : Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans-serif;
@code-family : "PT Mono", Menlo, "Courier New", monospace; @code-family : "PT Mono", Menlo, "Courier New", monospace;
@text-color : #666; @text-color : #666;
@font-size-base : 12px; @font-size-base : 12px;
@ -72,7 +72,7 @@
@btn-padding-lg : 4px 15px 5px 15px; @btn-padding-lg : 4px 15px 5px 15px;
@btn-border-radius-lg : 16px; @btn-border-radius-lg : 16px;
@btn-padding-sm : 1px 15px; @btn-padding-sm : 1px 7px;
@btn-border-radius-sm : 11px; @btn-border-radius-sm : 11px;
@btn-circle-size : 28px; @btn-circle-size : 28px;