rail-action-element.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import MaterialIcon, {
  2. AvailableUnfilledIcon,
  3. } from '@/shared/components/material-icon'
  4. import { forwardRef, ReactElement, useCallback } from 'react'
  5. import {
  6. Dropdown,
  7. DropdownToggle,
  8. } from '@/shared/components/dropdown/dropdown-menu'
  9. import OLTooltip from '@/shared/components/ol/ol-tooltip'
  10. import { DropdownToggle as BS5DropdownToggle } from 'react-bootstrap'
  11. type RailActionButton = {
  12. key: string
  13. icon: AvailableUnfilledIcon
  14. title: string
  15. action: () => void
  16. indicator?: ReactElement
  17. hide?: boolean
  18. ref?: React.Ref<HTMLButtonElement>
  19. }
  20. type RailDropdown = {
  21. key: string
  22. icon: AvailableUnfilledIcon
  23. title: string
  24. dropdown: ReactElement
  25. indicator?: ReactElement
  26. hide?: boolean
  27. ref?: React.Ref<HTMLButtonElement>
  28. }
  29. export type RailAction = RailDropdown | RailActionButton
  30. const RailActionElement = forwardRef<HTMLButtonElement, { action: RailAction }>(
  31. ({ action }, ref) => {
  32. const onActionClick = useCallback(() => {
  33. if ('action' in action) {
  34. action.action()
  35. }
  36. }, [action])
  37. if (action.hide) {
  38. return null
  39. }
  40. if ('dropdown' in action) {
  41. return (
  42. <Dropdown align="end" drop="end">
  43. <OLTooltip
  44. id={`rail-dropdown-tooltip-${action.key}`}
  45. description={action.title}
  46. overlayProps={{ delay: 0, placement: 'right' }}
  47. >
  48. <span>
  49. <DropdownToggle
  50. ref={ref as React.ForwardedRef<typeof BS5DropdownToggle>}
  51. id={`rail-dropdown-btn-${action.key}`}
  52. className="ide-rail-tab-link ide-rail-tab-button ide-rail-tab-dropdown"
  53. as="button"
  54. aria-label={action.title}
  55. >
  56. <RailActionIcon
  57. type={action.icon}
  58. indicator={action.indicator}
  59. />
  60. </DropdownToggle>
  61. </span>
  62. </OLTooltip>
  63. {action.dropdown}
  64. </Dropdown>
  65. )
  66. } else {
  67. return (
  68. <OLTooltip
  69. id={`rail-tab-tooltip-${action.key}`}
  70. description={action.title}
  71. overlayProps={{ delay: 0, placement: 'right' }}
  72. >
  73. <button
  74. ref={ref}
  75. onClick={onActionClick}
  76. className="ide-rail-tab-link ide-rail-tab-button"
  77. aria-label={action.title}
  78. >
  79. <RailActionIcon type={action.icon} indicator={action.indicator} />
  80. </button>
  81. </OLTooltip>
  82. )
  83. }
  84. }
  85. )
  86. function RailActionIcon({
  87. type,
  88. indicator,
  89. }: {
  90. type: AvailableUnfilledIcon
  91. indicator?: ReactElement
  92. }) {
  93. return (
  94. <>
  95. <MaterialIcon className="ide-rail-tab-link-icon" type={type} unfilled />
  96. {indicator}
  97. </>
  98. )
  99. }
  100. RailActionElement.displayName = 'RailActionElement'
  101. export default RailActionElement