header.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import styled from '@emotion/styled';
  2. import {Button} from 'sentry/components/button';
  3. import Input from 'sentry/components/input';
  4. import {Tooltip} from 'sentry/components/tooltip';
  5. import {IconCheckmark, IconEdit} from 'sentry/icons';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import {WidgetDescription} from 'sentry/views/dashboards/widgetCard';
  9. export interface MetricWidgetTitleState {
  10. edited: string;
  11. isEditing: boolean;
  12. stored: string;
  13. }
  14. interface Props {
  15. onTitleChange: (val: Partial<MetricWidgetTitleState>) => void;
  16. title: MetricWidgetTitleState;
  17. description?: string;
  18. placeholder?: string;
  19. }
  20. export function MetricWidgetTitle({
  21. title,
  22. onTitleChange,
  23. placeholder,
  24. description,
  25. }: Props) {
  26. const titleToDisplay =
  27. title.edited === ''
  28. ? title.stored === ''
  29. ? placeholder
  30. : title.stored
  31. : title.edited;
  32. return (
  33. <WidgetHeader>
  34. <WidgetTitleRow>
  35. {title.isEditing ? (
  36. <Input
  37. value={title.edited}
  38. placeholder={placeholder}
  39. onChange={e => {
  40. onTitleChange({edited: e.target.value});
  41. }}
  42. />
  43. ) : (
  44. <h3>{titleToDisplay}</h3>
  45. )}
  46. <Button
  47. aria-label={t('Edit Title')}
  48. size="sm"
  49. borderless
  50. icon={title.isEditing ? <IconCheckmark size="sm" /> : <IconEdit size="sm" />}
  51. priority={title.isEditing ? 'primary' : 'default'}
  52. onClick={() => {
  53. onTitleChange({isEditing: !title.isEditing});
  54. }}
  55. />
  56. </WidgetTitleRow>
  57. {description && (
  58. <Tooltip
  59. title={description}
  60. containerDisplayMode="grid"
  61. showOnlyOnOverflow
  62. isHoverable
  63. position="bottom"
  64. >
  65. <WidgetDescription>{description}</WidgetDescription>
  66. </Tooltip>
  67. )}
  68. </WidgetHeader>
  69. );
  70. }
  71. const WidgetHeader = styled('div')`
  72. display: flex;
  73. flex-direction: column;
  74. gap: ${space(1)};
  75. `;
  76. const WidgetTitleRow = styled('div')`
  77. display: flex;
  78. justify-content: flex-start;
  79. align-items: center;
  80. gap: ${space(1)};
  81. `;