ColumnSorter.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. }
  16. export default class ColumnSorter extends PureComponent<ColumnSorterProps> {
  17. static propTypes = {
  18. className: PropTypes.string,
  19. style: PropTypes.object,
  20. onClick: PropTypes.func,
  21. prefixCls: PropTypes.string,
  22. sortOrder: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
  23. };
  24. static defaultProps = {
  25. prefixCls: cssClasses.PREFIX,
  26. onClick: noop,
  27. sortOrder: false,
  28. };
  29. render() {
  30. const { prefixCls, onClick, sortOrder, style } = this.props;
  31. const iconBtnSize = 'small';
  32. const upCls = cls(`${prefixCls}-column-sorter-up`, {
  33. on: sortOrder === strings.SORT_DIRECTIONS[0],
  34. });
  35. const downCls = cls(`${prefixCls}-column-sorter-down`, {
  36. on: sortOrder === strings.SORT_DIRECTIONS[1],
  37. });
  38. const ariaProps = {
  39. /**
  40. * Set 'aria-sort' to aria-columnheader is difficult, so set 'aria-label' about sort info to sorter
  41. * reference: https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaSort
  42. */
  43. 'aria-label': `Current sort order is ${sortOrder ? `${sortOrder}ing` : 'none'}`,
  44. 'aria-roledescription': 'Sort data with this column',
  45. };
  46. return (
  47. <div
  48. role='button'
  49. {...ariaProps}
  50. tabIndex={-1}
  51. style={style}
  52. className={`${prefixCls}-column-sorter`}
  53. onClick={onClick}
  54. onKeyPress={e => isEnterPress(e) && onClick(e as any)}
  55. >
  56. <span className={`${upCls}`}>
  57. <IconCaretup size={iconBtnSize} />
  58. </span>
  59. <span className={`${downCls}`}>
  60. <IconCaretdown size={iconBtnSize} />
  61. </span>
  62. </div>
  63. );
  64. }
  65. }