groupPreviewHovercard.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import {ComponentProps, Fragment, useCallback} from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import {Hovercard} from 'sentry/components/hovercard';
  5. import theme from 'sentry/utils/theme';
  6. import useMedia from 'sentry/utils/useMedia';
  7. interface GroupPreviewHovercardProps extends ComponentProps<typeof Hovercard> {
  8. hide?: boolean;
  9. }
  10. export const GroupPreviewHovercard = ({
  11. className,
  12. children,
  13. hide,
  14. body,
  15. ...props
  16. }: GroupPreviewHovercardProps) => {
  17. const handleStackTracePreviewClick = useCallback(
  18. (e: React.MouseEvent) => void e.stopPropagation(),
  19. []
  20. );
  21. // No need to preview on hover for small devices
  22. const shouldNotPreview = useMedia(`(max-width: ${theme.breakpoints.medium})`);
  23. if (shouldNotPreview) {
  24. return <Fragment>{children}</Fragment>;
  25. }
  26. return (
  27. <StyledHovercardWithBodyClass
  28. className={className}
  29. displayTimeout={200}
  30. delay={100}
  31. position="right"
  32. tipBorderColor="border"
  33. tipColor="background"
  34. hide={hide}
  35. body={<div onClick={handleStackTracePreviewClick}>{body}</div>}
  36. {...props}
  37. >
  38. {children}
  39. </StyledHovercardWithBodyClass>
  40. );
  41. };
  42. // This intermediary is necessary to generate bodyClassName with styled components
  43. const HovercardWithBodyClass = ({className, ...rest}: GroupPreviewHovercardProps) => {
  44. return <StyledHovercard bodyClassName={className} {...rest} />;
  45. };
  46. const StyledHovercardWithBodyClass = styled(HovercardWithBodyClass)`
  47. padding: 0;
  48. max-height: 300px;
  49. overflow-y: auto;
  50. overscroll-behavior: contain;
  51. border-bottom-left-radius: ${p => p.theme.borderRadius};
  52. border-bottom-right-radius: ${p => p.theme.borderRadius};
  53. `;
  54. const StyledHovercard = styled(Hovercard)<{hide?: boolean}>`
  55. /* Lower z-index to match the modals (10000 vs 10002) to allow stackTraceLinkModal be on top of stack trace preview. */
  56. z-index: ${p => p.theme.zIndex.modal};
  57. width: auto;
  58. ${p =>
  59. p.hide &&
  60. css`
  61. visibility: hidden;
  62. `};
  63. .loading {
  64. margin: 0 auto;
  65. .loading-indicator {
  66. /**
  67. * Overriding the .less file - for default 64px loader we have the width of border set to 6px
  68. * For 32px we therefore need 3px to keep the same thickness ratio
  69. */
  70. border-width: 3px;
  71. }
  72. }
  73. `;