diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f9760a3504..fedbdf9311 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,6 @@ First of all, thanks for your contribution! :-) Please makes sure these boxes are checked before submitting your PR, thank you! -[ ] Run `npm run lint` and fix those errors before submitting in order to keep consistent code style. -[ ] Rebase before creating a PR to keep commit history clear. -[ ] Add some descriptions and refer relative issues for you PR. +* [ ] Run `npm run lint` and fix those errors before submitting in order to keep consistent code style. +* [ ] Rebase before creating a PR to keep commit history clear. +* [ ] Add some descriptions and refer relative issues for you PR. diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f5627d1b4..36c292e7ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,46 @@ --- +## 0.12.11 + +`2016-03-16` + +- 全新的设计文档 `语言` 部分。 +- 修复 Popconfirm `onConfirm` 和 `onCancel` 时没有触发 `onVisibleChange` 的问题。 +- TreeSelect 组件补充 `showCheckedStrategy` 属性,支持回填数据的不同展示方式。 +- 补充 Modal `align` 属性的文档。 +- 修复 Menu 弹出菜单 `z-index` 丢失的问题。 +- Progress 的默认颜色固定,不再随着主色变化。 +- 优化 Button 点击动画在 Chrome 下的效果。 +- 修复一个 Affix 的 `z-index` 太低的问题。 +- 修复 Table 树形数据的二级节点列前无法选择的问题。[#1212](https://github.com/ant-design/ant-design/issues/1212) +- 修复 Table 修改 `pageSize` 没有触发 `onChange` 的问题。[#1206](https://github.com/ant-design/ant-design/issues/1206) +- 修复 Table 指定 `rowKey` 时导致 `rowSelection.onChange` 的 `selectedRows` 参数为空的问题。 + +## 0.12.10 + +- 修复 0.12.9 版本 npm 包打包错误的问题。 + +## 0.12.9 + +`2016-03-11` + +- Transfer + - 可以定义 `notFoundContent `。 + - 修复 `searchPlaceholder` 使用了 `placeholder` 的值的问题。 +- 修复 Popconfirm、Popover、Tooltip 的箭头位置未指向元素的问题。 +- 修正 Badge 在搜狗等旧版 webkit 浏览器下无法使用的问题。 +- 调整 Tabs 样式。 +- 修复 Table 中的 Pagination 默认配置问题。 +- 调整 Form.Item 在 inline 模式下的 `margin-bottom`。[#1141](https://github.com/ant-design/ant-design/issues/1141) +- 修复 DatePicker `style` 设置错误的问题。 +- 优化 Popconfirm、Button 样式。 +- Dropdown 增加默认的 mouseEnterDelay 延迟以优化体验。 +- 修复 Dialog 样式问题。 +- 修复 Upload 上传中的状态问题。[#1159](https://github.com/ant-design/ant-design/issues/1159) +- 优化 Menu、Tabs 在 Chorme 下的渲染问题。 +- Form 默认阻止 submit 事件。 + ## 0.12.8 `2016-03-06` diff --git a/LICENSE b/LICENSE index c208f57b6a..12189b627d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT LICENSE -Copyright (c) 2015 Alipay.com, https://www.alipay.com/ +Copyright (c) 2015-present Alipay.com, https://www.alipay.com/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/components/alert/index.jsx b/components/alert/index.jsx index 566718731e..ed3637d1e8 100644 --- a/components/alert/index.jsx +++ b/components/alert/index.jsx @@ -9,7 +9,8 @@ export default React.createClass({ return { prefixCls: 'ant-alert', showIcon: false, - onClose() {} + onClose() {}, + type: 'info', }; }, getInitialState() { diff --git a/components/alert/index.md b/components/alert/index.md index 3ea71340a7..ba0e1b9c22 100644 --- a/components/alert/index.md +++ b/components/alert/index.md @@ -17,7 +17,7 @@ | 参数 | 说明 | 类型 | 默认值 | |----------- |--------------------------------------------------------- | ---------- |-------| -| type | 必选参数,指定警告提示的样式,有四种选择`success`、`info`、`warn`、`error` | String | 无 | +| type | 必选参数,指定警告提示的样式,有四种选择`success`、`info`、`warn`、`error` | String | `info` | | closable | 可选参数,默认不显示关闭按钮 | Boolean | 无 | | closeText | 可选参数,自定义关闭按钮 | React.Node | 无 | | message | 必选参数,警告提示内容 | React.Node | 无 | diff --git a/components/badge/ScrollNumber.jsx b/components/badge/ScrollNumber.jsx index 9b91e788a3..27a2fd19d5 100644 --- a/components/badge/ScrollNumber.jsx +++ b/components/badge/ScrollNumber.jsx @@ -76,6 +76,7 @@ class AntScrollNumber extends React.Component { className: `${this.props.prefixCls}-only`, style: { transition: removeTransition && 'none', + WebkitTransform: `translate3d(0, ${-position * height}px, 0)`, transform: `translate3d(0, ${-position * height}px, 0)`, height, }, diff --git a/components/button/button-group.jsx b/components/button/button-group.jsx index 46829114f3..e166885054 100644 --- a/components/button/button-group.jsx +++ b/components/button/button-group.jsx @@ -24,5 +24,5 @@ export default class ButtonGroup extends React.Component { } } ButtonGroup.propTypes = { - size: React.PropTypes.string, + size: React.PropTypes.oneOf(['large', 'small']), }; diff --git a/components/button/button.jsx b/components/button/button.jsx index f139d96059..73e82e2f3e 100644 --- a/components/button/button.jsx +++ b/components/button/button.jsx @@ -2,7 +2,7 @@ import React from 'react'; import classNames from 'classnames'; import { findDOMNode } from 'react-dom'; -const rxTwoCNChar = /^[\u4e00-\u9fa5]{2,2}$/; +const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/; const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar); function isString(str) { return typeof str === 'string'; @@ -73,10 +73,10 @@ export default class Button extends React.Component { } Button.propTypes = { - type: React.PropTypes.string, - shape: React.PropTypes.string, - size: React.PropTypes.string, - htmlType: React.PropTypes.string, + type: React.PropTypes.oneOf(['primary', 'ghost', 'dashed']), + shape: React.PropTypes.oneOf(['circle', 'circle-outline']), + size: React.PropTypes.oneOf(['large', 'small']), + htmlType: React.PropTypes.oneOf(['submit', 'button', 'reset']), onClick: React.PropTypes.func, loading: React.PropTypes.bool, className: React.PropTypes.string, diff --git a/components/button/demo/basic.md b/components/button/demo/basic.md index c4d69feb75..5f52387050 100644 --- a/components/button/demo/basic.md +++ b/components/button/demo/basic.md @@ -6,7 +6,7 @@ 通过设置 `type` 为 `primary` `ghost` 可分别创建主按钮、幽灵按钮,若不设置 `type` 值则为次按钮。不同的样式可以用来区别其重要程度。 -主按钮和次按钮可独立使用,需要强引导用主按钮。幽灵按钮用于和主按钮组合。 +主按钮和次按钮可独立使用,需要强引导用主按钮。幽灵按钮用于和主按钮组合。主按钮在同一个操作区域最多出现一次。 --- diff --git a/components/cascader/index.md b/components/cascader/index.md index 3d5462ecbc..1857abff10 100644 --- a/components/cascader/index.md +++ b/components/cascader/index.md @@ -36,3 +36,5 @@ | size | 输入框大小,可选 `large` `default` `small` | string | `default` | | disabled | 禁用 | boolean | false | | allowClear | 是否支持清除 | boolean | true | +| expandTrigger | 次级菜单的展开方式,可选 'click' 和 'hover' | string | 'click' | +| changeOnSelect | 当此项为 true 时,点选每级菜单选项值都会发生变化,具体见上面的演示 | boolean | false | diff --git a/components/date-picker/index.jsx b/components/date-picker/index.jsx index 85670591ec..b6dd9fb69a 100644 --- a/components/date-picker/index.jsx +++ b/components/date-picker/index.jsx @@ -115,7 +115,7 @@ function createPicker(TheCalendar, defaultFormat) { pickerClass += ' ant-calendar-picker-open'; } return ( - + diff --git a/components/dropdown/dropdown.jsx b/components/dropdown/dropdown.jsx index f767579dfc..01528b4b99 100644 --- a/components/dropdown/dropdown.jsx +++ b/components/dropdown/dropdown.jsx @@ -16,4 +16,6 @@ export default class Dropdown extends React.Component { Dropdown.defaultProps = { transitionName: 'slide-up', prefixCls: 'ant-dropdown', + mouseEnterDelay: 0.15, + mouseLeaveDelay: 0.1, }; diff --git a/components/form/Form.jsx b/components/form/Form.jsx index 34f29cf1ef..c969c560c0 100644 --- a/components/form/Form.jsx +++ b/components/form/Form.jsx @@ -35,6 +35,9 @@ Form.propTypes = { Form.defaultProps = { prefixCls: 'ant-form', + onSubmit(e) { + e.preventDefault(); + }, }; Form.childContextTypes = { diff --git a/components/form/index.md b/components/form/index.md index d680a6de83..7b6bebe9fb 100644 --- a/components/form/index.md +++ b/components/form/index.md @@ -85,6 +85,8 @@ CustomizedForm = Form.create({})(CustomizedForm); #### this.props.form.getFieldProps(id, options) +`getFieldProps` 返回的属性包括 `id`、`value`(或你设置的其它 `valuePropName`)、`ref`、`onChange`(或者你设置的其它 `trigger` `validateTrigger`),所以不应再设置同样的属性,以免冲突。如果对其返回值的细节有兴趣,可以 `console.log` 出来查看。 + | 参数 | 说明 | 类型 | 可选值 |默认值 | |-----------|------------------------------------------|------------|-------|--------| | options.id | 必填输入控件唯一标志 | string | | | diff --git a/components/icon/index.md b/components/icon/index.md index fb063e3705..af01303190 100644 --- a/components/icon/index.md +++ b/components/icon/index.md @@ -30,6 +30,10 @@ ``` +## 本地部署 + +图标组件使用 [iconfont.cn](http://iconfont.cn),默认公网可访问。如需本地部署,可参考 [示例](https://github.com/ant-design/antd-init/tree/master/examples/local-iconfont)。 + ## 图标列表 > 点击图标复制代码。 diff --git a/components/menu/index.md b/components/menu/index.md index 28fa33bfae..5f6e8ea9c0 100644 --- a/components/menu/index.md +++ b/components/menu/index.md @@ -17,9 +17,9 @@ ```html - 菜单项 + 菜单项 - 子菜单项 + 子菜单项 ``` diff --git a/components/modal/Modal.jsx b/components/modal/Modal.jsx index bd2274306b..d869650dce 100644 --- a/components/modal/Modal.jsx +++ b/components/modal/Modal.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { PropTypes } from 'react'; import Dialog from 'rc-dialog'; import { Dom } from 'rc-util'; import Button from '../button'; @@ -8,7 +8,7 @@ function noop() {} let mousePosition; let mousePositionEventBinded; -let AntModal = React.createClass({ +const AntModal = React.createClass({ getDefaultProps() { return { prefixCls: 'ant-modal', @@ -26,6 +26,21 @@ let AntModal = React.createClass({ antLocale: React.PropTypes.object, }, + propTypes: { + prefixCls: PropTypes.string, + onOk: PropTypes.func, + onCancel: PropTypes.func, + okText: PropTypes.node, + cancelText: PropTypes.node, + width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + confirmLoading: PropTypes.bool, + visible: PropTypes.bool, + align: PropTypes.object, + footer: PropTypes.node, + title: PropTypes.node, + closable: PropTypes.bool, + }, + handleCancel(e) { this.props.onCancel(e); }, diff --git a/components/modal/index.md b/components/modal/index.md index c8b39b68d3..875f4e46d5 100644 --- a/components/modal/index.md +++ b/components/modal/index.md @@ -30,7 +30,8 @@ | footer | 底部内容 | React.Element | 确定取消按钮 | | okText | 确认按钮文字 | String | 确定 | | cancelText | 取消按钮文字 | String | 取消 | -| maskClosable | 点击蒙层是否允许关闭 | Boolean | true | +| maskClosable | 点击蒙层是否允许关闭 | Boolean | true | +| align | 浮层自定义位置 | Object, [dom-align](https://github.com/yiminghe/dom-align) | 距离顶部 100px | ### Modal.xxx() diff --git a/components/popconfirm/demo/placement.md b/components/popconfirm/demo/placement.md index 3ce9735121..1f89c8d57e 100644 --- a/components/popconfirm/demo/placement.md +++ b/components/popconfirm/demo/placement.md @@ -2,7 +2,7 @@ - order: 1 -位置有四个方向。 +位置有十二个方向。 --- diff --git a/components/popconfirm/index.jsx b/components/popconfirm/index.jsx index 887ea73d59..c3fcc3baa2 100644 --- a/components/popconfirm/index.jsx +++ b/components/popconfirm/index.jsx @@ -2,7 +2,9 @@ import React from 'react'; import Tooltip from 'rc-tooltip'; import Icon from '../icon'; import Button from '../button'; +import getPlacements from '../popover/placements'; +const placements = getPlacements(); const prefixCls = 'ant-popover'; const noop = function () {}; const transitionNames = { @@ -55,12 +57,12 @@ export default React.createClass({ }, onVisibleChange(visible) { this.setVisible(visible); - this.props.onVisibleChange(visible); }, setVisible(visible) { if (!('visible' in this.props)) { this.setState({ visible }); } + this.props.onVisibleChange(visible); }, render() { const { title, placement, overlayStyle, trigger, ...restProps } = this.props; @@ -71,11 +73,11 @@ export default React.createClass({ } const overlay = (
-
-

