styles.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import type {Theme} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import {HighlightComponent} from 'sentry/components/highlight';
  5. import Panel from 'sentry/components/panels/panel';
  6. import PanelHeader from 'sentry/components/panels/panelHeader';
  7. import PanelItem from 'sentry/components/panels/panelItem';
  8. import {space} from 'sentry/styles/space';
  9. import {unreachable} from 'sentry/utils/unreachable';
  10. import {SeverityLevel} from 'sentry/views/explore/logs/utils';
  11. export const StyledPanel = styled(Panel)`
  12. margin-bottom: 0px;
  13. `;
  14. export const HeaderCell = styled(PanelHeader)<{align: 'left' | 'right'}>`
  15. white-space: nowrap;
  16. justify-content: ${p => (p.align === 'left' ? 'flex-start' : 'flex-end')};
  17. cursor: pointer;
  18. `;
  19. export const StyledPanelItem = styled(PanelItem)<{
  20. align?: 'left' | 'center' | 'right';
  21. overflow?: boolean;
  22. span?: number;
  23. }>`
  24. align-items: center;
  25. padding: ${space(1)} ${space(1)};
  26. ${p => (p.align === 'left' ? 'justify-content: flex-start;' : null)}
  27. ${p => (p.align === 'right' ? 'justify-content: flex-end;' : null)}
  28. ${p => (p.overflow ? p.theme.overflowEllipsis : null)};
  29. ${p =>
  30. p.align === 'center'
  31. ? `
  32. justify-content: space-around;`
  33. : p.align === 'left' || p.align === 'right'
  34. ? `text-align: ${p.align};`
  35. : undefined}
  36. ${p => p.span && `grid-column: auto / span ${p.span};`}
  37. white-space: nowrap;
  38. `;
  39. export const LogPanelContent = styled('div')`
  40. width: 100%;
  41. display: grid;
  42. grid-template-columns: min-content auto min-content;
  43. `;
  44. export const LogRowContent = styled('div')`
  45. display: flex;
  46. align-items: center;
  47. gap: 8px;
  48. `;
  49. export const DetailsWrapper = styled(StyledPanelItem)`
  50. background-color: ${p => p.theme.gray100};
  51. flex-direction: column;
  52. `;
  53. export const DetailsGrid = styled(StyledPanel)`
  54. display: grid;
  55. grid-template-columns: 1fr;
  56. width: 100%;
  57. gap: ${space(1)} ${space(2)};
  58. border-bottom: 0;
  59. border-bottom-left-radius: 0;
  60. border-bottom-right-radius: 0;
  61. padding: ${space(1)} ${space(2)};
  62. `;
  63. export const LogDetailsTitle = styled('div')`
  64. font-size: ${p => p.theme.fontSizeLarge};
  65. font-weight: ${p => p.theme.fontWeightBold};
  66. user-select: none;
  67. `;
  68. export const DetailsFooter = styled(StyledPanelItem)<{
  69. logColors: ReturnType<typeof getLogColors>;
  70. opaque?: boolean;
  71. }>`
  72. width: 100%;
  73. padding: ${space(1)} ${space(2)};
  74. color: ${p => p.logColors.color};
  75. &:last-child {
  76. border: 1px solid ${p => p.logColors.border};
  77. }
  78. border-bottom-left-radius: ${p => p.theme.borderRadius};
  79. border-bottom-right-radius: ${p => p.theme.borderRadius};
  80. background: ${p =>
  81. p.opaque
  82. ? `linear-gradient(
  83. ${p.logColors.backgroundLight},
  84. ${p.logColors.backgroundLight}),
  85. linear-gradient(${p.theme.background}, ${p.theme.background}
  86. )`
  87. : `
  88. ${p.logColors.backgroundLight}
  89. `};
  90. `;
  91. export const StyledChevronButton = styled(Button)`
  92. margin-right: ${space(0.5)};
  93. `;
  94. const DEFAULT_SIZE = '8px';
  95. export const ColoredLogCircle = styled('span')<{
  96. logColors: ReturnType<typeof getLogColors>;
  97. size?: string;
  98. }>`
  99. padding: 0;
  100. position: relative;
  101. width: ${p => p.size || DEFAULT_SIZE};
  102. height: ${p => p.size || DEFAULT_SIZE};
  103. margin-right: ${space(0.5)};
  104. text-indent: -9999em;
  105. display: inline-block;
  106. border-radius: 50%;
  107. flex-shrink: 0;
  108. background-color: ${p => p.logColors.background};
  109. `;
  110. export const ColoredLogText = styled('span')<{
  111. logColors: ReturnType<typeof getLogColors>;
  112. }>`
  113. color: ${p => p.logColors.color};
  114. font-weight: ${p => p.theme.fontWeightBold};
  115. font-family: ${p => p.theme.text.familyMono};
  116. `;
  117. export const LogDate = styled('span')`
  118. color: ${p => p.theme.gray300};
  119. `;
  120. export const LogsHighlight = styled(HighlightComponent)`
  121. font-weight: ${p => p.theme.fontWeightBold};
  122. background-color: ${p => p.theme.gray200};
  123. margin-right: 2px;
  124. margin-left: 2px;
  125. `;
  126. export const WrappingText = styled('div')<{wrap?: boolean}>`
  127. width: 100%;
  128. ${p => p.theme.overflowEllipsis};
  129. ${p => p.wrap && 'text-wrap: auto;'}
  130. `;
  131. export function getLogColors(level: SeverityLevel, theme: Theme) {
  132. switch (level) {
  133. case SeverityLevel.DEFAULT:
  134. return {
  135. background: theme.gray200,
  136. backgroundLight: theme.backgroundSecondary,
  137. border: theme.border,
  138. borderHover: theme.border,
  139. color: theme.gray200,
  140. };
  141. case SeverityLevel.TRACE:
  142. return {
  143. background: theme.blue300,
  144. backgroundLight: theme.blue100,
  145. border: theme.blue200,
  146. borderHover: theme.blue300,
  147. color: theme.blue400,
  148. };
  149. case SeverityLevel.WARN:
  150. return {
  151. background: theme.yellow300,
  152. backgroundLight: theme.yellow100,
  153. border: theme.yellow200,
  154. borderHover: theme.yellow300,
  155. color: theme.yellow400,
  156. };
  157. case SeverityLevel.ERROR:
  158. // All these colours are likely changing, so we'll hold off moving them into theme for now.
  159. return {
  160. background: '#FF7738', // Matches the legacy error level color
  161. backgroundLight: 'rgba(245, 113, 54, 0.11)',
  162. border: 'rgba(245, 113, 54, 0.55)',
  163. borderHover: '#FF7738',
  164. color: '#b34814',
  165. };
  166. case SeverityLevel.FATAL:
  167. return {
  168. background: theme.red300,
  169. backgroundLight: theme.red100,
  170. border: theme.red200,
  171. borderHover: theme.red300,
  172. color: theme.red400,
  173. };
  174. case SeverityLevel.DEBUG:
  175. return {
  176. background: theme.gray300,
  177. backgroundLight: theme.gray100,
  178. border: theme.gray200,
  179. borderHover: theme.gray300,
  180. color: theme.gray300,
  181. };
  182. case SeverityLevel.INFO:
  183. return {
  184. background: theme.blue300,
  185. backgroundLight: theme.blue100,
  186. border: theme.blue200,
  187. borderHover: theme.blue300,
  188. color: theme.blue400,
  189. };
  190. case SeverityLevel.UNKNOWN:
  191. return {
  192. background: theme.gray300,
  193. backgroundLight: theme.gray100,
  194. border: theme.gray200,
  195. borderHover: theme.gray300,
  196. color: theme.gray200,
  197. };
  198. default:
  199. unreachable(level);
  200. throw new Error(`Invalid log type, got ${level}`);
  201. }
  202. }