vitalCard.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import QuestionTooltip from 'sentry/components/questionTooltip';
  4. import {space} from 'sentry/styles/space';
  5. import {PERFORMANCE_SCORE_COLORS} from 'sentry/views/insights/browser/webVitals/utils/performanceScoreColors';
  6. type Props = {
  7. description: string;
  8. formattedValue: React.ReactNode;
  9. status: string | undefined;
  10. statusLabel: string | undefined;
  11. title: string;
  12. };
  13. function VitalCard({description, formattedValue, status, statusLabel, title}: Props) {
  14. return (
  15. <Fragment>
  16. <MeterBarContainer>
  17. <MeterBarBody>
  18. {description && (
  19. <StyledQuestionTooltip
  20. isHoverable
  21. size="xs"
  22. title={<span>{description}</span>}
  23. />
  24. )}
  25. <MeterHeader>{title}</MeterHeader>
  26. <MeterValueText>{formattedValue ?? '-'}</MeterValueText>
  27. </MeterBarBody>
  28. <MeterBarFooter label={statusLabel} status={status} />
  29. </MeterBarContainer>
  30. </Fragment>
  31. );
  32. }
  33. const MeterBarContainer = styled('div')<{clickable?: boolean}>`
  34. flex: 1;
  35. position: relative;
  36. padding: 0;
  37. cursor: ${p => (p.clickable ? 'pointer' : 'default')};
  38. min-width: 140px;
  39. `;
  40. const MeterBarBody = styled('div')`
  41. border: 1px solid ${p => p.theme.gray200};
  42. border-radius: ${p => p.theme.borderRadius} ${p => p.theme.borderRadius} 0 0;
  43. border-bottom: none;
  44. padding: ${space(1)} 0 ${space(0.5)} 0;
  45. `;
  46. const MeterHeader = styled('div')`
  47. font-size: ${p => p.theme.fontSizeSmall};
  48. color: ${p => p.theme.textColor};
  49. display: inline-block;
  50. text-align: center;
  51. width: 100%;
  52. `;
  53. const MeterValueText = styled('div')`
  54. display: flex;
  55. justify-content: center;
  56. align-items: center;
  57. font-size: ${p => p.theme.headerFontSize};
  58. color: ${p => p.theme.textColor};
  59. flex: 1;
  60. text-align: center;
  61. `;
  62. function MeterBarFooter({
  63. label,
  64. status,
  65. }: {
  66. label: string | undefined;
  67. status: string | undefined;
  68. }) {
  69. return (
  70. <MeterBarFooterContainer status={status || 'none'}>
  71. {label || '-'}
  72. </MeterBarFooterContainer>
  73. );
  74. }
  75. const MeterBarFooterContainer = styled('div')<{status: string}>`
  76. color: ${p => p.theme[PERFORMANCE_SCORE_COLORS[p.status].normal]};
  77. border-radius: 0 0 ${p => p.theme.borderRadius} ${p => p.theme.borderRadius};
  78. background-color: ${p => p.theme[PERFORMANCE_SCORE_COLORS[p.status].light]};
  79. border: solid 1px ${p => p.theme[PERFORMANCE_SCORE_COLORS[p.status].light]};
  80. font-size: ${p => p.theme.fontSizeExtraSmall};
  81. padding: ${space(0.5)};
  82. text-align: center;
  83. `;
  84. const StyledQuestionTooltip = styled(QuestionTooltip)`
  85. position: absolute;
  86. right: ${space(1)};
  87. `;
  88. export default VitalCard;