timelinePlaceholder.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import {keyframes} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {space} from 'sentry/styles/space';
  4. const SPACING = 15;
  5. export function TimelinePlaceholder() {
  6. return (
  7. <PlaceholderSvg xmlns="http://www.w3.org/2000/svg" width="100%" height="14px">
  8. <defs>
  9. <pattern
  10. id="tick-pattern"
  11. patternUnits="userSpaceOnUse"
  12. width={SPACING + 4}
  13. height={24}
  14. >
  15. <rect width="4px" height="14px" rx="2" fill="white" />
  16. </pattern>
  17. <mask id="pattern-mask">
  18. <rect width="100%" height="100%" fill="url(#tick-pattern)" />
  19. </mask>
  20. </defs>
  21. <foreignObject width="100%" height="14" mask="url(#pattern-mask)">
  22. <AnimatedGradient />
  23. </foreignObject>
  24. </PlaceholderSvg>
  25. );
  26. }
  27. const PlaceholderSvg = styled('svg')`
  28. margin: ${space(0.5)} 0;
  29. `;
  30. const gradientAnimation = keyframes`
  31. 0%{ background-position-x: 0%; }
  32. 100%{ background-position-x: -200%; }
  33. `;
  34. const AnimatedGradient = styled('div')`
  35. width: 100%;
  36. height: 100%;
  37. background-image: linear-gradient(
  38. 90deg,
  39. ${p => p.theme.border} 0%,
  40. rgba(255, 255, 255, 0) 20%,
  41. rgba(255, 255, 255, 0) 80%,
  42. ${p => p.theme.border} 100%
  43. );
  44. background-size: 200% 100%;
  45. animation: ${gradientAnimation} 2s linear infinite;
  46. `;