mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-18 11:18:14 +08:00
feat: more obviously tips for next sort (#21631)
This commit is contained in:
parent
c8c824c138
commit
e262d14c2b
@ -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',
|
||||
|
@ -23,6 +23,9 @@ export default {
|
||||
sortTitle: '排序',
|
||||
expand: '展开行',
|
||||
collapse: '关闭行',
|
||||
triggerDesc: '点击降序',
|
||||
triggerAsc: '点击升序',
|
||||
cancelSort: '取消排序',
|
||||
},
|
||||
Modal: {
|
||||
okText: '确定',
|
||||
|
@ -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,
|
||||
|
@ -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 = [
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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[];
|
||||
|
@ -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 {
|
||||
|
@ -9,3 +9,4 @@ import '../../checkbox/style';
|
||||
import '../../dropdown/style';
|
||||
import '../../spin/style';
|
||||
import '../../pagination/style';
|
||||
import '../../tooltip/style';
|
||||
|
Loading…
Reference in New Issue
Block a user