two-column-main-content.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import React, { ReactNode, useEffect, useState } from 'react'
  2. import { Panel, PanelGroup } from 'react-resizable-panels'
  3. import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'
  4. import { useTranslation } from 'react-i18next'
  5. import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler'
  6. import useFixedSizeColumn from '@/features/ide-react/hooks/use-fixed-size-column'
  7. import useCollapsiblePanel from '@/features/ide-react/hooks/use-collapsible-panel'
  8. import classNames from 'classnames'
  9. type TwoColumnMainContentProps = {
  10. leftColumnId: string
  11. leftColumnContent: ReactNode
  12. leftColumnDefaultSize: number
  13. setLeftColumnDefaultSize: React.Dispatch<React.SetStateAction<number>>
  14. rightColumnContent: ReactNode
  15. leftColumnIsOpen: boolean
  16. setLeftColumnIsOpen: (
  17. leftColumnIsOpen: TwoColumnMainContentProps['leftColumnIsOpen']
  18. ) => void
  19. }
  20. export default function TwoColumnMainContent({
  21. leftColumnId,
  22. leftColumnContent,
  23. leftColumnDefaultSize,
  24. setLeftColumnDefaultSize,
  25. rightColumnContent,
  26. leftColumnIsOpen,
  27. setLeftColumnIsOpen,
  28. }: TwoColumnMainContentProps) {
  29. const { t } = useTranslation()
  30. const {
  31. fixedPanelRef: leftColumnPanelRef,
  32. fixedPanelWidthRef: leftColumnWidthRef,
  33. handleLayout,
  34. } = useFixedSizeColumn(leftColumnDefaultSize, leftColumnIsOpen)
  35. useCollapsiblePanel(leftColumnIsOpen, leftColumnPanelRef)
  36. const [resizing, setResizing] = useState(false)
  37. // Update the left column default size on unmount rather than doing it on
  38. // every resize, which causes ResizeObserver errors
  39. useEffect(() => {
  40. if (leftColumnWidthRef.current) {
  41. setLeftColumnDefaultSize(leftColumnWidthRef.current.size)
  42. }
  43. }, [leftColumnWidthRef, setLeftColumnDefaultSize])
  44. return (
  45. <PanelGroup
  46. autoSaveId="ide-react-main-content-layout"
  47. direction="horizontal"
  48. onLayout={handleLayout}
  49. className={classNames({
  50. 'ide-react-main-content-resizing': resizing,
  51. })}
  52. >
  53. <Panel
  54. ref={leftColumnPanelRef}
  55. defaultSize={leftColumnDefaultSize}
  56. minSize={5}
  57. collapsible
  58. onCollapse={collapsed => setLeftColumnIsOpen(!collapsed)}
  59. >
  60. {leftColumnContent}
  61. </Panel>
  62. <HorizontalResizeHandle
  63. onDoubleClick={() => setLeftColumnIsOpen(!leftColumnIsOpen)}
  64. resizable={leftColumnIsOpen}
  65. onDragging={setResizing}
  66. >
  67. <HorizontalToggler
  68. id={leftColumnId}
  69. togglerType="west"
  70. isOpen={leftColumnIsOpen}
  71. setIsOpen={setLeftColumnIsOpen}
  72. tooltipWhenOpen={t('tooltip_hide_filetree')}
  73. tooltipWhenClosed={t('tooltip_show_filetree')}
  74. />
  75. </HorizontalResizeHandle>
  76. <Panel className="ide-react-panel">{rightColumnContent}</Panel>
  77. </PanelGroup>
  78. )
  79. }