From 1a9ff507aa3067ae5392d6eef91c6b2af5f17df3 Mon Sep 17 00:00:00 2001 From: Chi-Sheng Liu Date: Tue, 26 Mar 2024 02:10:53 +0800 Subject: [PATCH] feat(panel): Resizable side panel Resolves: flyteorg/flyte#5102 Signed-off-by: Chi-Sheng Liu --- .../src/components/common/DetailsPanel.tsx | 20 ++++++-- .../src/components/common/constants.ts | 2 +- .../src/components/hooks/useResize.ts | 51 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 packages/oss-console/src/components/hooks/useResize.ts diff --git a/packages/oss-console/src/components/common/DetailsPanel.tsx b/packages/oss-console/src/components/common/DetailsPanel.tsx index 0a598aebe..d70d881ba 100644 --- a/packages/oss-console/src/components/common/DetailsPanel.tsx +++ b/packages/oss-console/src/components/common/DetailsPanel.tsx @@ -4,7 +4,9 @@ import Paper from '@mui/material/Paper'; import { useTheme } from '@mui/material/styles'; import styled from '@mui/system/styled'; import { detailsPanelId } from '@clients/common/constants'; -import { detailsPanelWidth } from './constants'; +import classnames from 'classnames'; +import useResize from '@clients/oss-console/components/hooks/useResize'; +import { defaultDetailsPanelWidth } from './constants'; const StyledPaper = styled(Paper)(({ theme }) => ({ display: 'flex', @@ -12,7 +14,15 @@ const StyledPaper = styled(Paper)(({ theme }) => ({ maxHeight: '100%', paddingBottom: theme.spacing(2), pointerEvents: 'initial', - width: detailsPanelWidth, + '& .dragger': { + width: '3px', + cursor: 'ew-resize', + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + zIndex: 100, + }, })); interface DetailsPanelProps { @@ -29,6 +39,9 @@ export const DetailsPanel: React.FC> = ({ open = false, }) => { const theme = useTheme(); + + const { width, enableResize } = useResize({ minWidth: defaultDetailsPanelWidth }); + return ( > = ({ open={open} key="detailsPanel" > - + +
{children} diff --git a/packages/oss-console/src/components/common/constants.ts b/packages/oss-console/src/components/common/constants.ts index ca7197b01..1d62c8b4c 100644 --- a/packages/oss-console/src/components/common/constants.ts +++ b/packages/oss-console/src/components/common/constants.ts @@ -1,7 +1,7 @@ import { env } from '@clients/common/environment'; import { InterpreterOptions } from 'xstate'; -export const detailsPanelWidth = 432; +export const defaultDetailsPanelWidth = 432; export const labels = { moreOptionsButton: 'Display more options', diff --git a/packages/oss-console/src/components/hooks/useResize.ts b/packages/oss-console/src/components/hooks/useResize.ts new file mode 100644 index 000000000..f63deb389 --- /dev/null +++ b/packages/oss-console/src/components/hooks/useResize.ts @@ -0,0 +1,51 @@ +// Reference: https://stackoverflow.com/a/68742668 + +import { useCallback, useEffect, useState } from 'react'; + +type UseResizeProps = { + minWidth: number; +}; + +type UseResizeReturn = { + width: number; + enableResize: () => void; +}; + +const useResize = ({ minWidth }: UseResizeProps): UseResizeReturn => { + const [isResizing, setIsResizing] = useState(false); + const [width, setWidth] = useState(minWidth); + + const enableResize = useCallback(() => { + setIsResizing(true); + }, [setIsResizing]); + + const disableResize = useCallback(() => { + setIsResizing(false); + }, [setIsResizing]); + + const resize = useCallback( + (e: MouseEvent) => { + if (isResizing) { + const newWidth = document.body.offsetWidth - e.clientX; // You may want to add some offset here from props + if (newWidth >= minWidth) { + setWidth(newWidth); + } + } + }, + [minWidth, isResizing, setWidth], + ); + + useEffect(() => { + document.addEventListener('mousemove', resize); + document.addEventListener('mouseup', disableResize); + + return () => { + document.removeEventListener('mousemove', resize); + document.removeEventListener('mouseup', disableResize); + }; + }, [disableResize, resize]); + + return { width, enableResize }; +}; + +export default useResize;