header.tsx 2.1 KB

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