toolbar.tsx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import styled from '@emotion/styled';
  2. import {Button} from 'sentry/components/button';
  3. import {IconCopy, IconDelete, IconEdit, IconGrabbable} from 'sentry/icons';
  4. import {t} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import {DRAG_HANDLE_CLASS} from '../dashboard';
  7. type ToolbarProps = {
  8. isMobile?: boolean;
  9. onDelete?: () => void;
  10. onDuplicate?: () => void;
  11. onEdit?: () => void;
  12. };
  13. export function Toolbar({isMobile, onEdit, onDelete, onDuplicate}: ToolbarProps) {
  14. return (
  15. <ToolbarPanel>
  16. <IconContainer>
  17. {!isMobile && (
  18. <GrabbableButton
  19. size="xs"
  20. aria-label={t('Drag Widget')}
  21. icon={<IconGrabbable />}
  22. borderless
  23. className={DRAG_HANDLE_CLASS}
  24. />
  25. )}
  26. {onEdit && (
  27. <Button
  28. data-test-id="widget-edit"
  29. aria-label={t('Edit Widget')}
  30. size="xs"
  31. borderless
  32. onClick={onEdit}
  33. icon={<IconEdit />}
  34. />
  35. )}
  36. {onDuplicate && (
  37. <Button
  38. aria-label={t('Duplicate Widget')}
  39. size="xs"
  40. borderless
  41. onClick={onDuplicate}
  42. icon={<IconCopy />}
  43. />
  44. )}
  45. {onDelete && (
  46. <Button
  47. data-test-id="widget-delete"
  48. aria-label={t('Delete Widget')}
  49. borderless
  50. size="xs"
  51. onClick={onDelete}
  52. icon={<IconDelete />}
  53. />
  54. )}
  55. </IconContainer>
  56. </ToolbarPanel>
  57. );
  58. }
  59. const ToolbarPanel = styled('div')`
  60. position: absolute;
  61. top: 0;
  62. left: 0;
  63. z-index: 2;
  64. width: 100%;
  65. height: 100%;
  66. display: flex;
  67. justify-content: flex-end;
  68. align-items: flex-start;
  69. background-color: ${p => p.theme.overlayBackgroundAlpha};
  70. border-radius: calc(${p => p.theme.panelBorderRadius} - 1px);
  71. `;
  72. const IconContainer = styled('div')`
  73. display: flex;
  74. margin: ${space(1)};
  75. touch-action: none;
  76. `;
  77. const GrabbableButton = styled(Button)`
  78. cursor: grab;
  79. `;
  80. export const WidgetTitleRow = styled('span')`
  81. display: flex;
  82. align-items: center;
  83. gap: ${space(0.75)};
  84. `;
  85. export const WidgetDescription = styled('small')`
  86. ${p => p.theme.overflowEllipsis}
  87. color: ${p => p.theme.gray300};
  88. `;