draggableTabMenuButton.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import {DropdownMenu, type MenuItemProps} from 'sentry/components/dropdownMenu';
  5. import {IconEllipsis} from 'sentry/icons';
  6. interface DraggableTabMenuButtonProps {
  7. menuOptions: MenuItemProps[];
  8. hasUnsavedChanges?: boolean;
  9. triggerProps?: Omit<React.HTMLAttributes<HTMLElement>, 'children'>;
  10. }
  11. export function DraggableTabMenuButton({
  12. triggerProps,
  13. hasUnsavedChanges = false,
  14. menuOptions,
  15. }: DraggableTabMenuButtonProps) {
  16. return (
  17. <TriggerIconWrap>
  18. <StyledDropdownMenu
  19. position="bottom-start"
  20. triggerProps={{
  21. size: 'zero',
  22. showChevron: false,
  23. borderless: true,
  24. icon: (
  25. <Fragment>
  26. <StyledDropdownButton
  27. {...triggerProps}
  28. aria-label="Tab Options"
  29. borderless
  30. size="zero"
  31. icon={<IconEllipsis compact />}
  32. />
  33. {hasUnsavedChanges && <UnsavedChangesIndicator role="presentation" />}
  34. </Fragment>
  35. ),
  36. style: {width: '18px', height: '16px'},
  37. }}
  38. items={menuOptions}
  39. offset={[-10, 5]}
  40. />
  41. </TriggerIconWrap>
  42. );
  43. }
  44. const StyledDropdownMenu = styled(DropdownMenu)`
  45. font-weight: ${p => p.theme.fontWeightNormal};
  46. `;
  47. const UnsavedChangesIndicator = styled('div')`
  48. width: 7px;
  49. height: 7px;
  50. border-radius: 50%;
  51. background: ${p => p.theme.active};
  52. border: solid 1px ${p => p.theme.background};
  53. position: absolute;
  54. top: -3px;
  55. right: -3px;
  56. `;
  57. const StyledDropdownButton = styled(Button)`
  58. width: 18px;
  59. height: 16px;
  60. border: 1px solid ${p => p.theme.gray200};
  61. gap: 5px;
  62. border-radius: 4px;
  63. `;
  64. const TriggerIconWrap = styled('div')`
  65. position: relative;
  66. display: flex;
  67. align-items: center;
  68. `;