suggestedAvatarStack.tsx 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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 = 3;
  12. const SuggestedAvatarStack = ({owners, tooltip, tooltipOptions, ...props}: Props) => {
  13. const [firstSuggestion, ...suggestedOwners] = owners;
  14. const numAvatars = Math.min(owners.length, MAX_SUGGESTIONS);
  15. return (
  16. <AvatarStack data-test-id="suggested-avatar-stack">
  17. {suggestedOwners.slice(0, numAvatars - 1).map((owner, i) => (
  18. <Avatar
  19. {...props}
  20. suggested
  21. round={firstSuggestion.type === 'user'}
  22. actor={owner}
  23. key={i}
  24. index={i}
  25. hasTooltip={false}
  26. />
  27. ))}
  28. <Avatar
  29. {...props}
  30. suggested
  31. actor={firstSuggestion}
  32. index={numAvatars - 1}
  33. tooltip={tooltip}
  34. tooltipOptions={{...tooltipOptions, skipWrapper: true}}
  35. />
  36. </AvatarStack>
  37. );
  38. };
  39. const AvatarStack = styled('div')`
  40. display: flex;
  41. align-content: center;
  42. flex-direction: row-reverse;
  43. `;
  44. const translateStyles = (props: {index: number}) => css`
  45. transform: translateX(${60 * props.index}%);
  46. `;
  47. const Avatar = styled(ActorAvatar)<{index: number}>`
  48. ${translateStyles}
  49. `;
  50. export default SuggestedAvatarStack;