suggestedAvatarStack.tsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import ActorAvatar from 'sentry/components/avatar/actorAvatar';
  4. import BaseAvatar from 'sentry/components/avatar/baseAvatar';
  5. import {Actor} from 'sentry/types';
  6. type Props = {
  7. owners: Actor[];
  8. } & BaseAvatar['props'] &
  9. Omit<React.ComponentProps<typeof ActorAvatar>, 'actor' | 'hasTooltip'>;
  10. // Constrain the number of visible suggestions
  11. const MAX_SUGGESTIONS = 5;
  12. const SuggestedAvatarStack = ({owners, tooltip, tooltipOptions, ...props}: Props) => {
  13. const backgroundAvatarProps = {
  14. ...props,
  15. round: owners[0].type === 'user',
  16. suggested: true,
  17. };
  18. const numAvatars = Math.min(owners.length, MAX_SUGGESTIONS);
  19. return (
  20. <AvatarStack data-test-id="suggested-avatar-stack">
  21. {[...Array(numAvatars - 1)].map((_, i) => (
  22. <BackgroundAvatar
  23. {...backgroundAvatarProps}
  24. key={i}
  25. type="background"
  26. index={i}
  27. hasTooltip={false}
  28. />
  29. ))}
  30. <Avatar
  31. {...props}
  32. suggested
  33. actor={owners[0]}
  34. index={numAvatars - 1}
  35. tooltip={tooltip}
  36. tooltipOptions={{...tooltipOptions, skipWrapper: true}}
  37. />
  38. </AvatarStack>
  39. );
  40. };
  41. const AvatarStack = styled('div')`
  42. display: flex;
  43. align-content: center;
  44. flex-direction: row-reverse;
  45. `;
  46. const translateStyles = (props: {index: number}) => css`
  47. transform: translateX(${60 * props.index}%);
  48. `;
  49. const Avatar = styled(ActorAvatar)<{index: number}>`
  50. ${translateStyles}
  51. `;
  52. const BackgroundAvatar = styled(BaseAvatar)<{index: number}>`
  53. ${translateStyles}
  54. `;
  55. export default SuggestedAvatarStack;