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

View File

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

View File

@ -47,37 +47,86 @@
cursor: pointer; cursor: pointer;
color: @table-header-icon-color; color: @table-header-icon-color;
transition: all .3s; transition: all .3s;
width: 24px; width: 28px;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
height: 100%; height: 100%;
text-align: center; text-align: center;
&:hover {
color: @text-color-secondary;
background: rgba(0, 0, 0, .04);
}
> svg { > svg {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
margin-top: -@font-size-sm / 2; margin-top: -@font-size-sm / 2 + 1px;
margin-left: -@font-size-sm / 2; 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 { .@{table-prefix-cls}-filter-selected.@{iconfont-css-prefix}-filter {
color: @primary-color; 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; 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 { &-bordered {
.@{table-prefix-cls}-header > table, .@{table-prefix-cls}-header > table,
.@{table-prefix-cls}-body > table, .@{table-prefix-cls}-body > table,