+

+
- {title} -

+
{title}
+
@@ -87,7 +89,9 @@ export default React.createClass({ const transitionName = transitionNames[placement]; return ( - @@ -49,7 +52,7 @@ const Popover = React.createClass({ return (
{this.props.title &&
{this.props.title}
} -
+
{this.props.overlay}
diff --git a/components/popover/placements.js b/components/popover/placements.js new file mode 100644 index 0000000000..0b971f160d --- /dev/null +++ b/components/popover/placements.js @@ -0,0 +1,84 @@ +const autoAdjustOverflow = { + adjustX: 1, + adjustY: 1, +}; + +const targetOffset = [0, 0]; + +export default function getPlacements(config = {}) { + const { arrowWidth = 5, horizontalArrowShift = 16, verticalArrowShift = 12 } = config; + return { + left: { + points: ['cr', 'cl'], + overflow: autoAdjustOverflow, + offset: [-4, 0], + targetOffset, + }, + right: { + points: ['cl', 'cr'], + overflow: autoAdjustOverflow, + offset: [4, 0], + targetOffset, + }, + top: { + points: ['bc', 'tc'], + overflow: autoAdjustOverflow, + offset: [0, -4], + targetOffset, + }, + bottom: { + points: ['tc', 'bc'], + overflow: autoAdjustOverflow, + offset: [0, 4], + targetOffset, + }, + topLeft: { + points: ['bl', 'tc'], + overflow: autoAdjustOverflow, + offset: [-(horizontalArrowShift + arrowWidth), -4], + targetOffset, + }, + leftTop: { + points: ['tr', 'cl'], + overflow: autoAdjustOverflow, + offset: [-4, -(verticalArrowShift + arrowWidth)], + targetOffset, + }, + topRight: { + points: ['br', 'tc'], + overflow: autoAdjustOverflow, + offset: [horizontalArrowShift + arrowWidth, -4], + targetOffset, + }, + rightTop: { + points: ['tl', 'cr'], + overflow: autoAdjustOverflow, + offset: [4, -(verticalArrowShift + arrowWidth)], + targetOffset, + }, + bottomRight: { + points: ['tr', 'bc'], + overflow: autoAdjustOverflow, + offset: [horizontalArrowShift + arrowWidth, 4], + targetOffset, + }, + rightBottom: { + points: ['bl', 'cr'], + overflow: autoAdjustOverflow, + offset: [4, verticalArrowShift + arrowWidth], + targetOffset, + }, + bottomLeft: { + points: ['tl', 'bc'], + overflow: autoAdjustOverflow, + offset: [-(horizontalArrowShift + arrowWidth), 4], + targetOffset, + }, + leftBottom: { + points: ['br', 'cl'], + overflow: autoAdjustOverflow, + offset: [-4, verticalArrowShift + arrowWidth], + targetOffset, + }, + }; +} diff --git a/components/slider/index.md b/components/slider/index.md index 15c49e3f72..7a2d7b1657 100644 --- a/components/slider/index.md +++ b/components/slider/index.md @@ -16,15 +16,16 @@ | 参数 | 类型 | 默认值 |说明 | |------------|----------------|-------------|--------------| +| range | Boolean | false | 双滑块模式 | min | Number | 0 | 最小值 | max | Number | 100 | 最大值 | step | Number or null | 1 | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 `null`,此时 Slider 的可选值仅有 marks 标出来的部分。 -| marks | Object {Number: String} | {} | 分段标记,key 的类型必须为 `Number` 且取值在闭区间 [min, max] 内 +| marks | Object {Number: String} | {} | 刻度标记,key 的类型必须为 `Number` 且取值在闭区间 [min, max] 内 +| dots | Boolean | false | 是否只能拖拽到刻度上 | value | Number or [Number, Number]| | 设置当前取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]` | defaultValue | Number or [Number, Number]| 0 or [0, 0] | 设置初始取值。当 `range` 为 `false` 时,使用 `Number`,否则用 `[Number, Number]` | included | Boolean | true | `marks` 不为空对象时有效,值为 true 时表示值为包含关系,false 表示并列 | disabled | Boolean | false | 值为 `true` 时,滑块为禁用状态 -| allowCross | Boolean | true | 当 `range` 为 `true` 时,该属性可以设置是否允许两个滑块交换位置。 | onChange | Function | NOOP | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入。 | onAfterChange | Function | NOOP | 与 `onmouseup` 触发时机一致,把当前值作为参数传入。 | tipFormatter | Function or null | IDENTITY | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null,则隐藏 Tooltip。 diff --git a/components/table/demo/expand-children.md b/components/table/demo/expand-children.md index 7577deb3ab..5dc9c1e529 100644 --- a/components/table/demo/expand-children.md +++ b/components/table/demo/expand-children.md @@ -4,6 +4,8 @@ 表格支持树形数据的展示,可以通过设置 `indentSize` 以控制每一层的缩进宽度。 +> 注:暂不支持父子数据递归关联选择。 + --- ````jsx @@ -77,8 +79,21 @@ const data = [{ address: '我是b', }]; +// 通过 rowSelection 对象表明需要行选择 +const rowSelection = { + onChange(selectedRowKeys, selectedRows) { + console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + }, + onSelect(record, selected, selectedRows) { + console.log(record, selected, selectedRows); + }, + onSelectAll(selected, selectedRows, changeRows) { + console.log(selected, selectedRows, changeRows); + } +}; + ReactDOM.render( - , +
, mountNode ); ```` diff --git a/components/table/demo/row-selection-and-operation.md b/components/table/demo/row-selection-and-operation.md index 5f2244cd90..d303aa96cf 100644 --- a/components/table/demo/row-selection-and-operation.md +++ b/components/table/demo/row-selection-and-operation.md @@ -33,7 +33,7 @@ for (let i = 0; i < 46; i++) { const App = React.createClass({ getInitialState() { return { - selectedRowKeys: [], + selectedRowKeys: [], // 这里配置默认勾选列 loading: false, }; }, diff --git a/components/table/demo/row-selection-props.md b/components/table/demo/row-selection-props.md index ed3af7d2b2..3f52c18deb 100644 --- a/components/table/demo/row-selection-props.md +++ b/components/table/demo/row-selection-props.md @@ -12,9 +12,7 @@ import { Table } from 'antd'; const columns = [{ title: '姓名', dataIndex: 'name', - render(text) { - return {text}; - } + render: text => {text}, }, { title: '年龄', dataIndex: 'age' @@ -43,19 +41,9 @@ const data = [{ const rowSelection = { getCheckboxProps(record) { return { - defaultChecked: record.name === '李大嘴', // 配置默认勾选的列 disabled: record.name === '胡彦祖' // 配置无法勾选的列 }; }, - onChange(selectedRowKeys) { - console.log(`selectedRowKeys changed: ${selectedRowKeys}`); - }, - onSelect(record, selected, selectedRows) { - console.log(record, selected, selectedRows); - }, - onSelectAll(selected, selectedRows) { - console.log(selected, selectedRows); - }, }; ReactDOM.render(
diff --git a/components/table/filterDropdown.jsx b/components/table/filterDropdown.jsx index 97e2921dd7..79671bdaa2 100644 --- a/components/table/filterDropdown.jsx +++ b/components/table/filterDropdown.jsx @@ -96,6 +96,7 @@ let FilterMenu = React.createClass({ let menus = (
this.props.rowSelection.getCheckboxProps(item).defaultChecked) .map((record, rowIndex) => this.getRecordKey(record, rowIndex)); }, @@ -98,7 +99,7 @@ let AntTable = React.createClass({ componentWillReceiveProps(nextProps) { if (('pagination' in nextProps) && nextProps.pagination !== false) { this.setState({ - pagination: objectAssign({}, this.state.pagination, nextProps.pagination) + pagination: objectAssign({}, defaultPagination, this.state.pagination, nextProps.pagination) }); } // dataSource 的变化会清空选中项 @@ -122,8 +123,10 @@ let AntTable = React.createClass({ this.setState({ selectedRowKeys }); } if (this.props.rowSelection && this.props.rowSelection.onChange) { - const data = this.getCurrentPageData(); - const selectedRows = data.filter(row => selectedRowKeys.indexOf(row.key) >= 0); + const data = this.getFlatCurrentPageData(); + const selectedRows = data.filter( + (row, i) => selectedRowKeys.indexOf(this.getRecordKey(row, i)) >= 0 + ); this.props.rowSelection.onChange(selectedRowKeys, selectedRows); } }, @@ -164,9 +167,7 @@ let AntTable = React.createClass({ sorter, }; this.setState(newState); - this.props.onChange.apply(this, this.prepareParamsArguments( - objectAssign({}, this.state, newState) - )); + this.props.onChange(...this.prepareParamsArguments({ ...this.state, ...newState })); }, handleFilter(column, nextFilters) { @@ -186,9 +187,7 @@ let AntTable = React.createClass({ }; this.setState(newState); this.setSelectedRowKeys([]); - this.props.onChange.apply(this, this.prepareParamsArguments( - objectAssign({}, this.state, newState) - )); + this.props.onChange(...this.prepareParamsArguments({ ...this.state, ...newState })); }, handleSelect(record, rowIndex, e) { @@ -208,7 +207,7 @@ let AntTable = React.createClass({ }); this.setSelectedRowKeys(selectedRowKeys); if (this.props.rowSelection.onSelect) { - let data = this.getCurrentPageData(); + let data = this.getFlatCurrentPageData(); let selectedRows = data.filter((row, i) => { return selectedRowKeys.indexOf(this.getRecordKey(row, i)) >= 0; }); @@ -228,7 +227,7 @@ let AntTable = React.createClass({ }); this.setSelectedRowKeys(selectedRowKeys); if (this.props.rowSelection.onSelect) { - let data = this.getCurrentPageData(); + let data = this.getFlatCurrentPageData(); let selectedRows = data.filter((row, i) => { return selectedRowKeys.indexOf(this.getRecordKey(row, i)) >= 0; }); @@ -238,7 +237,7 @@ let AntTable = React.createClass({ handleSelectAllRow(e) { const checked = e.target.checked; - const data = this.getCurrentPageData(); + const data = this.getFlatCurrentPageData(); const defaultSelection = this.state.selectionDirty ? [] : this.getDefaultSelection(); const selectedRowKeys = this.state.selectedRowKeys.concat(defaultSelection); const changableRowKeys = data.filter(item => @@ -290,9 +289,7 @@ let AntTable = React.createClass({ pagination }; this.setState(newState); - this.props.onChange.apply(this, this.prepareParamsArguments( - objectAssign({}, this.state, newState) - )); + this.props.onChange(...this.prepareParamsArguments({ ...this.state, ...newState })); }, onRadioChange(ev) { @@ -350,7 +347,7 @@ let AntTable = React.createClass({ renderRowSelection() { let columns = this.props.columns.concat(); if (this.props.rowSelection) { - let data = this.getCurrentPageData().filter((item) => { + let data = this.getFlatCurrentPageData().filter((item) => { if (this.props.rowSelection.getCheckboxProps) { return !this.props.rowSelection.getCheckboxProps(item).disabled; } @@ -471,11 +468,12 @@ let AntTable = React.createClass({ handleShowSizeChange(current, pageSize) { const pagination = this.state.pagination; pagination.onShowSizeChange(current, pageSize); - - let nextPagination = objectAssign(pagination, { - pageSize, - }); + const nextPagination = { ...pagination, pageSize, current }; this.setState({ pagination: nextPagination }); + this.props.onChange(...this.prepareParamsArguments({ + ...this.state, + pagination: nextPagination, + })); }, renderPagination() { @@ -516,8 +514,8 @@ let AntTable = React.createClass({ return this.props.columns.filter(c => this.getColumnKey(c) === myKey)[0]; }, - getCurrentPageData(dataSource) { - let data = this.getLocalData(dataSource); + getCurrentPageData() { + let data = this.getLocalData(); let current; let pageSize; let state = this.state; @@ -541,9 +539,13 @@ let AntTable = React.createClass({ return data; }, - getLocalData(dataSource) { + getFlatCurrentPageData() { + return flatArray(this.getCurrentPageData()); + }, + + getLocalData() { let state = this.state; - let data = dataSource || this.props.dataSource; + let data = this.props.dataSource || []; // 排序 if (state.sortOrder && state.sorter) { data = data.slice(0); diff --git a/components/table/util.js b/components/table/util.js new file mode 100644 index 0000000000..f2dfcec48a --- /dev/null +++ b/components/table/util.js @@ -0,0 +1,15 @@ +export function flatArray(data = [], childrenName = 'children') { + const result = []; + const loop = (array) => { + array.forEach(item => { + const newItem = { ...item }; + delete newItem[childrenName]; + result.push(newItem); + if (item[childrenName] && item[childrenName].length > 0) { + loop(item[childrenName]); + } + }); + }; + loop(data); + return result; +} diff --git a/components/tabs/index.md b/components/tabs/index.md index 1a0127b9f2..ace73874b0 100644 --- a/components/tabs/index.md +++ b/components/tabs/index.md @@ -30,6 +30,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。 | onTabClick | tab 被点击的回调 | Function | 无 | | tabBarExtraContent | tab bar 上额外的元素 | React Node | 无 | | type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | String | 'line' | +| size | 大小,提供 `default` 和 `small` 两种大小 | String | 'default' | | tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | String | 'top' | | onEdit | 新增和删除页签的回调,在 `type="editable-card"` 时有效 | Function(targetKey, action) | 无 | diff --git a/components/tooltip/index.jsx b/components/tooltip/index.jsx index bb66a0f015..cb0dfb02da 100644 --- a/components/tooltip/index.jsx +++ b/components/tooltip/index.jsx @@ -1,5 +1,10 @@ import React from 'react'; import Tooltip from 'rc-tooltip'; +import getPlacements from '../popover/placements'; + +const placements = getPlacements({ + verticalArrowShift: 8, +}); export default React.createClass({ getDefaultProps() { @@ -42,6 +47,7 @@ export default React.createClass({ return ( 案例(敬请期待) diff --git a/docs/pattern/complex-table.md b/docs/pattern/complex-table.md index 891ac54e73..d2c6235247 100644 --- a/docs/pattern/complex-table.md +++ b/docs/pattern/complex-table.md @@ -3,10 +3,10 @@ - order: 5 - chinese: 表格:复杂数据 ---- - 表格也用于展示复杂和高度结构化数据。 +--- + ## 案例 ### 多列数据 diff --git a/docs/pattern/form.md b/docs/pattern/form.md index 0e9628c606..4809d44758 100644 --- a/docs/pattern/form.md +++ b/docs/pattern/form.md @@ -3,8 +3,6 @@ - order: 2 - chinese: 表单 ---- - 作为获取用户输入的重要交互方式,表单也承担将问题和答案进行配对的角色。 设计者进行表单设计时,应当注意这几点: @@ -23,6 +21,8 @@ 4. 不要提出不必要的问题。 +--- + ## 内容 结构示例 @@ -106,7 +106,7 @@ ### 字数校验框 -字数校验框示例 +字数校验框示例 用于统计当前输入长度,以及是否超过系统阈值。 diff --git a/docs/pattern/list.md b/docs/pattern/list.md index 460c552b42..983b2e381a 100644 --- a/docs/pattern/list.md +++ b/docs/pattern/list.md @@ -3,8 +3,6 @@ - order: 3 - chinese: 列表 ---- - 列表是非常常见的界面元素,有多种使用场景: - 获取概览 @@ -13,6 +11,8 @@ - 排序与过滤 - 重新安排、添加、删除或重新分类列表项 +--- + ## 交互 ### 显示详情信息 @@ -98,4 +98,4 @@
-## 案例(敬请期待) +## 案例(敬请期待) diff --git a/docs/pattern/navigation.md b/docs/pattern/navigation.md index 6037429e7a..a103916eff 100644 --- a/docs/pattern/navigation.md +++ b/docs/pattern/navigation.md @@ -3,14 +3,14 @@ - order: 1 - chinese: 导航 ---- - 在广义上,任何告知用户他在哪里,他能去什么地方以及如何到达那里的方式,都可以称之为导航。而我们将中后台常见的导航方式进行提炼和封装,帮助设计者快速构建清晰和流畅的系统。当设计者使用导航或者自定义一些导航结构时,请注意: 1. 尽可能提供标示、上下文线索以及网站地图,避免用户迷路; 2. 保持导航样式和行为一致或者减少导航数量,降低用户学习成本; 3. 尽可能减少页面间的跳转(eg:一个常见任务需要多个页面跳转时,请减少至一至两次),让用户移动距离保持简短。 +--- + ## 常见导航
diff --git a/docs/pattern/table.md b/docs/pattern/table.md index 5b10851e2c..7d6e881f3b 100644 --- a/docs/pattern/table.md +++ b/docs/pattern/table.md @@ -3,10 +3,10 @@ - order: 4 - chinese: 表格 ---- - 表格可被视为一种列表。它经常和其他界面元素一起协同,用于展示和操作结构化数据,并经常用于详情信息的入口。 +--- + ## 内容 结构示例 @@ -154,4 +154,4 @@ 数值右对齐(带小数则按小数点对齐),其余左对齐。 -## 案例(敬请期待) +## 案例(敬请期待) diff --git a/docs/practice/cases.md b/docs/practice/cases.md index e7b857bb71..bcd3cf7843 100644 --- a/docs/practice/cases.md +++ b/docs/practice/cases.md @@ -5,9 +5,9 @@ --- -Ant Design 是面向中后台的 UI 设计语言。 +Ant Design 是面向中台的 UI 设计语言。 -从 2015 年 4 月起,Ant Design 在蚂蚁金服中后台产品线迅速推广,对接多条业务线,覆盖系统 40 个以上。定位于中后台业务的 Ant Design 兼顾专业和非专业的设计人员,具有学习成本低、上手速度快、实现效果好等特点,并且提供从界面设计到前端开发的全链路生态,可以大大提升设计和开发的效率。 +从 2015 年 4 月起,Ant Design 在蚂蚁金服中后台产品线迅速推广,对接多条业务线,覆盖系统 40 个以上。定位于中台业务的 Ant Design 兼顾专业和非专业的设计人员,具有学习成本低、上手速度快、实现效果好等特点,并且提供从界面设计到前端开发的全链路生态,可以大大提升设计和开发的效率。 Ant Design 目前在外部也有 [许多产品实践](https://github.com/ant-design/ant-design/issues/477),如果你的公司和产品从中受益,欢迎留言。 diff --git a/docs/react/getting-started.md b/docs/react/getting-started.md index e64ce549d2..562a620acf 100644 --- a/docs/react/getting-started.md +++ b/docs/react/getting-started.md @@ -2,10 +2,10 @@ - order: 1 ---- - Ant Design React 致力于提供给程序员**愉悦**的开发体验。 +--- + ## 第一个例子 最简单的试用方式参照以下 CodePen 演示,也推荐 Fork 本例来进行 `Bug Report`,注意不要在实际项目中这样使用。 @@ -118,7 +118,7 @@ Ant Design React 支持所有的现代浏览器和 IE8+。 - + @@ -129,10 +129,6 @@ Ant Design React 支持所有的现代浏览器和 IE8+。 ``` -另外,由于 babel 对 IE8 的支持不佳,你可能会遇到类似 [#28](https://github.com/ant-tool/atool-build/issues/28) 和 [#858](https://github.com/ant-design/ant-design/issues/858) 的 default 报错的问题。 - -[antd-init](http://github.com/ant-design/antd-init) 脚手架已经解决了这个问题,你也可以参照这个 [webpack 配置](https://github.com/ant-design/antd-init/blob/8c4a55d205c82a6ad87814bbf997696051713d58/boilerplate/webpack.config.js#L10-L14)。 - > 更多 IE8 下使用 React 的相关问题可以参考:https://github.com/xcatliu/react-ie8 ## 自行构建 diff --git a/docs/react/introduce.md b/docs/react/introduce.md index 09e249f6aa..fe1a2d6401 100644 --- a/docs/react/introduce.md +++ b/docs/react/introduce.md @@ -2,8 +2,6 @@ - order: 0 ---- - 这里是 Ant Design 的 React 实现,开发和服务于企业级后台产品。
@@ -23,6 +21,7 @@ } +--- ## 特性 @@ -77,7 +76,10 @@ import 'antd/lib/index.css'; // or 'antd/style/index.less' ## 谁在使用 - 蚂蚁金服 +- 阿里巴巴 - 口碑 +- 新美大 +- 滴滴 > 如果你的公司和产品使用了 Ant Design,欢迎到 [这里](https://github.com/ant-design/ant-design/issues/477) 留言。 diff --git a/docs/react/upgrade-notes.md b/docs/react/upgrade-notes.md index cc76d4c5d8..acc34a8034 100644 --- a/docs/react/upgrade-notes.md +++ b/docs/react/upgrade-notes.md @@ -4,13 +4,15 @@ --- +这里只列出升级中的不兼容改动,其他改动见 [Changelog](/changelog)。 + ## 0.11 => 0.12 --- ### 使用 Form 提供的校验功能代替 Validation -Validation 已经被废弃,并会在以后的版本完全移除,所以建议尽快使用 Form 自带的校验功能替换 Validation。具体使用方式可以查阅文档和例子([#1](http://ant.design/components/form/#demo-validate-basic) [#2](http://ant.design/components/form/#demo-validate-other) [#3](http://ant.design/components/form/#demo-validate-customized))。 +Validation 已经被废弃,并会在以后的版本完全移除,所以建议尽快使用 Form 自带的校验功能替换 Validation。具体使用方式可以查阅文档和例子([#1](http://ant.design/components/form/#demo-validate-basic) [#2](http://ant.design/components/form/#demo-validate-other) [#3](http://ant.design/components/form/#demo-validate-customized))。 ### Progress `format` 属性的值改为函数 diff --git a/docs/spec/alignment.md b/docs/spec/alignment.md new file mode 100644 index 0000000000..c533ffe39e --- /dev/null +++ b/docs/spec/alignment.md @@ -0,0 +1,37 @@ +# 对齐 + +- category: 十大原则 +- order: 2 +- subtitle: Alignment + +正如『格式塔学派』中的连续律(Law of Continuity)所描述的,在知觉过程中人们往往倾向于使知觉对象的直线继续成为直线,使曲线继续成为曲线。在界面设计中,将元素进行对齐,既符合用户的认知特性,也能引导视觉流向,让用户更流畅地接收信息。 + +> ** 格式塔学派(德语:Gestalttheorie)** :是心理学重要流派之一,兴起于 20 世纪初的德国,又称为完形心理学;主张人脑的运作原理是整体的,『整体不同于其部件的总和』。——摘自『维基百科』 + +--- + +## 文案类对齐 + +推荐示例 +不推荐示例 + +如果页面的字段或段落较短、较散时,需要确定一个统一的视觉起点。 + +--- + +## 表单类对齐 + +冒号对齐示例 + +冒号对齐(右对齐)能让内容锁定在一定范围内,让用户眼球顺着冒号的视觉流,就能找到所有填写项,从而提高填写效率。 + +更多对齐方式,请查看[『模式/表单/规格/对齐方式』](../pattern/form#对齐方式)。 + +--- + +## 数字类对齐 + +正确示例 +错误示例 + +为了快速对比数值大小,建议所有数值取相同有效位数,并且右对齐。 diff --git a/docs/spec/colors.md b/docs/spec/colors.md index 7e1277ec57..e48c4e3707 100644 --- a/docs/spec/colors.md +++ b/docs/spec/colors.md @@ -1,6 +1,6 @@ # Colors -- category: 基础 +- category: 设计基础 - order: 2 - chinese: 色彩 @@ -10,7 +10,7 @@ 色彩在界面设计中的使用应同时具备品牌识别性以及界面设计功能性。众所周知色彩是相当感性的东西,设计中对色彩的运用首要应考虑到品牌层面的表达,另外很重要的一点是色彩的运用应达到信息传递,动作指引,交互反馈,或是强化和凸现某一个元素的目的。任何颜色的选取和使用应该是有意义的。众所周知色彩是相当感性的东西,设计中对色彩的运用首要应考虑到品牌层面的表达,另外很重要的一点是色彩的运用应达到信息传递,动作指引,交互反馈,或是强化和凸现某一个元素的目的。任何颜色的选取和使用应该是有意义的。 -## ANTD Color +## Ant Design Colors Ant Design 的色板由 9 种基本色彩组成,每种基本色又衍生出九宫格色板,在此基础上还可以通过黑白叠加的方式实现色彩明暗的效果。 diff --git a/docs/spec/contrast.md b/docs/spec/contrast.md new file mode 100644 index 0000000000..4e48cec749 --- /dev/null +++ b/docs/spec/contrast.md @@ -0,0 +1,48 @@ +# 对比 + +- category: 十大原则 +- order: 3 +- subtitle: Contrast + +对比是增加视觉效果最有效方法之一,同时也能在不同元素之间建立一种有组织的层次结构,让用户快速识别关键信息。 + +> 注:要实现有效的对比,对比就必须强烈,切不可畏畏缩缩。 + +--- + +## 主次关系对比 + +正确示例 +错误示例 + +为了让用户能在操作上(类似表单、弹出框等场景)快速做出判断, 来突出其中一项相对更重要或者更高频的操作。 + +> 注意:突出的方法,不局限于强化重点项,也可以是弱化其他项。 + +
+ +不区分主次的示例 + +在一些需要用户慎重决策的场景中,系统应该保持中立,不能替用户或者诱导用户做出判断。 + +--- + +## 总分关系对比 + +总分关系示例 1 + +总分关系示例 2 + +通过调整排版、字体、大小等方式来突出层次感,区分总分关系,使得页面更具张力和节奏感。 + +--- + +## 状态关系对比 + +静态对比示例 + +动态对比示例 + +通过改变颜色、增加辅助形状等方法来实现状态关系的对比,以便用户更好的区分信息。 + +常见类型有『静态对比』、『动态对比』。 diff --git a/docs/spec/direct.md b/docs/spec/direct.md new file mode 100644 index 0000000000..94cf2e3d99 --- /dev/null +++ b/docs/spec/direct.md @@ -0,0 +1,65 @@ +# 直截了当 + +- category: 十大原则 +- order: 5 +- subtitle: Make it Direct + +正如 Alan Cooper 所言:『需要在哪里输出,就要允许在哪里输入』。这就是直接操作的原理。eg:不要为了编辑内容而打开另一个页面,应该直接在上下文中实现编辑。 + +--- + +## 页内编辑 + +单击编辑示例 + +单字段行内编辑 + +当『易读性』远比『易编辑性』重要时,可以使用『单击编辑』。 + +
+ +文字链/图标编辑示例 + +当『易读性』为主,同时又要突出操作行的『易编辑性』时,可使用『文字链/图标编辑』。 + +
+ +多字段行内编辑示例 + +多字段行内编辑 + +>注:在『多字段行内编辑』的情况下,显示的内容和编辑时所需的字段会存在比较大的差异,所以更需要『巧用过渡』原则中的[『解释刚刚发生了什么』](../spec/transition#解释刚刚发生了什么)来消除这种视觉影响。 + +
+ +更多有关『页内编辑』的模式,可查看[『模式/表格/交互』](../pattern/table#模块编辑)中的内容。 + +
+ +--- + +## 利用拖放 + +拖放列表示例 + +拖放列表 + +只能限制在一个维度(上/下或者左/右)进行拖放。 + +
+ +拖放图片/文件示例 + +拖放图片/文件 + +
+ +拖放对象(敬请期待) + +拖放多个对象(敬请期待) + +
+ +--- + +## 直接选择(敬请期待) diff --git a/docs/spec/easing.md b/docs/spec/easing.md index d04080a93c..ce625e0590 100644 --- a/docs/spec/easing.md +++ b/docs/spec/easing.md @@ -15,7 +15,7 @@ 当某个东西往下掉时,首先是越掉越快,撞到地上后回弹,最终才又碰触地板。 -### 质量和重量 +## 质量和重量 在物理世界里,是以力量附加到物体对象里,加上自身的质量才完成一段动画。力量的持续时间决定物体的加速,减速与改变方向。 diff --git a/docs/spec/feature.md b/docs/spec/feature.md new file mode 100644 index 0000000000..155582a759 --- /dev/null +++ b/docs/spec/feature.md @@ -0,0 +1,108 @@ +# 三大特性 + +- order: 1 + +与众不同的是,Ant Design 不但追求『用户』的使用体验,还追求『设计者』的使用体验,真真正正贯彻和践行『以人为本』的设计理念。 + +
+
+ +
微小
+
致力于微小而美好的改变,力求在细节上精益求精,不仅让业务产品更加实用和可靠,而且还能让『用户』感到小惊喜。
+
+
+ +
确定
+
制定通俗而科学的设计原则、运用面向对象的方法、使用一致的文档沟通机制,给予研发团队一种高确定性、低熵值的研发状态。
+
+
+ +
幸福
+
不苛求简单,但是力求让『用户』和『设计者』流畅的完成目标,并带着成功和满足离开。
+
+
+ + + +--- + +## 微小 + +### 微创新 + +数值输入框示例 + +分页示例 + +字数校验框示例 + +『不同』不一定『更好』,但是『更好』一定『不同』。不断追求细节上的『更好』,使得我们的组件和同类产品都不一样,自然而然的『不同』。 + +### 集成创新 + +填空示例 + +带图表的表格 + +选择合适的组件进行组合和集成,形成优势互补的创新过程,来满足多变的业务需求。 + +--- + +## 确定 + +### 面向对象的方法 + +色值换算工具示例 + +排版规则示例 + +操作反馈 - 正确示例 + +操作反馈 - 错误示例 + +探索设计规律,并将其抽象成『对象』,增强界面设计的灵活性和可维护性,同时也减少『设计者』的主观干扰,从而降低系统的不确定性。 + +### 通俗而科学的设计原则 + +详见[『十大原则』](./principle)。 + +--- + +## 幸福 + +### 用户的幸福 + +用户的幸福示例 + +漂亮的组件、精致的排版、流畅的动画等的元素,使用户在『本能层次』中产生积极反应; + +良好的功能、性能和可用性,使用户在『行为层次』中产生积极反应; + +自我形象、个人满足和美好记忆,使用户在『反思层次』中体验思想和情感的交融。 + +### 设计者的幸福 + +设计者的幸福示例 + +从『无』到『有』时,提供一整套设计解决方案,帮助『设计者』将商业想法快速形成产品并推向市场,快速、低成本试错。 + +从『有』到『优』时,提供一系列自定义建议,帮助『设计者』塑造产品个性并提升整体体验,服务海量用户。 diff --git a/docs/spec/font.md b/docs/spec/font.md index 0954633e8e..9093eda02f 100644 --- a/docs/spec/font.md +++ b/docs/spec/font.md @@ -1,12 +1,12 @@ # 字体 -- category: 基础 +- category: 设计基础 - order: 0 ---- - 跨平台的字体设定,力求在各个操作系统下都有最佳展示效果。 +--- + ## 字体家族 - 中文字体族: diff --git a/docs/spec/introduce.md b/docs/spec/introduce.md index 96a3aee36f..fbddee2c20 100644 --- a/docs/spec/introduce.md +++ b/docs/spec/introduce.md @@ -2,20 +2,23 @@ - order: 0 +
+ +
+ +在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,给设计师和工程师带来很多困扰和重复建设,大大降低了产品的研发效率。我们(蚂蚁金服体验技术部)经过大量的项目实践和总结,沉淀出一个中台设计语言 Ant Design。旨在统一中台项目的前端 UI 设计,屏蔽不必要的设计差异和实现成本,解放设计和前端的研发资源。 + +Ant Design 是一个致力于提升『用户』和『设计者』使用体验的中台设计语言。它模糊了产品经理、交互设计师、视觉设计师、前端工程师、开发工程师等角色边界,将进行 UE 设计和 UI 设计人员统称为『设计者』,利用统一的规范进行设计赋能,全面提高中台产品体验和研发效率。 + --- -Ant Design 是一个 UI 设计语言,是一套提炼和应用于企业级中后台产品的交互语言和视觉体系。 - - - -Ant Design 源自蚂蚁金服体验技术部的后台产品开发。在中后台产品设计中,通常有很多类似的页面和控件,不同的产品会出现不同的规范和实现,给设计师和工程师带来很多困扰和重复建设,降低企业后台的整体研发效率。我们的设计师和前端工程师经过大量的项目实践和总结,希望能沉淀出一套企业级的交互视觉规范,统一中后台项目的前端 UI 设计,屏蔽各种不必要的设计差异和前端实现成本,解放设计和前端开发资源。 - -整套设计规范还在持续整理和完善中。 - ## 谁在使用 - 蚂蚁金服 +- 阿里巴巴 - 口碑 +- 新美大 +- 滴滴 > 如果你的公司和产品使用了 Ant Design,欢迎到 [这里](https://github.com/ant-design/ant-design/issues/477) 留言。 diff --git a/docs/spec/invitation.md b/docs/spec/invitation.md new file mode 100644 index 0000000000..09f3efb206 --- /dev/null +++ b/docs/spec/invitation.md @@ -0,0 +1,82 @@ +# 提供邀请 + +- category: 十大原则 +- order: 8 +- subtitle: Provide Invitation + +很多富交互模式(eg:『拖放』、『行内编辑』、『上下文工具』)都有一个共同问题,就是缺少易发现性。所以『提供邀请』是成功完成人机交互的关键所在。 + +邀请就是引导用户进入下一个交互层次的提醒和暗示,通常包括意符(eg:实时的提示信息)和可供性,以表明在下一个界面可以做什么。当可供性中可感知的部分(Perceived Affordance)表现为意符时,人机交互的过程往往更加自然、顺畅。 + +> ** 意符(Signifiers)** :一种额外的提示,告诉用户可以采取什么行为,以及应该怎么操作;必须是可感知(eg:视觉、听觉、触觉等)。——摘自《设计心理学 1 》 + +> ** 可供性(Affordance)** :也被翻译成『示能』,由 James J. Gibson 提出,定义为物品的特性与决定物品用途的主体能力之间的关系;其中部分可感知(此部分定义为 Perceived Affordance),部分不可感知。——摘自《设计心理学 1 》 + +--- + + +## 静态邀请 + +指通过可视化技术在页面上提供引导交互的邀请。 + +
+ +文本邀请示例 + +白板式邀请示例 + +未完成邀请示例 + +引导操作邀请:一般以静态说明形式出现在页面上,不过它们在视觉上也可以表现出多种不同样式。 +常见类型:『文本邀请』、『白板式邀请』、『未完成邀请』。 + +
+ +漫游探索邀请示例 1 + +漫游探索邀请示例 2 + +漫游探索邀请:是向用户介绍新功能的好方法,尤其是对于那些设计优良的界面。但是它不是『创口贴』,仅通过它不能解决界面交互的真正问题。 + +>注:保持漫游过程简单,让用户容易退出和重新启动;保持内容简明扼要,与功能密切相关。 + + +
+ +--- + +## 动态邀请 + +指以响应用户在特定位置执行特定操作的方式,提供特定的邀请。 + +
+ +悬停邀请示例 1 + +悬停邀请示例 2 + +悬停邀请:在鼠标悬停期间提供邀请。 + + +
+ +推论邀请示例 + +推论邀请:用于交互期间,合理推断用户可能产生的需求。 + +
+ +更多内容邀请示例 + +更多内容邀请:用于邀请用户查看更多内容。 + + +
+ +
+ +预期功能邀请 (敬请期待) + +
+ +拖放邀请 (敬请期待) diff --git a/docs/spec/layout/index.md b/docs/spec/layout/index.md index e806254042..8514201c96 100644 --- a/docs/spec/layout/index.md +++ b/docs/spec/layout/index.md @@ -1,7 +1,7 @@ # Layout - template: component -- category: 基础 +- category: 设计基础 - order: 4 - cols: 1 - chinese: 常用布局 diff --git a/docs/spec/lightweight.md b/docs/spec/lightweight.md new file mode 100644 index 0000000000..6b6bdb7a38 --- /dev/null +++ b/docs/spec/lightweight.md @@ -0,0 +1,76 @@ +# 简化交互 + +- category: 十大原则 +- order: 6 +- subtitle: Keep it Lightweight + +根据费茨法则(Fitts's Law)所描述的,如果用户鼠标移动距离越少、对象相对目标越大,那么用户越容易操作。通过运用上下文工具(即:放在内容中的操作工具),使内容和操作融合,从而简化交互。 + +> ** 费茨法则 ** :到达目标的时间是到达目标的距离与目标大小的函数,具体:。其中:1.设备当前位置和目标位置的距离(D);2.目标的大小(W)。距离越长,所用时间越长;目标越大,所用时间越短。 + +--- + +## 实时可见工具 + + +实时可见工具示例 --摘自知乎 + +如果某个操作非常重要,就应该把它放在界面中,并实时可见。 + +
+ +--- + +## 悬停即现工具 + + +悬停即现工具示例 + +如果某个操作不那么重要,或者使用『实时可见工具』过于啰嗦会影响用户阅读时,可以在悬停在该对象上时展示操作项。 + +
+ +--- + +## 开关显示工具 + + +开关显示工具示例 + +如果某些操作只需要在特定模式时显示,可以通过开关来实现。 + + +
+ +--- + +## 交互中的工具 + +推荐示例 + +推荐示例 + +不推荐示例 + + +如果操作不重要或者可以通过其他途径完成时,可以将工具放置在用户的操作流程中,减少界面元素,降低认知负担,给用户小惊喜。 + +此处也可以运用[『提供邀请』](../spec/invitation) 相关的知识点。 + +
+ +--- + +## 可视区域 ≠ 可点击区域 + +文字链热区示例 + +在使用 Table 时,文字链的点击范围受到文字长短影响,可以设置整个单元格为热区,以便用户触发。 + +
+ +按钮热区示例 + +当需要增强按钮的响应性时,可以通过增加用户点击热区的范围,而不是增大按钮形状,从而增强响应性,又不缺失美感。 + +>注:在移动端尤其适用。 diff --git a/docs/spec/motion.md b/docs/spec/motion.md index f94014f62e..b9e1323572 100644 --- a/docs/spec/motion.md +++ b/docs/spec/motion.md @@ -14,7 +14,6 @@ const Select = antd.Select; const Option = Select.Option; const OptGroup = Select.OptGroup; - let motions = []; motions = motions.concat([[{ name: '淡入', diff --git a/docs/spec/page-transition.md b/docs/spec/page-transition.md deleted file mode 100644 index 75cf6c831e..0000000000 --- a/docs/spec/page-transition.md +++ /dev/null @@ -1,77 +0,0 @@ -# Page Transition - -- category: 动画 -- order: 1 -- chinese: 互动转换 - ---- - -## 响应互动 - -响应交互一般是指我们在浏览页面时,点击元素时动画给我们视觉上的反馈,每个交互动效都能给我们带来不同视觉效果。 - -比如:按钮上的 hover 或 click 效果,随着你的鼠标事件而改变自身或增加元素在按钮上,或者折叠面板和弹出框,点击后给你呈现新加入的信息元素。 - -### 按钮反馈 - -
-
- - -## 转换动画 - -### 视觉连贯性三元素 - -- Adding:  新加入的信息元素应被告知如何使用,从页面转变的信息元素需被重新识别。 - -- Receding:  与当前页无关的信息元素应采用适当方式移除。 - -- Normal: 指那些从转场开始到结束都没有发生变化的信息元素。 - -### 可折叠面板 - -对于信息元素内容区域的延伸,显示信息元素和进一步内容对象之间的直接连接。 - - - 被展开的信息区域内容按照一定的路径依次进场。 - -
-
- - -### 弹出框动效 - -从一个触发点触发一个弹出框时,弹框从所触发区域弹出,且触发区域视觉上基本保持不变。这样让触发区域和弹出区域有所关联,提高用户对新内容的认知。 - -
- -
- - -### 页面转场 - -从内容A到内容B的转变过程时能有效的吸引用户注意力,突出视觉中心,提高整体视觉效果。 - - - 大页面转场可采用左出右入的形式。 - - - 小的信息元素排布或块状较多的情况下,根据一定的路径层次依次进场,区分维度层级,来凸显量级,来指引用户的视觉轨迹。 - -
- -
- -> 参考我们的进场组件案例。查看[进场动画组件(QueueAnim)](/components/queue-anim/) - -```__react -import scripts from '../../site/component/Motion/page-transition'; -class ExecuteJS extends React.Component { - componentDidMount() { - scripts(); - } - - render() { - return null; - } -} - -ReactDOM.render(, mountNode); -``` diff --git a/docs/spec/principle.md b/docs/spec/principle.md new file mode 100644 index 0000000000..1a7e7c6f38 --- /dev/null +++ b/docs/spec/principle.md @@ -0,0 +1,45 @@ +# 引言 + +- category: 十大原则 +- order: 0 +- subtitle: Introduction + +『好设计比差设计更难发现』,因为好设计是如此的自然,帮助用户轻松的完成目标,以至于用户根本意识不到好设计的存在。 + +我们借鉴了《写给大家看的设计书》、《Web 界面设计》对设计原则的总结和推理,并结合我们团队的实践和理解,制定了以下十大原则,为『设计者』提供解决具体问题的准则和启示。 + +> 注:设计原则是对具象设计的抽象和总结,然而产品是一个整体,用户对整个产品的认知也是从全局到局部,所以忽略全局,只在局部套用原则是不可取的。对于这些原则,『设计者』应当理性地学会它,而后勇敢地抛弃它。 + +--- + + + +#### Ant Design 十大设计原则 + +- [亲密性 Proximity](./proximity) +- [对齐 Alignment](./alignment) +- [对比 Contrast](./contrast) +- [重复 Repetition](./repetition) +- [直截了当 Make it Direct](./direct) +- [简化交互 Keep it Lightweight](./lightweight) +- [足不出户 Stay in the Page](./stay) +- [提供邀请 Provide Invitation](./invitation) +- [巧用过渡 Use Transition](./transition) +- [即时反应 React Immediately](./reaction) diff --git a/docs/spec/proximity.md b/docs/spec/proximity.md new file mode 100644 index 0000000000..0c9d6daaca --- /dev/null +++ b/docs/spec/proximity.md @@ -0,0 +1,37 @@ +# 亲密性 + +- category: 十大原则 +- order: 1 +- subtitle: Proximity + +如果信息之间关联性越高,它们之间的距离就应该越接近,也越像一个视觉单元;反之,则它们的距离就应该越远,也越像多个视觉单元。亲密性的根本目的是实现组织性,让用户对页面结构和信息层次一目了然。 + +--- + +## 纵向间距关系 + +纵向间距示例 + +通过『小号间距』、『中号间距』、『大号间距』这三种规格来划分信息层次。 + +
+ +增加元素示例 + +在这三种规格不适用的情况下,可以通过加减『基础间距』的倍数,或者增加元素来拉开信息层次。 + +> 注:在 Ant Design 中,`y=8+8*n`。其中,`n>=0`,y 是纵向间距,8 是『基础间距』。 + +--- + +## 横向间距关系 + +组合排布示例 + +为了适用不同尺寸的屏幕,在横向采用栅格布局来排布组件,从而保证布局的灵活性。 + +
+ +复选框内示例 + +在一个组件内部,元素的横向间距也应该有所不同。 diff --git a/docs/spec/reaction.md b/docs/spec/reaction.md new file mode 100644 index 0000000000..d9ae47c7f5 --- /dev/null +++ b/docs/spec/reaction.md @@ -0,0 +1,76 @@ +# 即时反应 + +- category: 十大原则 +- order: 10 +- subtitle: React Immediately + +『提供邀请』的强大体现在`交互之前`给出反馈,解决易发现性问题;『巧用过渡』的有用体现在它能够在`交互期间`为用户提供视觉反馈;『即时反应』的重要性体现在`交互之后`立即给出反馈。 + +就像『牛顿第三定律』所描述作用力和反作用一样,用户进行了操作或者内部数据发生了变化,系统就应该立即有一个对应的反馈,同时输入量级越大、重要性越高,那么反馈量级越大、重要性越高。 + +虽然反馈太多(准确的说,错误的反馈太多)是一个问题,但是反馈太少甚至没有反馈的系统,则让人感觉迟钝和笨拙,用户体验更差。 + +> ** 牛顿第三定律 ** :当两个物体互相作用时,彼此施加于对方的力,其大小相等、方向相反。——摘自《维基百科》 + +--- + +## 查询模式 + + +确定类目示例 + +不确定类目示例 + +自动完成:用户输入时,下拉列表会随着输入的关键词显示匹配项。 +根据查询结果分类的多少,可以分为『确定类目』、『不确定类目』两种类型。 + +
+ +实时搜索示例 + +实时搜索:随着用户输入,实时显示搜索结果。『自动完成』、『实时建议』的近亲。 + +
+ +微调搜索:随着用户调整搜索条件,实时调整搜索结构。具体可见:[『模式/高级搜索』](../pattern/advanced-search)。 + +
+ +--- +## 反馈模式 + +实时预览示例 + +实时预览:在用户提交输入之前,让他先行了解系统将如何处理他的输入。 + +>注:解决错误最好的办法,就是不让错误发生。而『实时预览』就是有效避免错误的好设计。 + +
+ +渐进式展现:在必要的时候提供必要的提示,而不是一股脑儿显示所有提示,导致界面混乱,增加认知负担。案例详见[『足不出户/渐进式展现』](../spec/stay#流程处理)。 + +
+ +按钮加载示例 + +表格加载示例 + +富列表加载示例 + +页面加载示例 + + +进度指示:当一个操作需要一定时间完成时,就需要即时告知进度,保持与用户的沟通。 +常见的进度指示:『按钮加载』、『表格加载』、『富列表加载』、『页面加载』。可根据操作的量级和重要性,展示不同类型的进度指示。 + +
+ +点击刷新示例 + +点击刷新:告知用户有新内容,并提供按钮等工具帮助用户查看新内容。 + +
+ +定时示例 + +定时刷新:无需用户介入,定时展示新内容。 diff --git a/docs/spec/repetition.md b/docs/spec/repetition.md new file mode 100644 index 0000000000..4b184b9b7a --- /dev/null +++ b/docs/spec/repetition.md @@ -0,0 +1,19 @@ +# 重复 + +- category: 十大原则 +- order: 4 +- subtitle: Repetition + +相同的元素在整个界面中不断重复,不仅可以有效降低用户的学习成本,也可以帮助用户识别出这些元素之间的关联性。 + +--- + +## 重复元素 + +线框重复示例 + +设计要素重复示例 + +文案格式重复示例 + +重复元素可以是一条粗线、一种线框,某种相同的颜色、设计要素、设计风格,某种格式、空间关系等。 diff --git a/docs/spec/stay.md b/docs/spec/stay.md new file mode 100644 index 0000000000..a9a511a8db --- /dev/null +++ b/docs/spec/stay.md @@ -0,0 +1,99 @@ +# 足不出户 + +- category: 十大原则 +- order: 6 +- subtitle: Stay on the Page + +能在这个页面解决的问题,就不要去其它页面解决,因为任何页面刷新和跳转都会引起变化盲视(Change Blindness),导致用户心流(Flow)被打断。频繁的页面刷新和跳转,就像在看戏时,演员说完一行台词就安排一次谢幕一样。 + +> ** 变换盲视(Change Blindness)** :指视觉场景中的某些变化并未被观察者注意到的心理现象。产生这种现象的原因包括场景中的障碍物,眼球运动、地点的变化,或者是缺乏注意力等。——摘自《维基百科》 + +> ** 心流(Flow)** :也有别名以化境 (Zone) 表示,亦有人翻译为神驰状态,定义是一种将个人精神力完全投注在某种活动上的感觉;心流产生时同时会有高度的兴奋及充实感。——摘自《维基百科》 + +--- + +## 覆盖层 + +推荐示例 + +推荐示例 + +不推荐示例 + +二次确认覆盖层:避免滥用 Modal 进行二次确认,应该勇敢的让用户去尝试,给用户机会『撤消』即可。 + +
+ +详情覆盖层示例 + +详情覆盖层:一般在列表中,通过用户『悬停』/『点击』某个区块,在当前页加载该条列表项的更多详情信息。 + +> 注:使用『悬停』激活时,当鼠标移入时,需要设置 0.5 秒左右的延迟触发;当鼠标移出时,立刻关闭覆盖层 + +
+ +输入覆盖层示例 + +输入覆盖层:在覆盖层上,让用户直接进行少量字段的输入。 + +
+ +--- + +## 嵌入层 + +列表嵌入层示例 + +列表嵌入层:在列表中,显示某条列表项的详情信息,保持上下文不中断。 + +
+ +详情嵌入层 (敬请期待) + +
+ +标签页示例 + +标签页:将多个平级的信息进行整理和分类了,一次只显示一组信息。 + +
+ +--- + +## 虚拟页面 + +在交互过程中,『覆盖层』可以在当前页面上方显示附加内容和交互链接;『嵌入层』可以在页面内部实现同样效果;而『虚拟页面』不局限机械时代的『页面』,可以利用信息时代的特点构建一种新型『页面』。 + +无限加载和分页器,详见[『模式/列表/显示长列表』](../pattern/list#显示长列表) + +走马灯,详见[『模式/列表/显示图片』](../pattern/list#显示图片) + +
+ +伸缩式用户界面(敬请期待) + +
+ +--- + +## 流程处理 + +长期以来,Web 实现流程的方式就是把每个步骤放在一个单独的页面上。虽然这种做法是分解问题最简单的方式,但并不是最佳解决方案。对于某些『流程处理』而言,让用户始终待在同一个页面上则更有必要。 + +
+ +渐进式展现示例 + +渐进式展现:基于用户的操作/某种特定规则,渐进式展现不同的操作选项。 + +
+ +配置程序示例 + +配置程序:通过提供一系列的配置项,帮助用户完成任务或者产品组装。 + +
+ +弹出框覆盖层示例 + +弹出框覆盖层:虽然弹出框的出现会打断用户的心流,但是有时候在弹出框中使用『步骤条』来管理复杂流程也是可行的。 diff --git a/docs/spec/transition.md b/docs/spec/transition.md new file mode 100644 index 0000000000..21c979495d --- /dev/null +++ b/docs/spec/transition.md @@ -0,0 +1,74 @@ +# 巧用过渡 + +- category: 十大原则 +- order: 9 +- subtitle: Use Transition + +人脑灰质(Gray Matter)会对动态的事物(eg:移动、形变、色变等)保持敏感。在界面中,适当的加入一些过渡效果,能让界面保持生动,同时也能增强用户和界面的沟通。 + +- Adding: 新加入的信息元素应被告知如何使用,从页面转变的信息元素需被重新识别。 +- Receding: 与当前页无关的信息元素应采用适当方式移除。 +- Normal: 指那些从转场开始到结束都没有发生变化的信息元素。 + +--- + +## 在视图变化时保持上下文 + +
+ { leftChildren } - { isSingleCol ? null : { rightChildren } } + { + isSingleCol ? null : + { rightChildren } + }
{ (doc.api || []).map(utils.objectToComponent.bind(null, location.pathname)) } diff --git a/site/component/Footer/index.jsx b/site/component/Footer/index.jsx index a6c473cb4f..cdda0f369b 100644 --- a/site/component/Footer/index.jsx +++ b/site/component/Footer/index.jsx @@ -1,8 +1,28 @@ import React from 'react'; import { Select } from '../../../'; +import { version as antdVersion } from '../../../package.json'; +import { docVersions } from '../../website.config'; +const Option = Select.Option; export default class Footer extends React.Component { + constructor(props) { + super(props); + + this.handleVersionChange = this.handleVersionChange.bind(this); + } + + handleVersionChange(url) { + window.location.href = url; + } + render() { + const options = Object.keys(docVersions).map((version, index) => { + return ( + + ); + }); return (
    @@ -38,9 +58,9 @@ export default class Footer extends React.Component {
    ©2015 蚂蚁金服体验技术部出品
    文档版本: - + { options }
    diff --git a/site/component/Motion/motion.js b/site/component/Motion/motion.js index d27b5f5156..06b0d91702 100644 --- a/site/component/Motion/motion.js +++ b/site/component/Motion/motion.js @@ -846,9 +846,7 @@ nm.start = function (self) { module.exports = newMotion; var motionVideo = { - video: ['https://t.alipayobjects.com/images/rmsweb/T1yHhhXfxkXXXXXXXX.webm', 'https://t.alipayobjects.com/images/rmsweb/T12I8gXexdXXXXXXXX.webm', 'https://t.alipayobjects.com/images/rmsweb/T1br0gXghtXXXXXXXX.webm', 'https://t.alipayobjects.com/images/rmsweb/T14q0hXbBdXXXXXXXX.webm'], - videoMp4: ['https://t.alipayobjects.com/images/rmsweb/T15IXhXlXbXXXXXXXX.mp4', 'https://t.alipayobjects.com/images/rmsweb/T1e0hgXcpdXXXXXXXX.mp4', 'https://t.alipayobjects.com/images/rmsweb/T1lcRgXb4gXXXXXXXX.mp4', 'https://t.alipayobjects.com/images/T1qWNhXkpeXXXXXXXX.mp4'], - init: function () { + init: function (videoList, videoMp4List) { var self = this; $('.video-player').each((i, videoBox) => { @@ -860,9 +858,9 @@ var motionVideo = { $videoBox.append(svg.node); var video = $videoBox.find('video'); if (video[0].canPlayType('video/webm; codecs="vp8.0, vorbis"')) { - $('').appendTo(video); + $('').appendTo(video); } else { - $('').appendTo(video); + $('').appendTo(video); } video.css({ 'width': '100%' diff --git a/site/component/Motion/page-transition.js b/site/component/Motion/page-transition.js deleted file mode 100644 index 56a267667d..0000000000 --- a/site/component/Motion/page-transition.js +++ /dev/null @@ -1,5 +0,0 @@ -import Motion from './motion'; - -module.exports = function () { - Motion.motionVideo.init(); -}; diff --git a/site/component/utils.js b/site/component/utils.js index b13e9ccad0..e8d161e219 100644 --- a/site/component/utils.js +++ b/site/component/utils.js @@ -44,7 +44,7 @@ export function objectToComponent(pathname, object, index) { key: index, id: children, }, [ - object.children, + , #, ]); } diff --git a/site/static/style.less b/site/static/style.less index c414a1b947..4479f40205 100644 --- a/site/static/style.less +++ b/site/static/style.less @@ -341,6 +341,7 @@ footer { position: relative; z-index: 1; color: #666; + box-shadow: 0 1000px 0 1000px #fff; } footer ul { @@ -474,6 +475,7 @@ footer ul li > a { overflow: hidden; padding: 24px 0 0; margin-bottom: 24px; + min-height: 400px; position: relative; } @@ -482,7 +484,8 @@ footer ul li > a { margin-left: 219px; padding: 0 40px 120px; background: #fff; - min-height: 500px; + min-height: 400px; + min-height: 80vh; overflow: hidden; } @@ -625,6 +628,7 @@ footer ul li > a { border-left: 4px solid #e9e9e9; padding-left: 0.8em; margin: 1em 0; + font-style: italic; } .markdown blockquote p { @@ -637,6 +641,10 @@ footer ul li > a { margin-left: 8px; } +.markdown .waiting { + color: #ccc; +} + .markdown h1:hover .anchor, .markdown h2:hover .anchor, .markdown h3:hover .anchor, @@ -698,9 +706,15 @@ footer ul li > a { margin-left: 1em; } +.subtitle { + font-size: 80%; + font-weight: normal; + font-family: "Helvetica Neue", Helvetica; +} + .toc { font-size: 14px; - margin-bottom: 20px; + margin: 36px 0 24px; background: #fbfbfb; border-left: 2px solid #eee; } @@ -1173,12 +1187,13 @@ a.entry-link:hover .anticon-smile { .preview-image-boxes { float: right; - margin: 0 0 110px 60px; + margin: 0 0 70px 28px; width: 616px; + clear: both; } .preview-image-boxes + .preview-image-boxes { - margin-top: -75px; + margin-top: -35px; } .preview-image-box { @@ -1196,6 +1211,22 @@ a.entry-link:hover .anticon-smile { position: relative; } +.preview-image-wrapper.video { + padding: 0; + background: 0; + display: block; +} + +.preview-image-wrapper video { + width: 100%; + display: block; + + svg { + position: absolute; + top: 0; + left: 0; + } +} + .preview-image-wrapper.good:after { content: ''; width: 100%; diff --git a/site/templates/component.html b/site/templates/component.html new file mode 100644 index 0000000000..edb39fca5d --- /dev/null +++ b/site/templates/component.html @@ -0,0 +1,20 @@ +{% extends "page.html" %} + +{% block content %} +
    +
    +

    + {{ post.title }} {{ post.meta.chinese }}{{ post.meta.subtitle }} + {%- if post.meta.API %} + + + API 使用说明 + + {%- endif %} +

    + {{ post.html|add_anchor }} +
    + {%- include "demos.html" %} +
    +
    +{% endblock %} diff --git a/site/templates/layout.html b/site/templates/layout.html index 28ddc69da8..1629b3cb0d 100644 --- a/site/templates/layout.html +++ b/site/templates/layout.html @@ -13,7 +13,7 @@ {% block styles %}{% endblock %} - +