baseBadge.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import {memo} from 'react';
  2. import styled from '@emotion/styled';
  3. import Avatar from 'sentry/components/avatar';
  4. import {space, type ValidSize} from 'sentry/styles/space';
  5. import type {Actor} from 'sentry/types/core';
  6. import type {Organization, Team} from 'sentry/types/organization';
  7. import type {AvatarProject} from 'sentry/types/project';
  8. import type {AvatarUser} from 'sentry/types/user';
  9. export interface BaseBadgeProps {
  10. avatarProps?: Record<string, any>;
  11. avatarSize?: number;
  12. className?: string;
  13. description?: React.ReactNode;
  14. // Hides the main display name
  15. hideAvatar?: boolean;
  16. hideName?: boolean;
  17. onClick?: React.HTMLAttributes<HTMLDivElement>['onClick'];
  18. }
  19. interface AllBaseBadgeProps extends BaseBadgeProps {
  20. displayName: React.ReactNode;
  21. actor?: Actor;
  22. organization?: Organization;
  23. project?: AvatarProject;
  24. team?: Team;
  25. user?: AvatarUser;
  26. }
  27. export const BaseBadge = memo(
  28. ({
  29. displayName,
  30. hideName = false,
  31. hideAvatar = false,
  32. avatarProps = {},
  33. avatarSize = 24,
  34. description,
  35. onClick,
  36. team,
  37. user,
  38. organization,
  39. project,
  40. actor,
  41. className,
  42. }: AllBaseBadgeProps) => {
  43. // Space items appropriatley depending on avatar size
  44. const wrapperGap: ValidSize = avatarSize <= 14 ? 0.5 : avatarSize <= 20 ? 0.75 : 1;
  45. return (
  46. <Wrapper className={className} style={{gap: space(wrapperGap)}} onClick={onClick}>
  47. {!hideAvatar && (
  48. <Avatar
  49. {...avatarProps}
  50. size={avatarSize}
  51. team={team}
  52. user={user}
  53. organization={organization}
  54. project={project}
  55. actor={actor}
  56. />
  57. )}
  58. {(!hideName || !!description) && (
  59. <DisplayNameAndDescription>
  60. {!hideName && (
  61. <DisplayName data-test-id="badge-display-name">{displayName}</DisplayName>
  62. )}
  63. {!!description && <Description>{description}</Description>}
  64. </DisplayNameAndDescription>
  65. )}
  66. </Wrapper>
  67. );
  68. }
  69. );
  70. const Wrapper = styled('div')`
  71. display: flex;
  72. align-items: center;
  73. flex-shrink: 0;
  74. `;
  75. const DisplayNameAndDescription = styled('div')`
  76. display: flex;
  77. flex-direction: column;
  78. line-height: 1.2;
  79. overflow: hidden;
  80. `;
  81. const DisplayName = styled('span')`
  82. overflow: hidden;
  83. text-overflow: ellipsis;
  84. line-height: 1.2;
  85. `;
  86. const Description = styled('div')`
  87. font-size: 0.875em;
  88. margin-top: ${space(0.25)};
  89. color: ${p => p.theme.gray300};
  90. line-height: 14px;
  91. ${p => p.theme.overflowEllipsis};
  92. `;