feat: implement sortIcon on Table (#42498)

* implement sortIcon on Table

* drop React.ReactNode from sortIcon

* add sortIcon test

* fix sortIcon arg type

* add sortIcon to docs

---------

Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
dyecma 2023-05-22 13:03:57 +09:00 committed by GitHub
parent a5069624bf
commit 8aca325d99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 28 deletions

View File

@ -355,6 +355,39 @@ describe('Table.sorter', () => {
expect(container.querySelector('.ant-tooltip-open')).toBeFalsy();
});
it('renders custome sort icon correctly', () => {
const sortIcon = ({ sorterOrder }: { sorterOrder?: SortOrder }): React.ReactNode => {
let text: string;
if (sorterOrder === undefined) {
text = 'unsorted';
} else if (sorterOrder === 'descend') {
text = 'sortDescend';
} else {
text = 'sortAscend';
}
return <span className="customize-icon">{text}</span>;
};
const { container } = render(
createTable({
columns: [
{
...column,
sortIcon,
},
],
}),
);
fireEvent.click(container.querySelector('.customize-icon')!);
expect(container.querySelector('.customize-icon')).toMatchSnapshot();
fireEvent.click(container.querySelector('.customize-icon')!);
expect(container.querySelector('.customize-icon')).toMatchSnapshot();
fireEvent.click(container.querySelector('.customize-icon')!);
expect(container.querySelector('.customize-icon')).toMatchSnapshot();
});
it('works with grouping columns in controlled mode', () => {
const columns = [
{

View File

@ -1,5 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Table.sorter renders custome sort icon correctly 1`] = `
<span
class="customize-icon"
>
sortAscend
</span>
`;
exports[`Table.sorter renders custome sort icon correctly 2`] = `
<span
class="customize-icon"
>
sortDescend
</span>
`;
exports[`Table.sorter renders custome sort icon correctly 3`] = `
<span
class="customize-icon"
>
unsorted
</span>
`;
exports[`Table.sorter renders sorter icon correctly 1`] = `
<thead
class="ant-table-thead"

View File

@ -127,20 +127,39 @@ function injectSorter<RecordType>(
const sorterState = sorterStates.find(({ key }) => key === columnKey);
const sorterOrder = sorterState ? sorterState.sortOrder : null;
const nextSortOrder = nextSortDirection(sortDirections, sorterOrder);
const upNode: React.ReactNode = sortDirections.includes(ASCEND) && (
<CaretUpOutlined
className={classNames(`${prefixCls}-column-sorter-up`, {
active: sorterOrder === ASCEND,
})}
/>
);
const downNode: React.ReactNode = sortDirections.includes(DESCEND) && (
<CaretDownOutlined
className={classNames(`${prefixCls}-column-sorter-down`, {
active: sorterOrder === DESCEND,
})}
/>
);
let sorter: React.ReactNode;
if (column.sortIcon) {
sorter = column.sortIcon({ sorterOrder });
} else {
const upNode: React.ReactNode = sortDirections.includes(ASCEND) && (
<CaretUpOutlined
className={classNames(`${prefixCls}-column-sorter-up`, {
active: sorterOrder === ASCEND,
})}
/>
);
const downNode: React.ReactNode = sortDirections.includes(DESCEND) && (
<CaretDownOutlined
className={classNames(`${prefixCls}-column-sorter-down`, {
active: sorterOrder === DESCEND,
})}
/>
);
sorter = (
<span
className={classNames(`${prefixCls}-column-sorter`, {
[`${prefixCls}-column-sorter-full`]: !!(upNode && downNode),
})}
>
<span className={`${prefixCls}-column-sorter-inner`} aria-hidden="true">
{upNode}
{downNode}
</span>
</span>
);
}
const { cancelSort, triggerAsc, triggerDesc } = tableLocale || {};
let sortTip: string | undefined = cancelSort;
if (nextSortOrder === DESCEND) {
@ -159,16 +178,7 @@ function injectSorter<RecordType>(
<span className={`${prefixCls}-column-title`}>
{renderColumnTitle(column.title, renderProps)}
</span>
<span
className={classNames(`${prefixCls}-column-sorter`, {
[`${prefixCls}-column-sorter-full`]: !!(upNode && downNode),
})}
>
<span className={`${prefixCls}-column-sorter-inner`} aria-hidden="true">
{upNode}
{downNode}
</span>
</span>
{sorter}
</div>
);
return showSorterTooltip ? (

View File

@ -194,6 +194,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
| 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 you need sort buttons only, set to `true` | function \| boolean | - | |
| sortOrder | Order of sorted values: `ascend` `descend` `null` | `ascend` \| `descend` \| null | - | |
| sortIcon | Customized sort icon | (props: { sorterOrder }) => ReactNode | - | |
| title | Title of this column | ReactNode \| ({ sortOrder, sortColumn, filters }) => ReactNode | - | |
| width | Width of this column ([width not working?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241)) | string \| number | - | |
| onCell | Set props on per cell | function(record, rowIndex) | - | |

View File

@ -196,6 +196,7 @@ const columns = [
| 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 | function \| boolean | - | |
| sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 `ascend` `descend` `null` | `ascend` \| `descend` \| null | - | |
| sortIcon | 自定义 sort 图标。 | (props: { sorterOrder }) => ReactNode | - | |
| title | 列头显示文字(函数用法 `3.10.0` 后支持) | ReactNode \| ({ sortOrder, sortColumn, filters }) => ReactNode | - | |
| width | 列宽度([指定了也不生效?](https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241) | string \| number | - | |
| onCell | 设置单元格属性 | function(record, rowIndex) | - | |

View File

@ -1,17 +1,17 @@
import type {
ColumnType as RcColumnType,
FixedType,
GetComponentProps,
ColumnType as RcColumnType,
RenderedCell as RcRenderedCell,
} from 'rc-table/lib/interface';
import { ExpandableConfig, GetRowKey } from 'rc-table/lib/interface';
import type * as React from 'react';
import type { Breakpoint } from '../_util/responsiveObserver';
import type { CheckboxProps } from '../checkbox';
import type { PaginationProps } from '../pagination';
import type { TooltipProps } from '../tooltip';
import type { Breakpoint } from '../_util/responsiveObserver';
import type { INTERNAL_SELECTION_ITEM } from './hooks/useSelection';
import type { InternalTableProps, TableProps } from './InternalTable';
import type { INTERNAL_SELECTION_ITEM } from './hooks/useSelection';
export type RefTable = <RecordType extends object = any>(
props: React.PropsWithChildren<TableProps<RecordType>> & { ref?: React.Ref<HTMLDivElement> },
@ -56,7 +56,7 @@ export interface TableLocale {
export type SortOrder = 'descend' | 'ascend' | null;
const TableActions = ['paginate', 'sort', 'filter'] as const;
export type TableAction = typeof TableActions[number];
export type TableAction = (typeof TableActions)[number];
export type CompareFn<T> = (a: T, b: T, sortOrder?: SortOrder) => number;
@ -119,6 +119,7 @@ export interface ColumnType<RecordType> extends Omit<RcColumnType<RecordType>, '
sortOrder?: SortOrder;
defaultSortOrder?: SortOrder;
sortDirections?: SortOrder[];
sortIcon?: (props: { sorterOrder: SortOrder }) => React.ReactNode;
showSorterTooltip?: boolean | TooltipProps;
// Filter