feat: more obviously tips for next sort (#21631)

This commit is contained in:
zefeng 2020-02-29 22:01:13 +08:00 committed by GitHub
parent c8c824c138
commit e262d14c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 122 additions and 25 deletions

View File

@ -22,6 +22,9 @@ export default {
sortTitle: 'Sort',
expand: 'Expand row',
collapse: 'Collapse row',
triggerDesc: 'Click sort by descend',
triggerAsc: 'Click sort by ascend',
cancelSort: 'Click to cancel sort',
},
Modal: {
okText: 'OK',

View File

@ -23,6 +23,9 @@ export default {
sortTitle: '排序',
expand: '展开行',
collapse: '关闭行',
triggerDesc: '点击降序',
triggerAsc: '点击升序',
cancelSort: '取消排序',
},
Modal: {
okText: '确定',

View File

@ -84,6 +84,7 @@ export interface TableProps<RecordType>
scrollToFirstRowOnChange?: boolean;
};
sortDirections?: SortOrder[];
showSorterTooltip?: boolean;
}
function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
@ -110,6 +111,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
scroll,
sortDirections,
locale,
showSorterTooltip = true,
} = props;
const size = React.useContext(SizeContext);
const { locale: contextLocale = defaultLocale, renderEmpty, direction } = React.useContext(
@ -208,12 +210,13 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
false,
);
};
const [transformSorterColumns, sortStates, sorterTitleProps, getSorters] = useSorter<RecordType>({
prefixCls,
columns: columns || [],
onSorterChange,
sortDirections: sortDirections || ['ascend', 'descend'],
tableLocale,
showSorterTooltip,
});
const sortedData = React.useMemo(() => getSortData(rawData, sortStates, childrenColumnName), [
rawData,

View File

@ -150,6 +150,45 @@ describe('Table.sorter', () => {
expect(sorter3.columnKey).toBe('name');
});
it('hover header show sorter tooltip', () => {
// tooltip has delay
jest.useFakeTimers();
const wrapper = mount(createTable({}));
// default show sorter tooltip
wrapper.find('.ant-table-column-sorters').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-open').length).toBeTruthy();
wrapper.find('.ant-table-column-sorters').simulate('mouseout');
// set table props showSorterTooltip is false
wrapper.setProps({ showSorterTooltip: false });
wrapper.find('.ant-table-column-sorters').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-open').length).toBeFalsy();
wrapper.find('.ant-table-column-sorters').simulate('mouseout');
// set table props showSorterTooltip is false, column showSorterTooltip is true
wrapper.setProps({
showSorterTooltip: false,
columns: [{ ...column, showSorterTooltip: true }],
});
wrapper.find('.ant-table-column-sorters').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-open').length).toBeTruthy();
wrapper.find('.ant-table-column-sorters').simulate('mouseout');
// set table props showSorterTooltip is true, column showSorterTooltip is false
wrapper.setProps({
showSorterTooltip: true,
columns: [{ ...column, showSorterTooltip: false }],
});
wrapper.find('.ant-table-column-sorters').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-open').length).toBeFalsy();
wrapper.find('.ant-table-column-sorters').simulate('mouseout');
});
it('works with grouping columns in controlled mode', () => {
const columns = [
{

View File

@ -10,9 +10,14 @@ import {
CompareFn,
ColumnTitleProps,
SorterResult,
TableLocale,
} from '../interface';
import Tooltip from '../../tooltip';
import { getColumnKey, getColumnPos, renderColumnTitle } from '../util';
const ASCEND = 'ascend';
const DESCEND = 'descend';
function getMultiplePriority<RecordType>(column: ColumnType<RecordType>): number | false {
if (typeof column.sorter === 'object' && typeof column.sorter.multiple === 'number') {
return column.sorter.multiple;
@ -89,6 +94,8 @@ function injectSorter<RecordType>(
sorterSates: SortState<RecordType>[],
triggerSorter: (sorterSates: SortState<RecordType>) => void,
defaultSortDirections: SortOrder[],
tableLocale?: TableLocale,
tableShowSorterTooltip?: boolean,
pos?: string,
): ColumnsType<RecordType> {
return (columns || []).map((column, index) => {
@ -97,53 +104,69 @@ function injectSorter<RecordType>(
if (newColumn.sorter) {
const sortDirections: SortOrder[] = newColumn.sortDirections || defaultSortDirections;
const showSorterTooltip =
newColumn.showSorterTooltip === undefined
? tableShowSorterTooltip
: newColumn.showSorterTooltip;
const columnKey = getColumnKey(newColumn, columnPos);
const sorterState = sorterSates.find(({ key }) => key === columnKey);
const sorterOrder = sorterState ? sorterState.sortOrder : null;
const upNode: React.ReactNode = sortDirections.includes('ascend') && (
const nextSortOrder = nextSortDirection(sortDirections, sorterOrder);
const upNode: React.ReactNode = sortDirections.includes(ASCEND) && (
<CaretUpOutlined
className={classNames(`${prefixCls}-column-sorter-up`, {
active: sorterOrder === 'ascend',
active: sorterOrder === ASCEND,
})}
/>
);
const downNode: React.ReactNode = sortDirections.includes('descend') && (
const downNode: React.ReactNode = sortDirections.includes(DESCEND) && (
<CaretDownOutlined
className={classNames(`${prefixCls}-column-sorter-down`, {
active: sorterOrder === 'descend',
active: sorterOrder === DESCEND,
})}
/>
);
const { cancelSort, triggerAsc, triggerDesc } = tableLocale || {};
let sortTip: string | undefined = cancelSort;
if (nextSortOrder === DESCEND) {
sortTip = triggerDesc;
} else if (nextSortOrder === ASCEND) {
sortTip = triggerAsc;
}
newColumn = {
...newColumn,
className: classNames(newColumn.className, { [`${prefixCls}-column-sort`]: sorterOrder }),
title: (renderProps: ColumnTitleProps<RecordType>) => (
<div className={`${prefixCls}-column-sorters`}>
<span>{renderColumnTitle(column.title, renderProps)}</span>
<span
className={classNames(`${prefixCls}-column-sorter`, {
[`${prefixCls}-column-sorter-full`]: upNode && downNode,
})}
>
<span className={`${prefixCls}-column-sorter-inner`}>
{upNode}
{downNode}
title: (renderProps: ColumnTitleProps<RecordType>) => {
const renderSortTitle = (
<div className={`${prefixCls}-column-sorters`}>
<span>{renderColumnTitle(column.title, renderProps)}</span>
<span
className={classNames(`${prefixCls}-column-sorter`, {
[`${prefixCls}-column-sorter-full`]: upNode && downNode,
})}
>
<span className={`${prefixCls}-column-sorter-inner`}>
{upNode}
{downNode}
</span>
</span>
</span>
</div>
),
</div>
);
return showSorterTooltip ? (
<Tooltip title={sortTip}>{renderSortTitle}</Tooltip>
) : (
renderSortTitle
);
},
onHeaderCell: col => {
const cell: React.HTMLAttributes<HTMLElement> =
(column.onHeaderCell && column.onHeaderCell(col)) || {};
const originOnClick = cell.onClick;
cell.onClick = (event: React.MouseEvent<HTMLElement>) => {
triggerSorter({
column,
key: columnKey,
sortOrder: nextSortDirection(sortDirections, sorterOrder),
sortOrder: nextSortOrder,
multiplePriority: getMultiplePriority(column),
});
@ -168,6 +191,8 @@ function injectSorter<RecordType>(
sorterSates,
triggerSorter,
defaultSortDirections,
tableLocale,
tableShowSorterTooltip,
columnPos,
),
};
@ -238,7 +263,7 @@ export function getSortData<RecordType>(
const compareResult = compareFn(record1, record2, sortOrder);
if (compareResult !== 0) {
return sortOrder === 'ascend' ? compareResult : -compareResult;
return sortOrder === ASCEND ? compareResult : -compareResult;
}
}
}
@ -265,6 +290,8 @@ interface SorterConfig<RecordType> {
sortStates: SortState<RecordType>[],
) => void;
sortDirections: SortOrder[];
tableLocale?: TableLocale;
showSorterTooltip?: boolean;
}
export default function useFilterSorter<RecordType>({
@ -272,6 +299,8 @@ export default function useFilterSorter<RecordType>({
columns,
onSorterChange,
sortDirections,
tableLocale,
showSorterTooltip,
}: SorterConfig<RecordType>): [
TransformColumns<RecordType>,
SortState<RecordType>[],
@ -363,7 +392,15 @@ export default function useFilterSorter<RecordType>({
}
const transformColumns = (innerColumns: ColumnsType<RecordType>) =>
injectSorter(prefixCls, innerColumns, mergedSorterStates, triggerSorter, sortDirections);
injectSorter(
prefixCls,
innerColumns,
mergedSorterStates,
triggerSorter,
sortDirections,
tableLocale,
showSorterTooltip,
);
const getSorters = () => {
return generateSorterInfo(mergedSorterStates);

View File

@ -82,6 +82,7 @@ const columns = [
| onRow | Set props on per row | Function(record, index) | - |
| getPopupContainer | the render container of dropdowns in table | (triggerNode) => HTMLElement | `() => TableHtmlElement` |
| sortDirections | supported sort way, could be `'ascend'`, `'descend'` | Array | `['ascend', 'descend']` |
| showSorterTooltip | header show next sorter direction tooltip | boolean | `true` |
#### onRow usage
@ -138,6 +139,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
| onFilter | Callback executed when the confirm filter button is clicked | Function | - |
| onFilterDropdownVisibleChange | Callback executed when `filterDropdownVisible` is changed | function(visible) {} | - |
| onHeaderCell | Set props on per header cell | Function(column) | - |
| showSorterTooltip | header show next sorter direction tooltip, override `showSorterTooltip` in table | boolean | `true` |
### ColumnGroup

View File

@ -87,6 +87,7 @@ const columns = [
| onRow | 设置行属性 | Function(record, index) | - |
| getPopupContainer | 设置表格内各类浮层的渲染节点,如筛选菜单 | (triggerNode) => HTMLElement | `() => TableHtmlElement` |
| sortDirections | 支持的排序方式,取值为 `'ascend'` `'descend'` | Array | `['ascend', 'descend']` |
| showSorterTooltip | 表头是否显示下一次排序的 tooltip 提示 | boolean | `true` |
#### onRow 用法
@ -143,6 +144,7 @@ const columns = [
| onFilter | 本地模式下,确定筛选的运行函数 | Function | - |
| onFilterDropdownVisibleChange | 自定义筛选菜单可见变化时调用 | function(visible) {} | - |
| onHeaderCell | 设置头部单元格属性 | Function(column) | - |
| showSorterTooltip | 表头显示下一次排序的 tooltip 提示, 覆盖 table 中`showSorterTooltip` | boolean | `true` |
### ColumnGroup

View File

@ -23,6 +23,9 @@ export interface TableLocale {
sortTitle?: string;
expand?: string;
collapse?: string;
triggerDesc?: string;
triggerAsc?: string;
cancelSort?: string;
}
export type SortOrder = 'descend' | 'ascend' | null;
@ -74,6 +77,7 @@ export interface ColumnType<RecordType> extends RcColumnType<RecordType> {
sortOrder?: SortOrder;
defaultSortOrder?: SortOrder;
sortDirections?: SortOrder[];
showSorterTooltip?: boolean;
// Filter
filters?: ColumnFilterItem[];

View File

@ -188,6 +188,7 @@
// ============================ Sorter ============================
thead th.@{table-prefix-cls}-column-has-sorters {
padding: 0;
cursor: pointer;
transition: all 0.3s;
@ -210,6 +211,8 @@
&-column-sorters {
display: inline-flex;
align-items: center;
width: 100%;
padding: @table-padding-vertical @table-padding-horizontal;
}
&-column-sorter {

View File

@ -9,3 +9,4 @@ import '../../checkbox/style';
import '../../dropdown/style';
import '../../spin/style';
import '../../pagination/style';
import '../../tooltip/style';