sortLink.tsx 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import {browserHistory} from 'react-router';
  2. import styled from '@emotion/styled';
  3. import {LocationDescriptorObject} from 'history';
  4. import omit from 'lodash/omit';
  5. import Link from 'sentry/components/links/link';
  6. import {IconArrow} from 'sentry/icons';
  7. export type Alignments = 'left' | 'right' | undefined;
  8. export type Directions = 'desc' | 'asc' | undefined;
  9. type Props = {
  10. align: Alignments;
  11. canSort: boolean;
  12. direction: Directions;
  13. generateSortLink: () => LocationDescriptorObject | undefined;
  14. title: React.ReactNode;
  15. onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
  16. replace?: boolean;
  17. };
  18. function SortLink({
  19. align,
  20. title,
  21. canSort,
  22. generateSortLink,
  23. onClick,
  24. direction,
  25. replace,
  26. }: Props) {
  27. const target = generateSortLink();
  28. if (!target || !canSort) {
  29. return <StyledNonLink align={align}>{title}</StyledNonLink>;
  30. }
  31. const arrow = !direction ? null : (
  32. <StyledIconArrow size="xs" direction={direction === 'desc' ? 'down' : 'up'} />
  33. );
  34. const handleOnClick: React.MouseEventHandler<HTMLAnchorElement> = e => {
  35. if (replace) {
  36. e.preventDefault();
  37. browserHistory.replace(target);
  38. }
  39. onClick?.(e);
  40. };
  41. return (
  42. <StyledLink align={align} to={target} onClick={handleOnClick}>
  43. {title} {arrow}
  44. </StyledLink>
  45. );
  46. }
  47. type LinkProps = React.ComponentPropsWithoutRef<typeof Link>;
  48. type StyledLinkProps = LinkProps & {align: Alignments};
  49. const StyledLink = styled((props: StyledLinkProps) => {
  50. const forwardProps = omit(props, ['align', 'css']);
  51. return <Link {...forwardProps} />;
  52. })`
  53. display: block;
  54. width: 100%;
  55. white-space: nowrap;
  56. color: inherit;
  57. &:hover,
  58. &:active,
  59. &:focus,
  60. &:visited {
  61. color: inherit;
  62. }
  63. ${(p: StyledLinkProps) => (p.align ? `text-align: ${p.align};` : '')}
  64. `;
  65. const StyledNonLink = styled('div')<{align: Alignments}>`
  66. display: block;
  67. width: 100%;
  68. white-space: nowrap;
  69. ${(p: {align: Alignments}) => (p.align ? `text-align: ${p.align};` : '')}
  70. `;
  71. const StyledIconArrow = styled(IconArrow)`
  72. vertical-align: top;
  73. `;
  74. export default SortLink;