From cd79a5be0ac0521e70ef2dde231c91a4dfd151de Mon Sep 17 00:00:00 2001 From: Martin Mark Date: Tue, 24 Dec 2024 11:34:50 -0500 Subject: [PATCH] Resizeable drawer / update trial selection header --- .../Browse3/pages/ChatView/ChoicesDrawer.tsx | 85 ++++++++----- .../Browse3/pages/common/ResizableDrawer.tsx | 115 ++++++++++++++++++ 2 files changed, 169 insertions(+), 31 deletions(-) create mode 100644 weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/ResizableDrawer.tsx diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ChatView/ChoicesDrawer.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ChatView/ChoicesDrawer.tsx index dd87968f181..d2e066894c6 100644 --- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ChatView/ChoicesDrawer.tsx +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/ChatView/ChoicesDrawer.tsx @@ -2,11 +2,13 @@ import {Box, Drawer} from '@mui/material'; import {MOON_200} from '@wandb/weave/common/css/color.styles'; import {Tag} from '@wandb/weave/components/Tag'; import {Tailwind} from '@wandb/weave/components/Tailwind'; -import React from 'react'; +import React, {useState, useEffect, useCallback} from 'react'; import {Button} from '../../../../../Button'; import {ChoiceView} from './ChoiceView'; import {Choice} from './types'; +import {ResizableDrawer} from '../common/ResizableDrawer'; +import {Icon} from '@wandb/weave/components/Icon'; type ChoicesDrawerProps = { choices: Choice[]; @@ -25,21 +27,36 @@ export const ChoicesDrawer = ({ selectedChoiceIndex, setSelectedChoiceIndex, }: ChoicesDrawerProps) => { + const [width, setWidth] = useState(784); + const [maxAllowedWidth, setMaxAllowedWidth] = useState(window.innerWidth - 73); + + useEffect(() => { + const handleResize = () => { + const newMaxWidth = window.innerWidth - 73; + setMaxAllowedWidth(newMaxWidth); + }; + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + const handleFullScreen = useCallback(() => { + const newWidth = width === maxAllowedWidth ? 784 : maxAllowedWidth; + setWidth(newWidth); + }, [width, maxAllowedWidth]); + return ( - setIsDrawerOpen(false)} - title="Choices" - anchor="right" - sx={{ - '& .MuiDrawer-paper': {mt: '60px', width: '400px'}, - }}> + defaultWidth={width} + setWidth={setWidth}> - Responses + Trials + + + +
+ + Response selected +
) : ( )} @@ -101,6 +124,6 @@ export const ChoicesDrawer = ({ ))} -
+ ); }; diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/ResizableDrawer.tsx b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/ResizableDrawer.tsx new file mode 100644 index 00000000000..b13aa694cc9 --- /dev/null +++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/common/ResizableDrawer.tsx @@ -0,0 +1,115 @@ +import {Box, Drawer, DrawerProps} from '@mui/material'; +import {MOON_200} from '@wandb/weave/common/css/color.styles'; +import React, {useCallback, useEffect, useState} from 'react'; + +interface ResizableDrawerProps extends Omit { + onClose: () => void; + defaultWidth?: number; + title?: React.ReactNode; + headerContent?: React.ReactNode; + setWidth?: (width: number) => void; +} + +export const ResizableDrawer: React.FC = ({ + children, + defaultWidth = 400, + title, + headerContent, + onClose, + setWidth: externalSetWidth, + ...drawerProps +}) => { + const [internalWidth, setInternalWidth] = useState(defaultWidth); + const [isResizing, setIsResizing] = useState(false); + // 73px = 57px sidebar + 16px padding + const [maxAllowedWidth, setMaxAllowedWidth] = useState(window.innerWidth - 73); + + const setWidthValue = useCallback((newWidth: number) => { + setInternalWidth(newWidth); + externalSetWidth?.(newWidth); + }, [externalSetWidth]); + + useEffect(() => { + if (externalSetWidth) { + setInternalWidth(defaultWidth); + } + }, [defaultWidth, externalSetWidth]); + + useEffect(() => { + const handleResize = () => { + const newMaxWidth = window.innerWidth - 73; + setMaxAllowedWidth(newMaxWidth); + if (internalWidth > newMaxWidth) { + setWidthValue(newMaxWidth); + } + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [internalWidth, setWidthValue]); + + const handleMouseDown = useCallback((e: React.MouseEvent) => { + setIsResizing(true); + e.preventDefault(); + }, []); + + const handleMouseUp = useCallback(() => { + setIsResizing(false); + }, []); + + const handleMouseMove = useCallback( + (e: MouseEvent) => { + if (!isResizing) return; + + const newWidth = window.innerWidth - e.clientX; + if (newWidth >= 120 && newWidth <= maxAllowedWidth) { + setWidthValue(newWidth); + } + }, + [isResizing, maxAllowedWidth, setWidthValue] + ); + + useEffect(() => { + if (isResizing) { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + } + + return () => { + window.removeEventListener('mousemove', handleMouseMove); + window.removeEventListener('mouseup', handleMouseUp); + }; + }, [isResizing, handleMouseMove, handleMouseUp]); + + return ( + + + {children} + + ); +};