styles.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import {Theme} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {LocationDescriptor} from 'history';
  4. import MenuHeader from 'sentry/components/actions/menuHeader';
  5. import ExternalLink from 'sentry/components/links/externalLink';
  6. import MenuItem from 'sentry/components/menuItem';
  7. import Tag, {Background} from 'sentry/components/tag';
  8. import Truncate from 'sentry/components/truncate';
  9. import space from 'sentry/styles/space';
  10. import {getDuration} from 'sentry/utils/formatters';
  11. import {QuickTraceEvent} from 'sentry/utils/performance/quickTrace/types';
  12. export const SectionSubtext = styled('div')`
  13. color: ${p => p.theme.subText};
  14. font-size: ${p => p.theme.fontSizeMedium};
  15. `;
  16. export const QuickTraceContainer = styled('div')`
  17. display: flex;
  18. align-items: center;
  19. `;
  20. const nodeColors = (theme: Theme) => ({
  21. error: {
  22. color: theme.white,
  23. background: theme.red300,
  24. border: theme.red300,
  25. },
  26. warning: {
  27. color: theme.errorText,
  28. background: theme.background,
  29. border: theme.red300,
  30. },
  31. white: {
  32. color: theme.textColor,
  33. background: theme.background,
  34. border: theme.textColor,
  35. },
  36. black: {
  37. color: theme.background,
  38. background: theme.textColor,
  39. border: theme.textColor,
  40. },
  41. });
  42. export const EventNode = styled(Tag)<{disabled?: boolean}>`
  43. cursor: ${p => (p.disabled ? 'default' : 'pointer')};
  44. span {
  45. display: flex;
  46. color: ${p => nodeColors(p.theme)[p.type || 'white'].color};
  47. }
  48. & ${Background} {
  49. background-color: ${p => nodeColors(p.theme)[p.type || 'white'].background};
  50. border: 1px solid ${p => nodeColors(p.theme)[p.type || 'white'].border};
  51. }
  52. `;
  53. export const TraceConnector = styled('div')`
  54. width: ${space(1)};
  55. border-top: 1px solid ${p => p.theme.textColor};
  56. `;
  57. /**
  58. * The DropdownLink component is styled directly with less and the way the
  59. * elements are laid out within means we can't apply any styles directly
  60. * using emotion. Instead, we wrap it all inside a span and indirectly
  61. * style it here.
  62. */
  63. export const DropdownContainer = styled('span')`
  64. .dropdown-menu {
  65. padding: 0;
  66. }
  67. `;
  68. export const DropdownMenuHeader = styled(MenuHeader)<{first?: boolean}>`
  69. background: ${p => p.theme.backgroundSecondary};
  70. ${p => p.first && 'border-radius: 2px'};
  71. padding: ${space(1)} ${space(1.5)};
  72. `;
  73. const StyledMenuItem = styled(MenuItem)<{width: 'small' | 'large'}>`
  74. width: ${p => (p.width === 'large' ? '350px' : '200px')};
  75. &:not(:last-child) {
  76. border-bottom: 1px solid ${p => p.theme.innerBorder};
  77. }
  78. `;
  79. const MenuItemContent = styled('div')`
  80. display: flex;
  81. justify-content: space-between;
  82. width: 100%;
  83. `;
  84. type DropdownItemProps = {
  85. children: React.ReactNode;
  86. allowDefaultEvent?: boolean;
  87. onSelect?: (eventKey: any) => void;
  88. to?: string | LocationDescriptor;
  89. width?: 'small' | 'large';
  90. };
  91. export function DropdownItem({
  92. children,
  93. onSelect,
  94. allowDefaultEvent,
  95. to,
  96. width = 'large',
  97. }: DropdownItemProps) {
  98. return (
  99. <StyledMenuItem
  100. data-test-id="dropdown-item"
  101. to={to}
  102. onSelect={onSelect}
  103. width={width}
  104. allowDefaultEvent={allowDefaultEvent}
  105. >
  106. <MenuItemContent>{children}</MenuItemContent>
  107. </StyledMenuItem>
  108. );
  109. }
  110. export const DropdownItemSubContainer = styled('div')`
  111. display: flex;
  112. flex-direction: row;
  113. > a {
  114. padding-left: 0 !important;
  115. }
  116. `;
  117. export const QuickTraceValue = styled(Truncate)`
  118. margin-left: ${space(1)};
  119. white-space: nowrap;
  120. `;
  121. export const ErrorNodeContent = styled('div')`
  122. display: grid;
  123. grid-template-columns: repeat(2, auto);
  124. gap: ${space(0.25)};
  125. align-items: center;
  126. `;
  127. export const ExternalDropdownLink = styled(ExternalLink)`
  128. display: inherit !important;
  129. padding: 0 !important;
  130. color: ${p => p.theme.textColor};
  131. &:hover {
  132. color: ${p => p.theme.textColor};
  133. }
  134. `;
  135. export function SingleEventHoverText({event}: {event: QuickTraceEvent}) {
  136. return (
  137. <div>
  138. <Truncate
  139. value={event.transaction}
  140. maxLength={30}
  141. leftTrim
  142. trimRegex={/\.|\//g}
  143. expandable={false}
  144. />
  145. <div>
  146. {getDuration(
  147. event['transaction.duration'] / 1000,
  148. event['transaction.duration'] < 1000 ? 0 : 2,
  149. true
  150. )}
  151. </div>
  152. </div>
  153. );
  154. }