Merge remote-tracking branch 'upstream/0.8.0' into notification

This commit is contained in:
zhujun24 2015-08-10 16:52:43 +08:00
commit b3651a4be4
43 changed files with 1135 additions and 77 deletions

View File

@ -85,7 +85,7 @@ var Affix = React.createClass({
},
render() {
var affix = this.state.affix ? 'affix' : '';
var affix = this.state.affix ? 'ant-affix' : '';
var className = this.props.className;
return (

View File

@ -11,9 +11,9 @@ var Datepicker = antd.Datepicker;
React.render(
<div>
<Datepicker size="lg" />
<Datepicker size="large" />
<Datepicker />
<Datepicker size="sm" />
<Datepicker size="small" />
</div>
, document.getElementById('components-datepicker-demo-size'));
````

View File

@ -64,6 +64,12 @@ export default React.createClass({
showOk={this.props.showTime}
showClear={false}/>
);
var sizeClass = '';
if (this.props.size === 'large') {
sizeClass = ' ant-input-lg';
} else if (this.props.size === 'small') {
sizeClass = ' ant-input-sm';
}
return (
<Datepicker
transitionName={this.props.transitionName}
@ -78,10 +84,11 @@ export default React.createClass({
value={this.state.value}
defaultValue={this.props.defaultValue}
prefixCls="ant-calendar-picker"
style={this.props.style}
onChange={this.handleChange}>
<input
placeholder={this.props.placeholder}
className={'ant-calendar-picker-input ant-input ant-input-' + this.props.size}/>
className={'ant-calendar-picker-input ant-input' + sizeClass}/>
</Datepicker>
);
}

View File

@ -27,12 +27,9 @@
| onSelect | 选择日期的回调 | function | 无 |
| showTime | 显示时间选择条 | boolean | false |
| disabled | 禁用 | bool | false |
| size | 输入框大小,`lg`代表高为32px`sm`代表高为22px默认28px | string | 无 |
| size | 输入框大小,`large`代表高为32px`small`代表高为22px默认28px | string | 无 |
<style>
.code-box-demo .ant-calendar-picker-input {
width: 200px;
}
.code-box-demo .ant-calendar-picker {
margin: 0 12px 12px 0;
}

View File

@ -52,8 +52,12 @@
|参数 |类型 |默认值 |详细 |
|-----------------|-------|-------------|----------------------------------------------------|
|type |string |`right` |执行动画的内置参数 |
|style |string |null |同上, style 的样式动画, `type` 有值,此项无效|
|eStyle |string |null |同上, style 的样式动画, `type` 有值,此项无效|
|direction |string |`enter`|动画进场或出场样式,以 `enter` `leave` 两值|
|duration |number |0.5 |每个动画的时间|
|ease |string|`cubic-bezier(0.165, 0.84, 0.44, 1);`|样式缓动;|
|delay |number |0 |整个区块的延时,以秒为单位|
|upend |boolean|false |是否倒放,从最后一个dom开始往上播放|
|interval |number |0.1 |递增延时值,以秒为单位|
### enter-data
@ -68,9 +72,9 @@
|-----------------|-----------------|----------------|----------------------------------------------------|
|type |string |`right` |内置动画样式:<br/> `alpha` `left` `right` `top` `bottom` `scale` `scaleBig` `scaleX` `scaleY`|
|style |string |null |动画样式,如 `transform: translateX(100px)``type` 有值此项无效|
|direction |string |`enter` |动画进出场方向:`enter` `leave`|
|duration |number |0.5 |动画的时间,以秒为单位|
|ease |string |`cubic-bezier(0.165, 0.84, 0.44, 1)`|样式缓动,只支持 css 样式缓动|
|direction |string |`enter` |动画进出场方向:`enter` `leave`,覆盖标签里的值|
|duration |number |0.5 |动画的时间,以秒为单位,覆盖标签里的值|
|ease |string |`cubic-bezier(0.165, 0.84, 0.44, 1)`|样式缓动,只支持 css 样式缓动,覆盖标签里的值|
|delay |number |0 |动画的延时,依照结构递增以上的 `interval`|
|queueId |number |0 |动画的线程|

View File

@ -36,7 +36,7 @@ React.render(
<div className="ant-form-item">
<label className="col-6">Select 选择器:</label>
<div className="col-14">
<Select value="lucy" style={{width:200}} onChange={handleSelectChange}>
<Select size="large" value="lucy" style={{width:200}} onChange={handleSelectChange}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
<Option value="disabled" disabled>disabled</Option>

View File

@ -41,7 +41,7 @@ React.render(
<div className="ant-form-item">
<label className="col-8" required>InputNumber 数字输入框:</label>
<div className="col-10">
<InputNumber min={1} max={10} defaultValue={3} onChange={onInputNumberChange} style={{width:100}}/>
<InputNumber size="large" min={1} max={10} defaultValue={3} onChange={onInputNumberChange} style={{width:100}}/>
<span className="ant-form-text"> 台机器</span>
</div>
</div>
@ -71,7 +71,7 @@ React.render(
<div className="ant-form-item">
<label for="" className="col-8" required>Select 选择器:</label>
<div className="col-16">
<Select value="lucy" style={{width:200}} onChange={handleSelectChange}>
<Select size="large" value="lucy" style={{width:200}} onChange={handleSelectChange}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
<Option value="disabled" disabled>disabled</Option>

View File

@ -1,6 +1,6 @@
# 不可用
- order: 0
- order: 2
点击按钮切换可用状态。

View File

@ -0,0 +1,29 @@
# 三种大小
- order: 1
三种大小的数字输入框,当 size 分别为 `large``small` 时,输入框高度为 `32px``22px` ,默认高度为 `28px`
---
````jsx
var InputNumber = antd.InputNumber;
function onChange(value) {
console.log('changed', value);
}
React.render(
<div>
<InputNumber size="large" min={1} max={100000} defaultValue={3} onChange={onChange} />
<InputNumber min={1} max={100000} defaultValue={3} onChange={onChange} />
<InputNumber size="small" min={1} max={100000} defaultValue={3} onChange={onChange} />
</div>
, document.getElementById('components-input-number-demo-size'));
````
````css
.ant-input-number{
margin-right: 10px;
}
````

View File

@ -8,6 +8,12 @@ export default React.createClass({
};
},
render() {
return <InputNumber style={{width: 90}} {...this.props} />;
var sizeClass = '';
if (this.props.size === 'large') {
sizeClass = 'ant-input-number-lg';
} else if (this.props.size === 'small') {
sizeClass = 'ant-input-number-sm';
}
return <InputNumber className={sizeClass} style={{width: 90}} {...this.props} />;
}
});

View File

@ -25,3 +25,4 @@
| defaultValue | 初始值 | Number | |
| onChange | 变化回调 | Function | |
| disabled | 禁用 | Boolean | false |
| size | 输入框大小 | String | 无 |

View File

@ -5,9 +5,11 @@
---
为页面和功能提供导航的菜单列表。
## 何时使用
需要多级菜单时
导航菜单是一个网站的灵魂,用户依赖导航在各个页面中进行跳转。一般分为顶部导航和侧边导航,顶部导航提供全局性的类目和功能,侧边导航提供多级结构来收纳和排列网站架构。
```html
<Menu>

View File

@ -13,22 +13,29 @@ export default React.createClass({
transitionName: '',
placement: 'top',
trigger: 'click',
onConfirm: function() {},
onCancel: function() {}
onConfirm: function () {
},
onCancel: function () {
}
};
},
confirm: function() {
confirm: function () {
this.props.onConfirm.call(this);
this.setState({
visible: false
});
},
cancel: function() {
cancel: function () {
this.props.onCancel.call(this);
this.setState({
visible: false
});
},
onVisibleChange(v){
this.setState({
visible: v
});
},
render() {
const overlay = <div>
<div className={prefixCls + '-content'}>
@ -36,6 +43,7 @@ export default React.createClass({
<i className="anticon anticon-exclamation-circle"></i>
{this.props.title}
</p>
<div className={prefixCls + '-buttons'}>
<button onClick={this.cancel} className="ant-btn ant-btn-sm"> </button>
<button onClick={this.confirm} className="ant-btn ant-btn-primary ant-btn-sm"> </button>
@ -52,12 +60,13 @@ export default React.createClass({
return (
<Tooltip placement={this.props.placement}
prefixCls={prefixCls}
renderPopupToBody={false}
transitionName={transitionName}
visible={this.state.visible}
trigger={this.props.trigger}
overlay={overlay}>
prefixCls={prefixCls}
renderPopupToBody={false}
onVisibleChange={this.onVisibleChange}
transitionName={transitionName}
visible={this.state.visible}
trigger={this.props.trigger}
overlay={overlay}>
{this.props.children}
</Tooltip>
);

View File

@ -0,0 +1,45 @@
# 三种大小
- order: 0
三种大小的选择框,当 size 分别为 `large``small` 时,输入框高度为 `32px``22px` ,默认高度为 `28px`
---
````jsx
var Select = antd.Select;
var Option = Select.Option;
function handleChange(value) {
console.log('selected ' + value);
}
React.render(
<div>
<Select size="large" value="lucy" style={{width:200}} onChange={handleChange}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="disabled" disabled>Disabled</Option>
<Option value="yiminghe">yiminghe</Option>
</Select>
<Select value="lucy" style={{width:200}} onChange={handleChange}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="disabled" disabled>Disabled</Option>
<Option value="yiminghe">yiminghe</Option>
</Select>
<Select size="small" value="lucy" style={{width:200}} onChange={handleChange}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="disabled" disabled>Disabled</Option>
<Option value="yiminghe">yiminghe</Option>
</Select>
</div>
, document.getElementById('components-select-demo-size'));
````
````css
.ant-select{
margin: 0 10px 10px 0;
}
````

View File

@ -11,8 +11,14 @@ var AntSelect = React.createClass({
};
},
render() {
var sizeClass = '';
if (this.props.size === 'large') {
sizeClass = 'ant-select-lg';
} else if (this.props.size === 'small') {
sizeClass = 'ant-select-sm';
}
return (
<Select {...this.props} />
<Select className={sizeClass} {...this.props} />
);
}
});

View File

@ -36,6 +36,7 @@
| placeholder | 选择框默认文字 | string | 无 |
| searchPlaceholder | 搜索框默认文字 | string | 无 |
| combobox | 输入框自动提示模式 | | false |
| size | 选择框大小 | String | 无 |
### Option props

View File

@ -6,7 +6,7 @@
---
开关选择器
开关选择器
## 何时使用

View File

@ -30,10 +30,6 @@ var columns = [{
dataIndex: 'address'
}];
function resolve(result) {
return result.data;
}
var dataSource = new Table.DataSource({
url: "/components/table/demo/data.json",
resolve: function(result) {
@ -56,7 +52,7 @@ var dataSource = new Table.DataSource({
sortField: sorter.field,
sortOrder: sorter.order
};
for (let key in filters) {
for (var key in filters) {
params[key] = filters[key];
}
console.log('请求参数:', params);
@ -64,14 +60,26 @@ var dataSource = new Table.DataSource({
}
});
function fetch() {
dataSource.fetch().then(function() {
console.log('fetch done');
});
}
var Test=React.createClass({
getInitialState() {
return {
dataSource: dataSource
};
},
refresh() {
this.setState({
dataSource: this.state.dataSource.clone()
});
},
render() {
return <div>
<Table columns={columns} dataSource={this.state.dataSource} />
<button className="ant-btn ant-btn-primary" onClick={this.refresh}>
外部重新加载数据
</button>
</div>;
}
});
React.render(<div>
<Table columns={columns} dataSource={dataSource} />
<button className="ant-btn ant-btn-primary" onClick={fetch}>外部重新加载数据</button>
</div>, document.getElementById('components-table-demo-ajax'));
React.render(<Test />, document.getElementById('components-table-demo-ajax'));
````

View File

@ -16,13 +16,25 @@ function defaultResolve(data) {
}
class DataSource {
constructor(config) {
init(config) {
this.config = config;
this.url = config.url || '';
this.resolve = config.resolve || defaultResolve;
this.getParams = config.getParams || noop;
this.getPagination = config.getPagination || noop;
this.headers = config.headers || {};
this.fetch = noop;
}
constructor(config) {
if (config) {
this.init(config);
}
}
clone() {
var d = new DataSource();
d.init(this.config);
return d;
}
}
@ -90,9 +102,7 @@ var AntTable = React.createClass({
},
getRemoteDataSource() {
let dataSource = this.props.dataSource;
dataSource.fetch = this.fetch;
return dataSource;
return this.props.dataSource;
},
toggleSortOrder(order, column) {

View File

@ -1,14 +1,13 @@
import React from 'react';
import Tree from 'rc-tree';
var TreeNode = Tree.TreeNode;
var antDTree = React.createClass({
var AntTree = React.createClass({
render() {
return <Tree {...this.props} >
{this.props.children}
</Tree>;
}
});
antDTree.TreeNode = TreeNode;
module.exports = antDTree;
AntTree.TreeNode = Tree.TreeNode;
export default AntTree;

View File

@ -0,0 +1,30 @@
# 点击上传
- order: 1
经典款式,用户点击按钮弹出文件选择框。
---
````jsx
var Upload = antd.Upload;
var props = {
description: '支持扩展名为: .rar .zip ...',
action: '/upload.do',
data: {},
accept: '',
uploadTip: '',
start: function(file){
console.log(file.name)
},
error: function() {},
success: function() {},
progress: function() {}
};
React.render(
<Upload {...props} />,
document.getElementById('components-upload-demo-basic')
);
````

View File

@ -0,0 +1,37 @@
# 拖拽上传
- order: 2
样式简单一些。
---
````jsx
var Dragger = antd.Upload.Dragger;
var props = {
name: 'file',
action: '/upload.do',
data: {},
accept: '',
uploadTip: '',
error: function() {},
success: function() {},
progress: function() {},
start: function() {}
};
React.render(
<Dragger {...props}>
<i className="anticon anticon-plus"></i>
</Dragger>,
document.getElementById('components-upload-demo-drag-simple')
);
````
<style>
#components-upload-demo-drag-simple {
width: 246px;
height: 146px;
}
</style>

View File

@ -0,0 +1,44 @@
# 拖拽上传
- order: 1
可以把文件拖入指定区域,完成上传,同样支持点击上传。
---
````jsx
var Dragger = antd.Upload.Dragger;
var props = {
name: 'file',
action: '/upload.do',
data: {},
accept: 'i',
uploadTip: '',
error: function(err) {
console.log(err)
},
success: function() {},
progress: function() {},
start: function(file){
console.log(file)
}
};
React.render(
<Dragger {...props}>
<p className="ant-upload-drag-icon">
<i className="anticon anticon-inbox"></i>
</p>
<p className="ant-upload-text">点击或将文件拖拽到此区域上传</p>
<p className="ant-upload-hint">支持单个或批量上传,严谨上传公司内部资料及其他违禁文件</p>
</Dragger>,
document.getElementById('components-upload-demo-drag')
);
````
<style>
#components-upload-demo-drag {
height: 300px;
}
</style>

116
components/upload/index.jsx Normal file
View File

@ -0,0 +1,116 @@
import React from 'react';
import Upload from 'rc-upload';
import assign from 'object-assign';
import Message from '../message';
import UploadList from './uploadList';
const prefixCls = 'ant-upload';
let AntUpload = React.createClass({
getInitialState() {
return {
downloadList: []
};
},
handleStart(file) {
var i = this.state.downloadList.length;
var nextDownloadList = this.state.downloadList;
nextDownloadList.push({
id: i,
uid: file.uid || '',
filename: file.name,
status: 'downloading'
});
this.setState({
downloadList: nextDownloadList
});
},
handleSuccess(ret, file) {
var matchWay = file.uid === '' ? 'byName' : 'byUid';
Message.success(file.name + '上传完成');
for (var i = 0; i < this.state.downloadList.length; i++) {
if (matchWay === 'byName') {
if (this.state.downloadList[i].filename === file.name) {
this.state.downloadList[i].status = 'done';
}
} else {
if (this.state.downloadList[i].uid === file.uid) {
this.state.downloadList[i].status = 'done';
}
}
}
this.setState({
downloadList: this.state.downloadList
});
},
handleProgress() {
},
handleError() {
Message.error('上传失败');
},
getDefaultProps() {
return {
type: 'select',
name: '',
multipart: false,
action: '',
data: {},
accept: '',
uploadTip: '',
start: function() {},
error: function() {},
success: function() {},
progress: function() {}
};
},
render() {
var type = this.props.type || 'select';
var props = assign({}, this.props);
props.onStart = (file) => {
this.handleStart(file);
props.start.call(this, file);
};
props.onSuccess = (ret, file) => {
this.handleSuccess(ret, file);
props.success.call(this, ret, file);
};
props.onProgress = (step) => {
this.handleProgress(step);
props.progress.call(this, step);
};
props.onError = (err) => {
this.handleError(err);
props.error.call(this, err);
};
if (type === 'drag') {
return (
<Upload {...props}>
<div className={prefixCls + ' ' + prefixCls + '-drag'}>
<div className={prefixCls + '-drag-container'}>
{this.props.children}
</div>
</div>
</Upload>
);
} else if (type === 'select') {
return (
<div className={prefixCls + ' ' + prefixCls + '-select'}>
<Upload {...props}>
<button className='ant-btn ant-btn-ghost'>
<i className='anticon anticon-upload'></i> 点击上传
</button>
</Upload>
<UploadList items={this.state.downloadList} />
</div>
);
}
}
});
AntUpload.Dragger = React.createClass({
render() {
return <AntUpload {...this.props} type="drag" style={{height: this.props.height}} />;
}
});
export default AntUpload;

View File

@ -9,6 +9,20 @@
## 何时使用
上传是将信息从个人计算机(本地计算机)传递到中央计算机(远程计算机)系统上,让网络上的人都能看到.将制作好的网页、文字、图片、视频通过网页或者上传工具软件发布到互联网上的服务器系统上去,以便让其他人浏览、欣赏。这一过程称为上传。
- 当需要上传一个或一些文件时。
- 当需要展现上传的进度时。
- 当需要使用拖拽交互时。
## API
| 参数 | 说明 | 类型 | 默认值 |
|----------- |--------------------------------------------------------- | ---------- |-------|
| name | 可选参数, 上传的文件 | String | file |
| action | 必选参数, 上传的地址 | String | 无 |
| data | 可选参数, 上传所需参数 | Object | 无 |
| accept | 可选参数, 接受上传的文件类型, 详见input accept Attribute | String | 无 |
| onError | 可选参数, error callback |Function | 无 |
| onSuccess | 可选参数, success callback | Function | 无 |
| onProgress | 可选参数, progress callback, 现代浏览器有效 | Function | 无 |

View File

@ -0,0 +1,54 @@
import React from 'react';
const prefixCls = 'ant-upload';
export default React.createClass({
getDefaultProps() {
return {
items: []
};
},
getInitialState() {
return {
items: this.props.items
};
},
componentWillReceiveProps(nextProps) {
if ('items' in nextProps) {
this.setState({
items: nextProps.items
});
}
},
handleClose(file) {
var matchWay = file.uid === '' ? 'byName' : 'byUid';
let items = this.state.items;
let removeItem = items.filter((item) => {
if (matchWay === 'byName') {
return item.filename === file.filename;
} else {
return item.uid === file.uid;
}
})[0];
if (removeItem) {
items.splice(removeItem, 1);
}
this.setState({
items: items
});
},
render() {
var items = this.state.items;
var downloadItem = (file) => {
var statusIcon = file.status === 'done' ? <i className={'anticon anticon-check ' + prefixCls + '-success-icon'}></i> : <i className='anticon anticon-loading'></i>;
var closeIcon = file.status === 'done' ? <i className='anticon anticon-cross' ref='theCloseBtn' onClick={this.handleClose.bind(this, file)}></i> : '';
return (
<div className={prefixCls + '-list-item'} key={file.id}>
{statusIcon}
<b className={prefixCls + '-item-name'}>{file.filename}</b>
{closeIcon}
</div>
);
};
return <div className={prefixCls + '-list'}>{items.map(downloadItem)}</div>;
}
});

View File

@ -158,7 +158,7 @@ var Form = React.createClass({
<div className="col-12">
<div className={this.renderValidateStyle('email', this.state.isEmailOver)}>
<Validator rules={[{required: true, type:'email', message: '请输入正确的邮箱地址'}]} trigger={this.state.emailValidateMethod}>
<input name="email" className="ant-input" value={formData.email} placeholder="onBlur 与 onChange 相结合" onChange={this.setField.bind('email')} onBlur={this.handleEmailInputBlur} onFocus={this.handleEmailInputFocus} />
<input name="email" className="ant-input" value={formData.email} placeholder="onBlur 与 onChange 相结合" onBlur={this.handleEmailInputBlur} onFocus={this.handleEmailInputFocus} />
</Validator>
{status.email.errors ? <div className="ant-form-explain">{status.email.errors.join(',')}</div> : null}
</div>
@ -170,7 +170,7 @@ var Form = React.createClass({
<div className="col-12">
<div className={this.renderValidateStyle('select', false)}>
<Validator rules={[{required: true, message: '请选择您的国籍'}]}>
<Select style={{width:100 + "%"}} name="select" value={formData.select}>
<Select size="large" placeholder="请选择国家" style={{width:"100%"}} name="select" value={formData.select}>
<Option value="china">中国</Option>
<Option value="use">美国</Option>
<Option value="japan">日本</Option>
@ -180,9 +180,9 @@ var Form = React.createClass({
</Validator>
{status.select.errors ? <div className="ant-form-explain">{status.select.errors.join(',')}</div> : null}
</div>
</div>
</div>
</div>
<div className="ant-form-item ant-form-item-compact">
<label className="col-7" required>性别:</label>
<div className="col-12">

View File

@ -31,6 +31,7 @@ var antd = {
Alert: require('./components/alert'),
Validation: require('./components/validation'),
Tree: require('./components/Tree'),
Upload: require('./components/upload'),
Menu: require('./components/Menu')
};

32
nico.js
View File

@ -1,6 +1,8 @@
var path = require('path');
var package = require('./package');
var webpack = require('webpack');
var inspect = require('util').inspect;
var Busboy = require('busboy');
var webpackMiddleware = require('webpack-dev-middleware');
var webpackConfig = require('./webpack.config');
var webpackCompiler = webpack(webpackConfig);
@ -31,7 +33,35 @@ exports.ignorefilter = function(filepath, subdir) {
}
return true;
};
exports.middlewares = [{
exports.middlewares = [
{
name: 'upload',
filter: /upload\.do?$/,
handle: function(req, res, next) {
if (req.method === 'POST') {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
file.on('data', function(data) {
console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
});
file.on('end', function() {
console.log('File [' + fieldname + '] Finished');
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
//res.writeHead(303, { Connection: 'close', Location: '/' });
res.end('success');
});
req.pipe(busboy);
}
}
},
{
name: 'webpackDevMiddleware',
filter: /\.(js|css)(\.map)?$/,
handle: function(req, res, next) {

View File

@ -32,7 +32,7 @@
],
"license": "MIT",
"dependencies": {
"enter-animation": "~0.1.3",
"enter-animation": "~0.2.5",
"gregorian-calendar": "~3.0.0",
"gregorian-calendar-format": "~3.0.1",
"is-equal-shallow": "~0.1.3",
@ -49,14 +49,15 @@
"rc-pagination": "~1.1.0",
"rc-progress": "~1.0.0",
"rc-radio": "~2.0.0",
"rc-select": "~4.5.1",
"rc-slider": "~1.3.1",
"rc-select": "~4.5.2",
"rc-slider": "~1.4.0",
"rc-steps": "~1.1.4",
"rc-switch": "~1.2.0",
"rc-table": "~3.1.0",
"rc-tabs": "~5.3.2",
"rc-tooltip": "~2.5.0",
"rc-tree": "~0.10.0",
"rc-upload": "~1.2.4-beta2",
"rc-util": "~2.0.3",
"react-slick": "~0.6.4"
},
@ -78,7 +79,8 @@
"nico-jsx": "~0.5.8",
"precommit-hook": "^1.0.7",
"webpack": "^1.10.1",
"webpack-dev-middleware": "^1.2.0"
"webpack-dev-middleware": "^1.2.0",
"busboy": "~0.2.9"
},
"scripts": {
"babel": "babel components --out-dir lib",

View File

@ -8,7 +8,7 @@
<ul class="{%- if category === post.meta.category %}aside-list-show{%- endif %}">
{%- for item in items %}
<li class="{%- if item.title === post.title %}current{%- endif %}">
<a href="{{permalink_url(item)}}">
<a href="{{permalink_url(item)}}" class="{%- if item.meta.disabled %}nav-link-disabled{%- endif %}">
{{item.title}}
<span class="chinese">{{item.meta.chinese}}</span>
</a>

View File

@ -1,6 +0,0 @@
# 色系和交互
- category: 色彩
- order: 0
---

111
spec/colors.md Normal file
View File

@ -0,0 +1,111 @@
# 色彩
- category: 色彩
- order: 0
- disabled: true
---
## 有意义的颜色
色彩在界面设计中的使用应同时具备品牌识别性以及界面设计功能性。众所周知色彩是相当感性的东西,设计中对色彩的运用首要应考虑到品牌层面的表达,另外很重要的一点是色彩的运用应达到信息传递,动作指引,交互反馈,或是强化和凸现某一个元素的目的。任何颜色的选取和使用应该是有意义的。
## 色板
Ant Design 的色板由 16 种基本色彩以及通过黑白叠加的方式扩展的色板组成。
### 主色
<script src="https://t.alipayobjects.com/images/T12b4hXcdhXXXXXXXX.js"></script>
<span class="donut" data-peity='{ "fill": ["#ED1C1C", "#E75B10", "#FF6600", "#FDBF06", "#F1E60E", "#96DA19", "#31C009", "#06D9CF", "#0EC4DF", "#2DB7F5", "#1062CE", "#3344D8", "#582DAA", "#BC1ACD", "#FB1479", "#C21D63"], "innerRadius": 70, "radius": 110 }'>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</span>
<script>$('.donut').peity('donut');</script>
### 扩展色板
Ant Design 提供了16 种主色。每一种颜色都按照添加白色或者黑色 5 的规则,可以延展出 40 种颜色,由于 100% 的白色覆盖90-100% 之间的黑色覆盖在视觉上看不出太多的差别因此每种颜色省略前后4种颜色保留 36 色的衍生色,基本已经可以满足日常系统设计的需求。
<div id="extend-palettes"></div>
### 灰色
灰色是中性化的颜色,通常传递出来的感觉是沉稳,在配色心理学中描述“专业化、系统化”的词条中灰色的使用占了较高的比例。同时灰色也是一种比较百搭的颜色,和很多颜色都可以很好的进行搭配使用。实际设计的过程中,常常用于字体颜色、边界色、阴影色以及界面中大面积背景的底色搭配。
<div id="grey-palette"></div>
## 交互
设计元素本身由于交互行为会引发一系列细微的视觉变化,而元素本身的颜色变化有时也能很好的实现这一目的。在进行这类设计的同时,建议采取在颜色上添加黑色或者白色并按照 nX5% 的规律递增的方式来实现。以下图为例,当鼠标移动到某个特定元素,就视为浮起,对应颜色就相应增加白色叠加,相反点击的行为可以理解为按下去,在颜色上就相应的增加黑色的叠加。
<img src="https://t.alipayobjects.com/images/T1fZJhXahgXXXXXXXX.png" width="100%">
<img src="https://t.alipayobjects.com/images/T1ZHxhXdNmXXXXXXXX.png" width="100%">
<style>
.color-palette {
margin: 32px 0;
overflow: hidden;
width: 800px;
}
.color-palette div {
float: left;
width: 33px;
height: 33px;
border-radius: 4px;
margin-right: 3px;
margin-bottom: 3px;
}
.color-palette .main-color {
width: 70px;
height: 70px;
line-height: 70px;
text-align: center;
color: #fff;
font-size: 12px;
}
</style>
<script src="https://t.alipayobjects.com/images/T1DrxhXe0mXXXXXXXX.js"></script>
`````jsx
let Palette = React.createClass({
render() {
let color = this.props.color;
let values = new Values(color).all(5);
let extendTintColors = values.map((value, i) => {
if (i >= (values.length-1)/2) {
return null;
}
return <div style={{backgroundColor: '#' + value.hex}}></div>;
}).reverse();
let extendShadeColors = values.map((value, i) => {
if (i <= (values.length-1)/2 || i >= values.length-3) {
return null;
}
return <div style={{backgroundColor: '#' + value.hex}}></div>;
});
return <div className="color-palette">
<div className="main-color" style={{backgroundColor: color}}>{color}</div>
{extendTintColors}
{extendShadeColors}
</div>;
}
});
let ExtendPalettes = React.createClass({
render() {
var colors = ["#ED1C1C", "#E75B10", "#FF6600", "#FDBF06", "#F1E60E", "#96DA19", "#31C009", "#06D9CF", "#0EC4DF", "#2DB7F5", "#1062CE", "#3344D8", "#582DAA", "#BC1ACD", "#FB1479", "#C21D63"];
return <div>
{colors.map((color) => {
return <Palette color={color} />;
})}
</div>;
}
});
let GreyPalette = React.createClass({
render() {
var colors = ["#ED1C1C", "#E75B10", "#FF6600", "#FDBF06", "#F1E60E", "#96DA19", "#31C009", "#06D9CF", "#0EC4DF", "#2DB7F5", "#1062CE", "#3344D8", "#582DAA", "#BC1ACD", "#FB1479", "#C21D63"];
return <Palette color="#808080" />;
}
});
React.render(<GreyPalette />, document.getElementById('grey-palette'));
React.render(<ExtendPalettes />, document.getElementById('extend-palettes'));
`````

View File

@ -5,3 +5,199 @@
---
跨平台的字体设定,力求在各个操作系统下都有最佳展示效果。
## 字体家族
- 中文字体族:
<img src="https://t.alipayobjects.com/images/T1NrdhXghnXXXXXXXX.png" width="100%">
- 英文文字体族:
<img src="https://t.alipayobjects.com/images/T1bcXhXfNeXXXXXXXX.png" width="100%">
字体家族 css 代码如下:
```css
font-family: "Helvetica Neue",Helvetica,"Hiragino Sans GB","STHeitiSC-Light","Microsoft YaHei","微软雅黑",Arial,sans-serif;
```
代码字体:
```css
font-family: "PT Mono",Menlo,Consolas,"Courier New",monospace;
```
## 字体使用规范
<div class="row">
<div class="col col-12">
<div class="font-type head-1">
<div class="font-title">主标题</div>
<h1 class="font-text">
<span>我是标题</span>
<span>加粗</span>
<span>#666</span>
<span>16px</span>
</h1>
</div>
<div class="font-type head-2">
<div class="font-title">次级标题</div>
<h2 class="font-text">
<span>我是标题</span>
<span>加粗</span>
<span>#666</span>
<span>14px</span>
</h2>
</div>
<div class="font-type head-3">
<div class="font-title">小标题</div>
<h3 class="font-text">
<span>我是标题</span>
<span>加粗</span>
<span>#666</span>
<span>12px</span>
</h3>
</div>
<div class="font-type text">
<div class="font-title">正文</div>
<p class="font-text">
<span>我是正文</span>
<span>#666</span>
<span>12px</span>
</p>
</div>
<div class="font-type help-text">
<div class="font-title">辅助文字</div>
<p class="font-text">
<span>我是辅助文字</span>
<span>#999</span>
<span>12px</span>
</p>
</div>
<div class="font-type disabled-text">
<div class="font-title">失效文字</div>
<p class="font-text">
<span>我是失效文字</span>
<span>#ccc</span>
<span>12px</span>
</p>
</div>
<div class="font-type link-text">
<div class="font-title">链接文字</div>
<p class="font-text">
<a href="#">
<span>我是链接文字</span>
<span>#2db7f5</span>
<span>12px</span>
</a>
</p>
</div>
</div>
<div class="col col-12">
<div class="font-type head-1">
<div class="font-title">Main Head</div>
<h1 class="font-text">
<span>I am example text</span>
<span>bold</span>
<span>#666</span>
<span>16px</span>
</h1>
</div>
<div class="font-type head-2">
<div class="font-title">Sub Head</div>
<h2 class="font-text">
<span>I am example text</span>
<span>bold</span>
<span>#666</span>
<span>14px</span>
</h2>
</div>
<div class="font-type head-3">
<div class="font-title">Small Head</div>
<h3 class="font-text">
<span>I am example text</span>
<span>bold</span>
<span>#666</span>
<span>12px</span>
</h3>
</div>
<div class="font-type text">
<div class="font-title">Text</div>
<p class="font-text">
<span>I am example text</span>
<span>#666</span>
<span>12px</span>
</p>
</div>
<div class="font-type help-text">
<div class="font-title">Help Text</div>
<p class="font-text">
<span>I am example text</span>
<span>#999</span>
<span>12px</span>
</p>
</div>
<div class="font-type disabled-text">
<div class="font-title">Disabled Text</div>
<p class="font-text">
<span>I am example text</span>
<span>#ccc</span>
<span>12px</span>
</p>
</div>
<div class="font-type link-text">
<div class="font-title">Link Text</div>
<p class="font-text">
<a href="#">
<span>I am example text</span>
<span>#2db7f5</span>
<span>12px</span>
</a>
</p>
</div>
</div>
</div>
<style>
.font-type {
margin: 20px 0;
overflow: hidden;
font-size: 12px;
}
.font-type h1,
.font-type h2,
.font-type h3,
.font-type p {
margin: 0;
color: #666;
}
.font-type > * {
display: inline-block;
}
.font-title {
font-size: 14px;
width: 100px;
text-align: right;
margin-right: 30px;
}
.font-text {
width: 300px;
}
.font-text span {
margin-right: 8px;
}
.head-1 h1 {
font-size: 16px;
}
.head-2 h2 {
font-size: 14px;
}
.head-3 h3 {
font-size: 12px;
}
.disabled-text .font-text {
color: #ccc;
}
</style>

View File

@ -4,3 +4,114 @@
- order: 1
---
良好的排版规范能大大提升用户的视觉体验。
## 行高和段落
考虑到阅读的舒适度和节奏感句子和段落间需要合适的间距。行距決定了段落中各行文字的垂直距离通过字体本身行高来控制我们行高默认为字号的1.5倍。段落间距決定了段落上下的间距,一般采用直接空一行来解决。
<div class="row">
<div class="col col-12 paragraph-12px">
<h3>12px 段落</h3>
<p>汉学家称这个空白字为「盘古之白」,因为它劈开了全角字和半角字之间的混沌。</p>
<p>另有有研究显示打字的时候不喜欢在中文和英文之间加空格的人感情路都走得很辛苦有七成的比例会在34 岁的时候跟自己不爱的人结婚,而其余三成的人最后只能把遗产留给自己的猫。毕竟爱情跟书写都需要适时地留白。</p>
</div>
<div class="col col-12 paragraph-14px">
<h3>14px 段落</h3>
<p>汉学家称这个空白字为「盘古之白」,因为它劈开了全角字和半角字之间的混沌。</p>
<p>另有有研究显示打字的时候不喜欢在中文和英文之间加空格的人感情路都走得很辛苦有七成的比例会在34 岁的时候跟自己不爱的人结婚,而其余三成的人最后只能把遗产留给自己的猫。毕竟爱情跟书写都需要适时地留白。</p>
</div>
</div>
<style>
.paragraph-14px, .paragraph-12px {
padding: 15px;
line-height: 1.5;
}
.paragraph-14px p,
.paragraph-12px p {
margin: 1em 0;
}
.paragraph-14px {
font-size: 14px;
}
.paragraph-12px {
font-size: 12px;
}
</style>
## 标点和空格
<img align="right" src="https://t.alipayobjects.com/images/T1KrXhXlxnXXXXXXXX.png" width="200">
1. 使用全角中文标点。
2. 遇到完整的英文整句、特殊名词,其内容使用半角标点。
3. 数字使用半角字符。
4. 不重复使用标点符号。
### 空格规范
1. 中文和英文间需要空格。
2. 数字与单位之间需要增加空格。
例外:度、百分比与数字之间不需要增加空格。
3. 中文链接之间增加空格。
## 文字背景
当文字和背景明暗对比小于一定比值时,人眼识别文字信息将会变得吃力,尤其在明亮的室外或晃动的情况下。
方法:若彩色背景,可先将色彩去色转为黑白,分别吸取并查看背景和文字的 `HSV` 色值。
两者的 V 值的差额便是明暗对比差。这个明暗对比差建议不小于 40。
<img src="https://t.alipayobjects.com/images/T1UYphXe8lXXXXXXXX.png" width="100%">
## 对齐
### 中文/英文居左对齐
中文和英文均采用左对齐的方式,是因为文字的阅读顺序一般是从左到右的。
<img src="https://t.alipayobjects.com/images/T1nHhhXl4mXXXXXXXX.png" width="100%">
### 数字/小数点对齐
<img align="right" src="https://t.alipayobjects.com/images/T1YbthXhRkXXXXXXXX.png" width="400">
<p style="height:220px;width:380px;">数字通常采用右对齐或小数点对齐,这样便于对个十百千位上的数字进行对比。</p>
### 冒号对齐
<img align="right" src="https://t.alipayobjects.com/images/T1hcJhXnlXXXXXXXXX.png" width="400">
<p style="height:220px;width:380px;">以冒号对齐的方式在form表单中尤其常见。主要是为了区分标题和内容区块除了美观简洁外让用户能迅速看清标题减少出错概率。</p>
## 文案长度
语言通常是越简单越明确,而提示性文字更需要简明扼要,让用户一目了然,减少操作失误。提示性句子长度是业务而定,建议一般不超过 1618 个字。
<img align="right" style="margin:30px 100px" src="https://t.alipayobjects.com/images/T17cthXgpbXXXXXXXX.png" width="300">
保持简明准确的方法:
- 每个句子只包含一个观点;
- 使用明确的词;
- 尽可能使用主动语态少用被动语态;
## 层级引导
我们通常使用对比的手法来区分出信息的层次感,信息主次分明能准确地将信息清晰地传达给用户,让用户第一眼获取所需资讯,提升阅读体验。
<img src="https://t.alipayobjects.com/images/T1GYBhXghjXXXXXXXX.png" width="600">
### Squint test
我们可以采用 [模糊测试](https://chrome.google.com/webstore/detail/the-squint-test/gppnipfbappicilfniaimcnagbpfflpg) 的方法,即眯起眼睛从整体来检视结构上的合理与否。
<img src="https://t.alipayobjects.com/images/T1bY4hXkpfXXXXXXXX.png" width="600">

View File

@ -225,7 +225,7 @@ a.logo {
display: block;
}
.nav ul li a.disabled {
a.nav-link-disabled {
cursor: not-allowed;
color: #ddd !important;
pointer-events: none;

View File

@ -0,0 +1,3 @@
.ant-affix {
position: fixed;
}

View File

@ -29,4 +29,6 @@
@import "tree";
@import "carousel/slick";
@import "carousel/slick-theme";
@import "upload";
@import "menu";
@import "affix";

View File

@ -75,6 +75,60 @@
.disabled();
}
}
&-lg {
padding: 0;
.ant-input-number-handler-wrap {
height: 32px;
}
.ant-input-number-input-wrap {
height: 32px;
}
.ant-input-number-handler {
height: 16px;
}
input {
height: 32px;
line-height: 32px;
font-size: 14px;
}
.ant-input-number-handler-up-inner {
top: 2px;
}
.ant-input-number-handler-down-inner {
top: 18px;
}
}
&-sm {
padding: 0;
.ant-input-number-handler-wrap {
height: 22px;
}
.ant-input-number-input-wrap {
height: 22px;
overflow: hidden;
position: relative;
}
.ant-input-number-handler {
height: 11px;
}
input {
height: 22px;
line-height: 22px;
position: absolute;
top: 0;
}
.ant-input-number-handler-up-inner {
top: -1px;
}
.ant-input-number-handler-down-inner {
top: 10px;
}
}
&-handler-wrap {
float: right;
@ -109,7 +163,7 @@
.handler-disabled() {
opacity: 0.72;
color: #ccc!important;
color: #ccc !important;
cursor: default;
&:hover {
color: #ccc;

View File

@ -7,6 +7,7 @@
float: right;
font-weight: bold;
}
.selected_icon() {
position: relative;
&:after {
@ -114,6 +115,59 @@
.@{selectPrefixCls}-selection__clear {
.selection__clear();
}
.@{selectPrefixCls}-selection__placeholder {
color: #ccc;
}
}
&-lg {
.ant-select-selection--single {
height: 32px;
.ant-select-selection__rendered {
line-height: 30px;
font-size: 14px;
}
}
.ant-select-selection--multiple {
min-height: 32px;
.ant-select-selection__rendered {
li {
height: 24px;
.ant-select-selection__choice__content {
font-size: 14px;
line-height: 24px;
}
}
}
}
}
&-sm {
.ant-select-selection--single {
height: 22px;
.ant-select-selection__rendered {
line-height: 20px;
}
}
.ant-select-selection--multiple {
min-height: 22px;
.ant-select-selection__rendered {
li {
height: 14px;
.ant-select-selection__choice__content {
line-height: 14px;
position: relative;
top: -3px;
}
.ant-select-selection__choice__remove {
position: relative;
top: -4px;
}
}
}
}
}
&-disabled &-selection__choice__remove {

View File

@ -133,7 +133,7 @@
display: none;
}
&-placement-top {
&-placement-points-bc-tc {
padding: @slider-tooltip-arrow-width 0 @slider-tooltip-distance 0;
}
@ -158,7 +158,7 @@
border-style: solid;
}
&-placement-top &-arrow {
&-placement-points-bc-tc &-arrow {
bottom: @slider-tooltip-distance - @slider-tooltip-arrow-width;
left: 50%;
margin-left: -@slider-tooltip-arrow-width;

View File

@ -0,0 +1,84 @@
@prefixUploadClass: ant-upload;
.@{prefixUploadClass} {
&.@{prefixUploadClass}-drag {
border: 1px dashed #d9d9d9;
transition: all 0.3s ease;
cursor: pointer;
border-radius: @border-radius-base;
text-align: center;
width: 100%;
height: 100%;
position: relative;
.@{prefixUploadClass}-drag-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
}
&:hover {
border: 1px dashed #999;
}
p.@{prefixUploadClass}-drag-icon {
.anticon {
font-size: 80px;
margin-top: -30px;
color: tint(@primary-color, 20%);
}
height: 60px;
margin-bottom: 24px;
}
p.@{prefixUploadClass}-text {
font-size: 14px;
}
p.@{prefixUploadClass}-hint {
font-size: 12px;
color: #999;
}
.anticon-plus {
font-size: 30px;
transition: all 0.3s ease;
color: #d9d9d9;
&:hover {
color: #999;
}
}
&:hover .anticon-plus {
color: #999;
}
}
}
.@{prefixUploadClass}-list {
margin-left: 4px;
margin-top: 8px;
.@{prefixUploadClass}-list-item {
margin-bottom: 4px;
height: 22px;
overflow: hidden;
.anticon {
margin-top: -2px;
.iconfont-size-under-12px(10px);
&.anticon-cross {
cursor: pointer;
color: #999;
&:hover {
color: #666;
}
}
}
}
.@{prefixUploadClass}-item-name {
font-size: 12px;
color: #666;
margin-left: 4px;
margin-right: 8px;
font-weight: normal;
}
.@{prefixUploadClass}-success-icon {
color: @success-color;
font-weight: bold;
}
}

View File

@ -98,6 +98,3 @@ a {
.invisible {
visibility: hidden;
}
.affix {
position: fixed;
}