sortLink.tsx 1.8 KB

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