separate filter and sort into two click area

This commit is contained in:
afc163 2018-09-17 17:33:02 +08:00 committed by 偏右
parent 4c84dad106
commit 6f67c435c2
3 changed files with 116 additions and 111 deletions

View File

@ -764,11 +764,11 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
renderColumnsDropdown(columns: ColumnProps<T>[], locale: TableLocale) {
const { prefixCls, dropdownPrefixCls } = this.props;
const { sortOrder } = this.state;
return treeMap(columns, (originColumn, i) => {
let column = { ...originColumn };
let key = this.getColumnKey(column, i) as string;
return treeMap(columns, (column, i) => {
const key = this.getColumnKey(column, i) as string;
let filterDropdown;
let sortButton;
const isSortColumn = this.isSortColumn(column);
if ((column.filters && column.filters.length > 0) || column.filterDropdown) {
let colFilters = this.state.filters[key] || [];
filterDropdown = (
@ -780,53 +780,66 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
prefixCls={`${prefixCls}-filter`}
dropdownPrefixCls={dropdownPrefixCls || 'ant-dropdown'}
getPopupContainer={this.getPopupContainer}
key="filter-dropdown"
/>
);
}
if (column.sorter) {
let isSortColumn = this.isSortColumn(column);
if (isSortColumn) {
column.className = classNames(column.className, {
[`${prefixCls}-column-sort`]: sortOrder,
});
}
const isAscend = isSortColumn && sortOrder === 'ascend';
const isDescend = isSortColumn && sortOrder === 'descend';
sortButton = (
<div className={`${prefixCls}-column-sorter`}>
<span
<div className={`${prefixCls}-column-sorter`} key="sorter">
<Icon
className={`${prefixCls}-column-sorter-up ${isAscend ? 'on' : 'off'}`}
title="↑"
onClick={() => this.toggleSortOrder('ascend', column)}
>
<Icon type="caret-up" />
</span>
<span
type="caret-up"
theme="filled"
/>
<Icon
className={`${prefixCls}-column-sorter-down ${isDescend ? 'on' : 'off'}`}
title="↓"
onClick={() => this.toggleSortOrder('descend', column)}
>
<Icon type="caret-down" />
</span>
type="caret-down"
theme="filled"
/>
</div>
);
}
column.title = (
<span key={key}>
{column.title}
{sortButton}
{filterDropdown}
</span>
);
if (sortButton || filterDropdown) {
column.className = classNames(`${prefixCls}-column-has-filters`, column.className);
}
return column;
return {
...column,
className: classNames(column.className, {
[`${prefixCls}-column-has-actions`]: sortButton || filterDropdown,
[`${prefixCls}-column-has-filters`]: filterDropdown,
[`${prefixCls}-column-has-sorters`]: sortButton,
[`${prefixCls}-column-sort`]: isSortColumn && sortOrder,
}),
title: [
<div key="sort-area" className={`${prefixCls}-column-sorters`}>
{column.title}
{sortButton}
</div>,
filterDropdown,
],
onHeaderCell: (columnProps: ColumnProps<T>) => {
// for onHeaderCell compatibility
const headerCellProps = column.onHeaderCell ? column.onHeaderCell(columnProps) : {};
return {
onClick: (e: MouseEvent) => {
this.handleColumnHeaderClick(e);
if (headerCellProps && headerCellProps.onClick) {
headerCellProps.onClick(e);
}
},
...headerCellProps,
};
},
};
});
}
handleColumnHeaderClick = (e: MouseEvent) => {
console.log(e);
}
handleShowSizeChange = (current: number, pageSize: number) => {
const pagination = this.state.pagination;
pagination.onShowSizeChange!(current, pageSize);

View File

@ -11,6 +11,13 @@ import Radio from '../radio';
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
import { FilterMenuProps, FilterMenuState, ColumnProps, ColumnFilterItem } from './interface';
function stopPropagation(e: React.SyntheticEvent<any>) {
e.stopPropagation();
if (e.nativeEvent.stopImmediatePropagation) {
e.nativeEvent.stopImmediatePropagation();
}
}
export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, FilterMenuState> {
static defaultProps = {
handleFilter() {},
@ -181,12 +188,14 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
return filterIcon ? React.cloneElement(filterIcon as any, {
title: locale.filterTitle,
className: classNames(`${prefixCls}-icon`, filterIcon.props.className),
onClick: stopPropagation,
}) : (
<Icon
title={locale.filterTitle}
type="filter"
theme="filled"
className={dropdownSelectedClass}
onClick={stopPropagation}
/>
);
}

View File

@ -47,37 +47,86 @@
cursor: pointer;
color: @table-header-icon-color;
transition: all .3s;
width: 24px;
width: 28px;
position: absolute;
top: 0;
right: 0;
height: 100%;
text-align: center;
&:hover {
color: @text-color-secondary;
background: rgba(0, 0, 0, .04);
}
> svg {
position: absolute;
top: 50%;
left: 50%;
margin-top: -@font-size-sm / 2;
margin-top: -@font-size-sm / 2 + 1px;
margin-left: -@font-size-sm / 2;
}
}
.@{table-prefix-cls}-column-sorter + .@{iconfont-css-prefix}-filter {
margin-left: 4px;
}
.@{table-prefix-cls}-filter-selected.@{iconfont-css-prefix}-filter {
color: @primary-color;
}
&.@{table-prefix-cls}-column-has-filters {
.@{table-prefix-cls}-column-sorter {
position: absolute;
right: 8px;
top: 50%;
width: 14px;
height: @font-size-base;
margin-top: -@font-size-base / 2;
text-align: center;
color: @table-header-icon-color;
&-up,
&-down {
.iconfont-size-under-12px(8px);
line-height: 4px;
height: 4px;
transition: all .3s;
display: block;
}
&-down {
margin-top: 2px;
}
}
&.@{table-prefix-cls}-column-has-actions {
position: relative;
cursor: pointer;
// Very complicated styles logic but neccessary
&:hover {
background: #f5f5f5;
.@{iconfont-css-prefix}-filter,
.@{table-prefix-cls}-filter-icon {
background: #f5f5f5;
&:hover {
color: @text-color-secondary;
background: #ebebeb;
}
}
}
}
.@{table-prefix-cls}-column-sorters {
&:before {
position: absolute;
content: '';
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
transition: all .3s;
}
&:hover:before {
background: rgba(0, 0, 0, .04);
}
}
&.@{table-prefix-cls}-column-has-filters .@{table-prefix-cls}-column-sorter {
right: 28px + 8px;
}
}
@ -238,72 +287,6 @@
}
}
&-column-sorter {
position: relative;
margin-left: 8px;
display: inline-block;
vertical-align: text-bottom;
top: -1.5px;
width: 14px;
height: @font-size-base;
text-align: center;
font-weight: normal;
color: @table-header-icon-color;
&-up,
&-down {
display: block;
width: 14px;
height: @font-size-base / 2 - 1px;
line-height: @font-size-base / 2 - 1px;
cursor: pointer;
position: relative;
&:hover .@{iconfont-css-prefix} {
color: @primary-4;
}
&.on {
.@{iconfont-css-prefix}-caret-up,
.@{iconfont-css-prefix}-caret-down {
color: @primary-color;
}
}
&:after {
position: absolute;
content: '';
height: 30px;
width: 14px;
left: 0;
}
}
&-up:after {
bottom: 0;
}
&-down:after {
top: 0;
}
.@{iconfont-css-prefix}-caret-up,
.@{iconfont-css-prefix}-caret-down {
.iconfont-size-under-12px(8px);
line-height: 4px;
height: 4px;
transition: all .3s;
position: relative;
display: block;
}
&-down {
margin-top: 1.5px;
}
.@{iconfont-css-prefix}-caret-up {
margin-top: 0.5px;
}
}
&-bordered {
.@{table-prefix-cls}-header > table,
.@{table-prefix-cls}-body > table,