diff --git a/src/scenes/Projects/Overview/ProjectOverview.tsx b/src/scenes/Projects/Overview/ProjectOverview.tsx index c215150b6f..315c412d5f 100644 --- a/src/scenes/Projects/Overview/ProjectOverview.tsx +++ b/src/scenes/Projects/Overview/ProjectOverview.tsx @@ -55,11 +55,7 @@ import { ProjectListQueryVariables } from '../List/ProjectList.graphql'; import { EditableProjectField, UpdateProjectDialog } from '../Update'; import { ProjectWorkflowDialog } from '../Update/ProjectWorkflowDialog'; import { useProjectId } from '../useProjectId'; -import { - WorkflowEventsDrawer, - WorkflowEventsIcon, - WorkflowEventsList, -} from '../WorkflowEvents'; +import { WorkflowEventsDrawer, WorkflowEventsIcon } from '../WorkflowEvents'; import { ProjectEngagementListOverviewDocument as EngagementList, ProjectOverviewDocument, @@ -586,9 +582,10 @@ export const ProjectOverview = () => { )} {project && ( - - - + )} ); diff --git a/src/scenes/Projects/WorkflowEvents/WorkflowEventsDrawer.tsx b/src/scenes/Projects/WorkflowEvents/WorkflowEventsDrawer.tsx index 8f236ed881..1eced2dbc9 100644 --- a/src/scenes/Projects/WorkflowEvents/WorkflowEventsDrawer.tsx +++ b/src/scenes/Projects/WorkflowEvents/WorkflowEventsDrawer.tsx @@ -1,39 +1,92 @@ import { Close } from '@mui/icons-material'; import { Box, Divider, Drawer, DrawerProps, Typography } from '@mui/material'; +import { useSize } from 'ahooks'; +import { useEffect, useRef, useState } from 'react'; import { extendSx } from '~/common'; import { IconButton } from '~/components/IconButton'; +import { ProjectWorkflowEventFragment as WorkflowEvent } from './projectWorkflowEvent.graphql'; +import { WorkflowEventsList } from './WorkflowEventsList'; +type WorkflowEventsDrawerProps = DrawerProps & { + TransitionProps?: DrawerProps['SlideProps']; + events: readonly WorkflowEvent[]; +}; export const WorkflowEventsDrawer = ({ + events, TransitionProps, ...props -}: DrawerProps & { TransitionProps?: DrawerProps['SlideProps'] }) => ( - - - Status History Log - props.onClose?.(e, 'backdropClick')}> - - - - - {props.children} - -); +}: WorkflowEventsDrawerProps) => { + const listRef = useRef(); + const listSize = useSize(listRef); + const windowSize = useSize(() => document.querySelector('body')); + const [needsWidthCalc, setNeedsWidthCalc] = useState(false); + + const isFullWidth = + !!windowSize?.width && + !!listSize?.width && + windowSize.width <= listSize.width; + + useEffect(() => setNeedsWidthCalc(true), [events]); + useEffect(() => { + listSize?.width && setNeedsWidthCalc(false); + }, [listSize?.width]); + + return ( + <> + + + Status History Log + props.onClose?.(e, 'backdropClick')}> + + + + + + {/* Actual list shown in UI */} + + + + {/* + Hidden list to track intrinsic size to calculate full width. + Outside the drawer so it is in DOM when needed regardless of drawer state. + */} + {needsWidthCalc && ( + + )} + + ); +}; diff --git a/src/scenes/Projects/WorkflowEvents/WorkflowEventsList.tsx b/src/scenes/Projects/WorkflowEvents/WorkflowEventsList.tsx index 07089df51e..7e8ec50292 100644 --- a/src/scenes/Projects/WorkflowEvents/WorkflowEventsList.tsx +++ b/src/scenes/Projects/WorkflowEvents/WorkflowEventsList.tsx @@ -1,97 +1,110 @@ import { ChevronRight } from '@mui/icons-material'; -import { Box, Divider, List, Typography } from '@mui/material'; +import { Box, Divider, List, ListProps, Typography } from '@mui/material'; +import { forwardRef } from 'react'; import { ProjectStepLabels, ProjectStepList } from '~/api/schema/enumLists'; +import { extendSx } from '~/common'; import { RelativeDateTime } from '~/components/Formatters'; import { Link } from '~/components/Routing'; import { TextChip } from '~/components/TextChip'; import { ProjectWorkflowEventFragment as WorkflowEvent } from './projectWorkflowEvent.graphql'; -const gridAt = 'md' as const; - -export const WorkflowEventsList = ({ - events, -}: { +type WorkflowEventsListProps = { events: readonly WorkflowEvent[]; -}) => ( - ({ - display: 'flex', - flexDirection: 'column', - [theme.breakpoints.up(gridAt)]: { - display: 'grid', - rowGap: 1, - columnGap: 2, - alignItems: 'center', - gridTemplateColumns: - '[at] min-content [from] min-content [arrow] min-content [to] min-content', - }, - })} - > - {events.toReversed().map((event, index, array) => { - const prev = index >= 1 ? array[index - 1] : null; - const prevStatus = prev ? prev.to : ProjectStepList[0]!; + fullWidth?: boolean; +} & ListProps; + +export const WorkflowEventsList = forwardRef( + function WorkflowEventsList({ events, fullWidth = false, ...props }, ref) { + return ( + + {events.toReversed().map((event, index, array) => { + const prev = index >= 1 ? array[index - 1] : null; + const prevStatus = prev ? prev.to : ProjectStepList[0]!; - return ( - ({ - display: 'contents', - [theme.breakpoints.down(gridAt)]: { - display: 'flex', - flexWrap: 'wrap', - alignItems: 'center', - gap: 1, - padding: 1, - borderBottom: `thin solid ${theme.palette.divider}`, - }, - })} - > - - {event.who.value?.__typename === 'User' && ( - - {event.who.value.fullName} - - )} - - - - - ({ - display: 'contents', - [theme.breakpoints.down(gridAt)]: { - display: 'flex', - flexWrap: 'wrap', - alignItems: 'center', - gap: 1, - }, - })} - > - - {ProjectStepLabels[prevStatus]} - - - - {ProjectStepLabels[event.to]} - - - - - ); - })} - + return ( + ({ + display: 'flex', + flexWrap: 'wrap', + alignItems: 'center', + gap: 1, + padding: 1, + borderBottom: `thin solid ${theme.palette.divider}`, + })), + ]} + > + + {event.who.value?.__typename === 'User' && ( + + {event.who.value.fullName} + + )} + + + + + + + {ProjectStepLabels[prevStatus]} + + + + {ProjectStepLabels[event.to]} + + + + + ); + })} + + ); + } );