listLink.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // eslint-disable-next-line no-restricted-imports
  2. import {Link as RouterLink, withRouter, WithRouterProps} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import classNames from 'classnames';
  5. import {LocationDescriptor} from 'history';
  6. import * as qs from 'query-string';
  7. type LinkProps = Omit<React.ComponentProps<typeof RouterLink>, 'to'>;
  8. type Props = WithRouterProps &
  9. LinkProps & {
  10. /**
  11. * Link target. We don't want to expose the ToLocationFunction on this component.
  12. */
  13. to: LocationDescriptor;
  14. /**
  15. * The class to apply when the link is 'active'
  16. */
  17. activeClassName?: string;
  18. disabled?: boolean;
  19. index?: boolean;
  20. /**
  21. * Should be should be supplied by the parent component
  22. */
  23. isActive?: (location: LocationDescriptor, indexOnly?: boolean) => boolean;
  24. query?: string;
  25. };
  26. function ListLink({
  27. children,
  28. className,
  29. isActive,
  30. query,
  31. router,
  32. to,
  33. activeClassName = 'active',
  34. index = false,
  35. disabled = false,
  36. ...props
  37. }: Props) {
  38. const queryData = query ? qs.parse(query) : undefined;
  39. const target: LocationDescriptor =
  40. typeof to === 'string' ? {pathname: to, query: queryData} : to;
  41. const active = isActive?.(target, index) ?? router.isActive(target, index);
  42. return (
  43. <StyledLi
  44. className={classNames({[activeClassName]: active}, className)}
  45. disabled={disabled}
  46. >
  47. <RouterLink {...props} onlyActiveOnIndex={index} to={disabled ? '' : to}>
  48. {children}
  49. </RouterLink>
  50. </StyledLi>
  51. );
  52. }
  53. export default withRouter(ListLink);
  54. const StyledLi = styled('li', {
  55. shouldForwardProp: prop => prop !== 'disabled',
  56. })<{disabled?: boolean}>`
  57. ${p =>
  58. p.disabled &&
  59. `
  60. a {
  61. color:${p.theme.disabled} !important;
  62. pointer-events: none;
  63. :hover {
  64. color: ${p.theme.disabled} !important;
  65. }
  66. }
  67. `}
  68. `;