userBadge.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import styled from '@emotion/styled';
  2. import {space} from 'sentry/styles/space';
  3. import type {AvatarUser} from 'sentry/types/user';
  4. import Link from '../links/link';
  5. import BadgeDisplayName from './badgeDisplayName';
  6. import {BaseBadge, type BaseBadgeProps} from './baseBadge';
  7. export interface UserBadgeProps extends BaseBadgeProps {
  8. displayEmail?: React.ReactNode | string;
  9. displayName?: React.ReactNode;
  10. hideEmail?: boolean;
  11. to?: string;
  12. user?: AvatarUser;
  13. }
  14. function UserBadge({
  15. hideEmail = false,
  16. displayName,
  17. displayEmail,
  18. user,
  19. to,
  20. ...props
  21. }: UserBadgeProps) {
  22. const title =
  23. displayName ||
  24. (user &&
  25. (user.name ||
  26. user.email ||
  27. user.username ||
  28. user.ipAddress ||
  29. // Because this can be used to render EventUser models, or User *interface*
  30. // objects from serialized Event models. we try both ipAddress and ip_address.
  31. user.ip_address ||
  32. user.ip ||
  33. user.id));
  34. const name = <Name hideEmail={!!hideEmail}>{title}</Name>;
  35. return (
  36. <BaseBadge
  37. displayName={
  38. <BadgeDisplayName>
  39. {to ? <Link to={to}>{name}</Link> : name}
  40. {!hideEmail && <Email>{displayEmail || user?.email}</Email>}
  41. </BadgeDisplayName>
  42. }
  43. user={user}
  44. {...props}
  45. />
  46. );
  47. }
  48. const Name = styled('span')<{hideEmail: boolean}>`
  49. font-weight: ${p => (p.hideEmail ? 'inherit' : 'bold')};
  50. line-height: 1.15em;
  51. ${p => p.theme.overflowEllipsis};
  52. `;
  53. const Email = styled('div')`
  54. font-size: 0.875em;
  55. margin-top: ${space(0.25)};
  56. color: ${p => p.theme.gray300};
  57. ${p => p.theme.overflowEllipsis};
  58. `;
  59. export default UserBadge;