From 35a73a5b8ec60f9d5c529cb2a28ff0ae6f7bc7d1 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Thu, 3 Oct 2024 09:02:12 +0200 Subject: [PATCH] fix: add grid w/container query for projects (#8344) The main goals of this are: 1. Make it so that the layout grid doesn't break on small screens 2. Fix an issue where the border of the box didn't fit the outline 3. (Bonus): make the layout of the info box depend on the **box's** size, not the screen size. To achieve those goals, this PR: 1. Switches to using a native CSS grid instead of MUI's grid component. This gives us more power over the layout in various different sizes. 2. Switches from putting borders on the boxes inside the grid, instead makes the grid container the color of the border and uses gaps to create borders. 3. If your browser supports it, it will use container queries to determine whether we should display the layout as a multi-column grid or in a single column. Container query demo (both with the same screen sizes): Sidebar closed: ![image](https://github.com/user-attachments/assets/9a7d9a78-de92-4429-bf06-8e98fbf40ed0) Sidebar open: ![image](https://github.com/user-attachments/assets/90e790ba-13db-485c-8f5e-ee60fe36dabb) --- .../src/component/personalDashboard/Grid.tsx | 62 +++++ .../personalDashboard/MyProjects.tsx | 223 ++++++++++-------- 2 files changed, 187 insertions(+), 98 deletions(-) diff --git a/frontend/src/component/personalDashboard/Grid.tsx b/frontend/src/component/personalDashboard/Grid.tsx index de1ce152ec..d3da090664 100644 --- a/frontend/src/component/personalDashboard/Grid.tsx +++ b/frontend/src/component/personalDashboard/Grid.tsx @@ -1,6 +1,68 @@ import { Box, Grid, styled } from '@mui/material'; import type { Theme } from '@mui/material/styles/createTheme'; +export const ContentGridContainer = styled('div')({ + containerType: 'inline-size', +}); + +const ContentGrid2 = styled('article')(({ theme }) => { + return { + backgroundColor: theme.palette.divider, + borderRadius: `${theme.shape.borderRadiusLarge}px`, + overflow: 'hidden', + border: `0.5px solid ${theme.palette.divider}`, + gap: `2px`, + display: 'flex', + flexFlow: 'column nowrap', + + '&>*': { + backgroundColor: theme.palette.background.paper, + }, + }; +}); + +export const ProjectGrid = styled(ContentGrid2)(({ theme }) => ({ + '@container (min-width: 1000px)': { + gridTemplateColumns: '1fr 1fr 1fr', + display: 'grid', + gridTemplateAreas: ` + "title onboarding onboarding" + "projects box1 box2" + ". owners owners" + `, + }, + + '@supports not (container-type: inline-size)': { + [theme.breakpoints.up('lg')]: { + gridTemplateColumns: '1fr 1fr 1fr', + display: 'grid', + gridTemplateAreas: ` + "title onboarding onboarding" + "projects box1 box2" + ". owners owners" + `, + }, + }, +})); + +export const SpacedGridItem2 = styled('div')(({ theme }) => ({ + padding: theme.spacing(4), +})); + +export const EmptyGridItem = styled('div')(({ theme }) => ({ + display: 'none', + + '@container (min-width: 1000px)': { + display: 'block', + }, + + '@supports not (container-type: inline-size)': { + [theme.breakpoints.up('lg')]: { + display: 'block', + }, + }, +})); + export const ContentGrid = styled(Grid)(({ theme }) => ({ backgroundColor: theme.palette.background.paper, borderRadius: `${theme.shape.borderRadiusLarge}px`, diff --git a/frontend/src/component/personalDashboard/MyProjects.tsx b/frontend/src/component/personalDashboard/MyProjects.tsx index 7ee59bc760..f95a60e286 100644 --- a/frontend/src/component/personalDashboard/MyProjects.tsx +++ b/frontend/src/component/personalDashboard/MyProjects.tsx @@ -21,10 +21,12 @@ import type { PersonalDashboardSchemaProjectsItem, } from '../../openapi'; import { - ContentGrid, + ContentGridContainer, + EmptyGridItem, ListItemBox, listItemStyle, - SpacedGridItem, + ProjectGrid, + SpacedGridItem2, } from './Grid'; const ActiveProjectDetails: FC<{ @@ -78,104 +80,129 @@ export const MyProjects: FC<{ activeProjectStage === 'first-flag-created'; return ( - - - My projects - - - {setupIncomplete ? ( - Setup incomplete - ) : null} - - - + + - {projects.map((project) => { - return ( - - setActiveProject(project.id)} + My projects + + + {setupIncomplete ? ( + Setup incomplete + ) : null} + + + + {projects.map((project) => { + return ( + - - - - {project.name} - - - + setActiveProject(project.id) + } + > + + + + {project.name} + + + + + + {project.id === activeProject ? ( + - - - {project.id === activeProject ? ( - - ) : null} - - - ); - })} - - - - {activeProjectStage === 'onboarded' && - personalDashboardProjectDetails ? ( - - ) : null} - {activeProjectStage === 'onboarding-started' || - activeProjectStage === 'loading' ? ( - - ) : null} - {activeProjectStage === 'first-flag-created' ? ( - - ) : null} - - - {activeProjectStage === 'onboarded' && - personalDashboardProjectDetails ? ( - - ) : null} - {setupIncomplete || activeProjectStage === 'loading' ? ( - - ) : null} - - - - {personalDashboardProjectDetails ? ( - role.name, - )} - owners={personalDashboardProjectDetails.owners} - /> - ) : null} - - + ) : null} + + + ); + })} + + + + {activeProjectStage === 'onboarded' && + personalDashboardProjectDetails ? ( + + ) : null} + {activeProjectStage === 'onboarding-started' || + activeProjectStage === 'loading' ? ( + + ) : null} + {activeProjectStage === 'first-flag-created' ? ( + + ) : null} + + + {activeProjectStage === 'onboarded' && + personalDashboardProjectDetails ? ( + + ) : null} + {setupIncomplete || activeProjectStage === 'loading' ? ( + + ) : null} + + + + {personalDashboardProjectDetails ? ( + role.name, + )} + owners={personalDashboardProjectDetails.owners} + /> + ) : null} + + + ); };