mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-18 11:18:14 +08:00
feat: support showSorterTooltip.target
for Table sorters (#47409)
* Added `sorterTooltipTarget` prop for table sorters * demo updated * updated snapshot * updated snapshot * moved table tooltip target to `showSorterTooltip` * fix * updated docs * empty commit * updated version in docs --------- Co-authored-by: Alina Andrieieva <Alina_Andrieieva@epam.com>
This commit is contained in:
parent
dfd342d985
commit
1bd8fbc5f3
@ -25,7 +25,6 @@ import Pagination from '../pagination';
|
||||
import type { SpinProps } from '../spin';
|
||||
import Spin from '../spin';
|
||||
import { useToken } from '../theme/internal';
|
||||
import type { TooltipProps } from '../tooltip';
|
||||
import renderExpandIcon from './ExpandIcon';
|
||||
import useContainerWidth from './hooks/useContainerWidth';
|
||||
import type { FilterState } from './hooks/useFilter';
|
||||
@ -47,6 +46,7 @@ import type {
|
||||
GetRowKey,
|
||||
RefInternalTable,
|
||||
SorterResult,
|
||||
SorterTooltipProps,
|
||||
SortOrder,
|
||||
TableAction,
|
||||
TableCurrentDataSource,
|
||||
@ -116,7 +116,7 @@ export interface TableProps<RecordType = any>
|
||||
scrollToFirstRowOnChange?: boolean;
|
||||
};
|
||||
sortDirections?: SortOrder[];
|
||||
showSorterTooltip?: boolean | TooltipProps;
|
||||
showSorterTooltip?: boolean | SorterTooltipProps;
|
||||
virtual?: boolean;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ const InternalTable = <RecordType extends AnyObject = AnyObject>(
|
||||
scroll,
|
||||
sortDirections,
|
||||
locale,
|
||||
showSorterTooltip = true,
|
||||
showSorterTooltip = { target: 'full-header' },
|
||||
virtual,
|
||||
} = props;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React from 'react';
|
||||
|
||||
import type { ColumnType, TableProps } from '..';
|
||||
import Table from '..';
|
||||
import { act, fireEvent, render } from '../../../tests/utils';
|
||||
@ -283,7 +284,7 @@ describe('Table.sorter', () => {
|
||||
|
||||
// set table props showSorterTooltip is false, column showSorterTooltip is true
|
||||
rerender(
|
||||
createTable({ showSorterTooltip: true, columns: [{ ...column, showSorterTooltip: true }] }),
|
||||
createTable({ showSorterTooltip: false, columns: [{ ...column, showSorterTooltip: true }] }),
|
||||
);
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorters')!);
|
||||
act(() => {
|
||||
@ -305,6 +306,96 @@ describe('Table.sorter', () => {
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeFalsy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorters')!);
|
||||
|
||||
// table props showSorterTooltip is 'full-header' by default
|
||||
rerender(
|
||||
createTable({
|
||||
showSorterTooltip: true,
|
||||
columns: [{ ...column }],
|
||||
}),
|
||||
);
|
||||
expect(container.querySelector('.ant-table-column-sorters')).not.toHaveClass(
|
||||
'ant-table-column-sorters-tooltip-target-sorter',
|
||||
);
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorters')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeTruthy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorters')!);
|
||||
|
||||
// set table props showSorterTooltip target is 'sorter-icon'
|
||||
rerender(
|
||||
createTable({
|
||||
showSorterTooltip: { target: 'sorter-icon' },
|
||||
columns: [{ ...column }],
|
||||
}),
|
||||
);
|
||||
expect(container.querySelector('.ant-table-column-sorters')).toHaveClass(
|
||||
'ant-table-column-sorters-tooltip-target-sorter',
|
||||
);
|
||||
// hovering over the sorters element does NOT open tooltip
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorters')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeFalsy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorters')!);
|
||||
// hovering over the sorter element DOES open tooltip
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorter')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeTruthy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorter')!);
|
||||
|
||||
// set table props showSorterTooltip target is 'sorter-icon', column showSorterTooltip target is 'full-header'
|
||||
rerender(
|
||||
createTable({
|
||||
showSorterTooltip: { target: 'sorter-icon' },
|
||||
columns: [{ ...column, showSorterTooltip: { target: 'full-header' } }],
|
||||
}),
|
||||
);
|
||||
expect(container.querySelector('.ant-table-column-sorters')).not.toHaveClass(
|
||||
'ant-table-column-sorters-tooltip-target-sorter',
|
||||
);
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorters')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeTruthy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorters')!);
|
||||
|
||||
// set table props showSorterTooltip target is 'full-header', column showSorterTooltip target is 'sorter-icon'
|
||||
rerender(
|
||||
createTable({
|
||||
showSorterTooltip: { target: 'full-header' },
|
||||
columns: [{ ...column, showSorterTooltip: { target: 'sorter-icon' } }],
|
||||
}),
|
||||
);
|
||||
expect(container.querySelector('.ant-table-column-sorters')).toHaveClass(
|
||||
'ant-table-column-sorters-tooltip-target-sorter',
|
||||
);
|
||||
// hovering over the sorters element does NOT open tooltip
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorters')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeFalsy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorters')!);
|
||||
// hovering over the title element does NOT open tooltip
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-title')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeFalsy();
|
||||
// hovering over the sorter element DOES open tooltip
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-table-column-sorter')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelector('.ant-tooltip-open')).toBeTruthy();
|
||||
fireEvent.mouseOut(container.querySelector('.ant-table-column-sorter')!);
|
||||
});
|
||||
|
||||
it('should show correct tooltip when showSorterTooltip is an object', () => {
|
||||
|
@ -16446,7 +16446,7 @@ exports[`renders components/table/demo/head.tsx extend context correctly 1`] = `
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
class="ant-table-column-sorters ant-table-column-sorters-tooltip-target-sorter"
|
||||
>
|
||||
<span
|
||||
class="ant-table-column-title"
|
||||
@ -16500,23 +16500,23 @@ exports[`renders components/table/demo/head.tsx extend context correctly 1`] = `
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-tooltip-placement-top"
|
||||
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
|
||||
>
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
class="ant-tooltip-arrow"
|
||||
style="position: absolute; bottom: 0px; left: 0px;"
|
||||
/>
|
||||
<div
|
||||
class="ant-tooltip-content"
|
||||
>
|
||||
Click to cancel sorting
|
||||
<div
|
||||
class="ant-tooltip-inner"
|
||||
role="tooltip"
|
||||
>
|
||||
Click to cancel sorting
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13204,7 +13204,7 @@ exports[`renders components/table/demo/head.tsx correctly 1`] = `
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
class="ant-table-column-sorters ant-table-column-sorters-tooltip-target-sorter"
|
||||
>
|
||||
<span
|
||||
class="ant-table-column-title"
|
||||
|
@ -13,6 +13,7 @@ const columns: TableColumnsType<DataType> = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
showSorterTooltip: { target: 'full-header' },
|
||||
filters: [
|
||||
{
|
||||
text: 'Joe',
|
||||
@ -97,6 +98,13 @@ const onChange: TableProps<DataType>['onChange'] = (pagination, filters, sorter,
|
||||
console.log('params', pagination, filters, sorter, extra);
|
||||
};
|
||||
|
||||
const App: React.FC = () => <Table columns={columns} dataSource={data} onChange={onChange} />;
|
||||
const App: React.FC = () => (
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
onChange={onChange}
|
||||
showSorterTooltip={{ target: 'sorter-icon' }}
|
||||
/>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import CaretDownOutlined from '@ant-design/icons/CaretDownOutlined';
|
||||
import CaretUpOutlined from '@ant-design/icons/CaretUpOutlined';
|
||||
import classNames from 'classnames';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import * as React from 'react';
|
||||
|
||||
import type { TooltipProps } from '../../tooltip';
|
||||
import Tooltip from '../../tooltip';
|
||||
import type {
|
||||
@ -13,6 +14,7 @@ import type {
|
||||
CompareFn,
|
||||
Key,
|
||||
SorterResult,
|
||||
SorterTooltipProps,
|
||||
SortOrder,
|
||||
TableLocale,
|
||||
TransformColumns,
|
||||
@ -110,7 +112,7 @@ function injectSorter<RecordType>(
|
||||
triggerSorter: (sorterSates: SortState<RecordType>) => void,
|
||||
defaultSortDirections: SortOrder[],
|
||||
tableLocale?: TableLocale,
|
||||
tableShowSorterTooltip?: boolean | TooltipProps,
|
||||
tableShowSorterTooltip?: boolean | SorterTooltipProps,
|
||||
pos?: string,
|
||||
): ColumnsType<RecordType> {
|
||||
return (columns || []).map((column, index) => {
|
||||
@ -123,6 +125,7 @@ function injectSorter<RecordType>(
|
||||
newColumn.showSorterTooltip === undefined
|
||||
? tableShowSorterTooltip
|
||||
: newColumn.showSorterTooltip;
|
||||
|
||||
const columnKey = getColumnKey(newColumn, columnPos);
|
||||
const sorterState = sorterStates.find(({ key }) => key === columnKey);
|
||||
const sortOrder = sorterState ? sorterState.sortOrder : null;
|
||||
@ -178,19 +181,35 @@ function injectSorter<RecordType>(
|
||||
...newColumn,
|
||||
className: classNames(newColumn.className, { [`${prefixCls}-column-sort`]: sortOrder }),
|
||||
title: (renderProps: ColumnTitleProps<RecordType>) => {
|
||||
const columnSortersClass = `${prefixCls}-column-sorters`;
|
||||
const renderColumnTitleWrapper = (
|
||||
<span className={`${prefixCls}-column-title`}>
|
||||
{renderColumnTitle(column.title, renderProps)}
|
||||
</span>
|
||||
);
|
||||
const renderSortTitle = (
|
||||
<div className={`${prefixCls}-column-sorters`}>
|
||||
<span className={`${prefixCls}-column-title`}>
|
||||
{renderColumnTitle(column.title, renderProps)}
|
||||
</span>
|
||||
<div className={columnSortersClass}>
|
||||
{renderColumnTitleWrapper}
|
||||
{sorter}
|
||||
</div>
|
||||
);
|
||||
return showSorterTooltip ? (
|
||||
<Tooltip {...tooltipProps}>{renderSortTitle}</Tooltip>
|
||||
) : (
|
||||
renderSortTitle
|
||||
);
|
||||
if (showSorterTooltip) {
|
||||
if (
|
||||
typeof showSorterTooltip !== 'boolean' &&
|
||||
showSorterTooltip?.target === 'sorter-icon'
|
||||
) {
|
||||
return (
|
||||
<div
|
||||
className={`${columnSortersClass} ${prefixCls}-column-sorters-tooltip-target-sorter`}
|
||||
>
|
||||
{renderColumnTitleWrapper}
|
||||
<Tooltip {...tooltipProps}>{sorter}</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <Tooltip {...tooltipProps}>{renderSortTitle}</Tooltip>;
|
||||
}
|
||||
return renderSortTitle;
|
||||
},
|
||||
onHeaderCell: (col) => {
|
||||
const cell: React.HTMLAttributes<HTMLElement> =
|
||||
@ -346,7 +365,7 @@ interface SorterConfig<RecordType> {
|
||||
) => void;
|
||||
sortDirections: SortOrder[];
|
||||
tableLocale?: TableLocale;
|
||||
showSorterTooltip?: boolean | TooltipProps;
|
||||
showSorterTooltip?: boolean | SorterTooltipProps;
|
||||
}
|
||||
|
||||
export default function useFilterSorter<RecordType>({
|
||||
|
@ -132,7 +132,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| rowSelection | Row selection [config](#rowselection) | object | - | |
|
||||
| scroll | Whether the table can be scrollable, [config](#scroll) | object | - | |
|
||||
| showHeader | Whether to show table header | boolean | true | |
|
||||
| showSorterTooltip | The header show next sorter direction tooltip. It will be set as the property of Tooltip if its type is object | boolean \| [Tooltip props](/components/tooltip/#api) | true | |
|
||||
| showSorterTooltip | The header show next sorter direction tooltip. It will be set as the property of Tooltip if its type is object | boolean \| [Tooltip props](/components/tooltip/#api) & `{target?: 'full-header' \| 'sorter-icon' }` | { target: 'full-header' } | 5.16.0 |
|
||||
| size | Size of table | `large` \| `middle` \| `small` | `large` | |
|
||||
| sortDirections | Supported sort way, could be `ascend`, `descend` | Array | \[`ascend`, `descend`] | |
|
||||
| sticky | Set sticky header and scroll bar | boolean \| `{offsetHeader?: number, offsetScroll?: number, getContainer?: () => HTMLElement}` | - | 4.6.0 (getContainer: 4.7.0) |
|
||||
@ -204,7 +204,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
|
||||
| responsive | The list of breakpoints at which to display this column. Always visible if not set | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
|
||||
| rowScope | Set scope attribute for all cells in this column | `row` \| `rowgroup` | - | 5.1.0 |
|
||||
| shouldCellUpdate | Control cell render logic | (record, prevRecord) => boolean | - | 4.3.0 |
|
||||
| showSorterTooltip | If header show next sorter direction tooltip, override `showSorterTooltip` in table | boolean \| [Tooltip props](/components/tooltip/) | true | |
|
||||
| showSorterTooltip | If header show next sorter direction tooltip, override `showSorterTooltip` in table | boolean \| [Tooltip props](/components/tooltip/) & `{target?: 'full-header' \| 'sorter-icon' }` | { target: 'full-header' } | 5.16.0 |
|
||||
| sortDirections | Supported sort way, override `sortDirections` in `Table`, could be `ascend`, `descend` | Array | \[`ascend`, `descend`] | |
|
||||
| sorter | Sort function for local sort, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction. If it is server-side sorting, set to `true`, but if you want to support multi-column sorting, you can set it to `{ multiple: number }` | function \| boolean \| { compare: function, multiple: number } | - | |
|
||||
| sortOrder | Order of sorted values: `ascend` `descend` `null` | `ascend` \| `descend` \| null | - | |
|
||||
|
@ -133,7 +133,7 @@ const columns = [
|
||||
| rowSelection | 表格行是否可选择,[配置项](#rowselection) | object | - | |
|
||||
| scroll | 表格是否可滚动,也可以指定滚动区域的宽、高,[配置项](#scroll) | object | - | |
|
||||
| showHeader | 是否显示表头 | boolean | true | |
|
||||
| showSorterTooltip | 表头是否显示下一次排序的 tooltip 提示。当参数类型为对象时,将被设置为 Tooltip 的属性 | boolean \| [Tooltip props](/components/tooltip-cn) | true | |
|
||||
| showSorterTooltip | 表头是否显示下一次排序的 tooltip 提示。当参数类型为对象时,将被设置为 Tooltip 的属性 | boolean \| [Tooltip props](/components/tooltip-cn) & `{target?: 'full-header' \| 'sorter-icon' }` | { target: 'full-header' } | 5.16.0 |
|
||||
| size | 表格大小 | `large` \| `middle` \| `small` | `large` | |
|
||||
| sortDirections | 支持的排序方式,取值为 `ascend` `descend` | Array | \[`ascend`, `descend`] | |
|
||||
| sticky | 设置粘性头部和滚动条 | boolean \| `{offsetHeader?: number, offsetScroll?: number, getContainer?: () => HTMLElement}` | - | 4.6.0 (getContainer: 4.7.0) |
|
||||
@ -205,7 +205,7 @@ const columns = [
|
||||
| responsive | 响应式 breakpoint 配置列表。未设置则始终可见。 | [Breakpoint](https://github.com/ant-design/ant-design/blob/015109b42b85c63146371b4e32b883cf97b088e8/components/_util/responsiveObserve.ts#L1)\[] | - | 4.2.0 |
|
||||
| rowScope | 设置列范围 | `row` \| `rowgroup` | - | 5.1.0 |
|
||||
| shouldCellUpdate | 自定义单元格渲染时机 | (record, prevRecord) => boolean | - | 4.3.0 |
|
||||
| showSorterTooltip | 表头显示下一次排序的 tooltip 提示, 覆盖 table 中 `showSorterTooltip` | boolean \| [Tooltip props](/components/tooltip-cn/#api) | true | |
|
||||
| showSorterTooltip | 表头显示下一次排序的 tooltip 提示, 覆盖 table 中 `showSorterTooltip` | boolean \| [Tooltip props](/components/tooltip-cn/#api) & `{target?: 'full-header' \| 'sorter-icon' }` | { target: 'full-header' } | 5.16.0 |
|
||||
| sortDirections | 支持的排序方式,覆盖 `Table` 中 `sortDirections`, 取值为 `ascend` `descend` | Array | \[`ascend`, `descend`] | |
|
||||
| sorter | 排序函数,本地排序使用一个函数(参考 [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的 compareFunction)。需要服务端排序可设为 `true`(单列排序) 或 `{ multiple: number }`(多列排序) | function \| boolean \| { compare: function, multiple: number } | - | |
|
||||
| sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `ascend` `descend` `null` | `ascend` \| `descend` \| null | - | |
|
||||
|
@ -58,6 +58,12 @@ export interface TableLocale {
|
||||
|
||||
export type SortOrder = 'descend' | 'ascend' | null;
|
||||
|
||||
export type SorterTooltipTarget = 'full-header' | 'sorter-icon';
|
||||
|
||||
export type SorterTooltipProps = TooltipProps & {
|
||||
target?: SorterTooltipTarget;
|
||||
};
|
||||
|
||||
const TableActions = ['paginate', 'sort', 'filter'] as const;
|
||||
export type TableAction = (typeof TableActions)[number];
|
||||
|
||||
@ -123,7 +129,7 @@ export interface ColumnType<RecordType> extends Omit<RcColumnType<RecordType>, '
|
||||
defaultSortOrder?: SortOrder;
|
||||
sortDirections?: SortOrder[];
|
||||
sortIcon?: (props: { sortOrder: SortOrder }) => React.ReactNode;
|
||||
showSorterTooltip?: boolean | TooltipProps;
|
||||
showSorterTooltip?: boolean | SorterTooltipProps;
|
||||
|
||||
// Filter
|
||||
filtered?: boolean;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
import type { TableToken } from './index';
|
||||
|
||||
@ -65,6 +66,12 @@ const genSorterStyle: GenerateStyle<TableToken, CSSObject> = (token) => {
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-column-sorters-tooltip-target-sorter`]: {
|
||||
'&::after': {
|
||||
content: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-column-sorter`]: {
|
||||
marginInlineStart: marginXXS,
|
||||
color: headerIconColor,
|
||||
|
Loading…
Reference in New Issue
Block a user