ColumnSorter.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import React, { PureComponent } from 'react';
  2. import PropTypes from 'prop-types';
  3. import cls from 'classnames';
  4. import { noop } from 'lodash';
  5. import { IconCaretup, IconCaretdown } from '@douyinfe/semi-icons';
  6. import { cssClasses, strings } from '@douyinfe/semi-foundation/table/constants';
  7. import { SortOrder } from './interface';
  8. import isEnterPress from '@douyinfe/semi-foundation/utils/isEnterPress';
  9. export interface ColumnSorterProps {
  10. className?: string;
  11. style?: React.CSSProperties;
  12. onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
  13. prefixCls?: string;
  14. sortOrder?: SortOrder;
  15. title?: React.ReactNode
  16. }
  17. export default class ColumnSorter extends PureComponent<ColumnSorterProps> {
  18. static propTypes = {
  19. className: PropTypes.string,
  20. style: PropTypes.object,
  21. onClick: PropTypes.func,
  22. prefixCls: PropTypes.string,
  23. sortOrder: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  24. };
  25. static defaultProps = {
  26. prefixCls: cssClasses.PREFIX,
  27. onClick: noop,
  28. sortOrder: false,
  29. };
  30. render() {
  31. const { prefixCls, onClick, sortOrder, style, title } = this.props;
  32. const iconBtnSize = 'default';
  33. const upCls = cls(`${prefixCls}-column-sorter-up`, {
  34. on: sortOrder === strings.SORT_DIRECTIONS[0],
  35. });
  36. const downCls = cls(`${prefixCls}-column-sorter-down`, {
  37. on: sortOrder === strings.SORT_DIRECTIONS[1],
  38. });
  39. const ariaProps = {
  40. /**
  41. * Set 'aria-sort' to aria-columnheader is difficult, so set 'aria-label' about sort info to sorter
  42. * reference: https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaSort
  43. */
  44. 'aria-label': `Current sort order is ${sortOrder ? `${sortOrder}ing` : 'none'}`,
  45. 'aria-roledescription': 'Sort data with this column',
  46. };
  47. return (
  48. <div
  49. role='button'
  50. {...ariaProps}
  51. tabIndex={-1}
  52. className={`${prefixCls}-column-sorter-wrapper`}
  53. onClick={onClick}
  54. onKeyPress={e => isEnterPress(e) && onClick(e as any)}
  55. >
  56. {title}
  57. <div
  58. style={style}
  59. className={`${prefixCls}-column-sorter`}
  60. >
  61. <span className={`${upCls}`}>
  62. <IconCaretup size={iconBtnSize} />
  63. </span>
  64. <span className={`${downCls}`}>
  65. <IconCaretdown size={iconBtnSize} />
  66. </span>
  67. </div>
  68. </div>
  69. );
  70. }
  71. }