From f5c78605ed90863ff157962e92c51f03f541d1a2 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Thu, 3 Oct 2024 09:54:27 +0200 Subject: [PATCH] refactor: use css grid for flags and no content grid (#8347) This PR uses the new CSS grid layout for the flag grid and the no content grid. In doing so, it also improves how you use the grid item (giving them a `gridArea` prop) and extracts the breakpoint handling so that all sections that use breakpoints use the same breakpoints. As with the previous PR, here's screenies of the same screen width, but with open and closed sidebar: Open: ![image](https://github.com/user-attachments/assets/2d41d412-5072-4c66-9a48-e7aa0d8cff45) Closed: ![image](https://github.com/user-attachments/assets/994e3f2c-6f4c-4db1-9f10-e1d1a4d96540) --- .../ContentGridNoProjects.tsx | 197 +++++++++--------- .../src/component/personalDashboard/Grid.tsx | 76 +++---- .../personalDashboard/MyProjects.tsx | 52 ++--- .../personalDashboard/PersonalDashboard.tsx | 102 ++++----- 4 files changed, 206 insertions(+), 221 deletions(-) diff --git a/frontend/src/component/personalDashboard/ContentGridNoProjects.tsx b/frontend/src/component/personalDashboard/ContentGridNoProjects.tsx index 219f30b568..f1454f5901 100644 --- a/frontend/src/component/personalDashboard/ContentGridNoProjects.tsx +++ b/frontend/src/component/personalDashboard/ContentGridNoProjects.tsx @@ -1,18 +1,18 @@ -import { Grid, Typography, styled } from '@mui/material'; +import { Typography, styled } from '@mui/material'; import { AvatarGroupFromOwners } from 'component/common/AvatarGroupFromOwners/AvatarGroupFromOwners'; import { UserAvatar } from 'component/common/UserAvatar/UserAvatar'; import type { PersonalDashboardSchemaAdminsItem } from 'openapi/models/personalDashboardSchemaAdminsItem'; import type { PersonalDashboardSchemaProjectOwnersItem } from 'openapi/models/personalDashboardSchemaProjectOwnersItem'; import { Link } from 'react-router-dom'; +import { + ContentGridContainer, + EmptyGridItem, + ProjectGrid, + SpacedGridItem, +} from './Grid'; -const ContentGrid = styled(Grid)(({ theme }) => ({ - backgroundColor: theme.palette.background.paper, - borderRadius: `${theme.shape.borderRadiusLarge}px`, -})); - -const SpacedGridItem = styled(Grid)(({ theme }) => ({ +const PaddedEmptyGridItem = styled(EmptyGridItem)(({ theme }) => ({ padding: theme.spacing(4), - border: `0.5px solid ${theme.palette.divider}`, })); const TitleContainer = styled('div')(({ theme }) => ({ @@ -68,96 +68,99 @@ type Props = { export const ContentGridNoProjects: React.FC = ({ owners, admins }) => { return ( - - - My projects - - - Potential next steps - - - - - You don't currently have access to any projects in the - system. - - - To get started, you can{' '} - - create your own project - - . Alternatively, you can review the available projects - in the system and ask the owner for access. - - - - - - - 1 - Contact Unleash admin - - - {admins.length ? ( - <> + + + + My projects + + + Potential next steps + + + + + You don't currently have access to any projects in + the system. + + + To get started, you can{' '} + + create your own project + + . Alternatively, you can review the available + projects in the system and ask the owner for access. + + + + + + + 1 + Contact Unleash admin + + + {admins.length ? ( + <> +

+ Your Unleash administrator + {admins.length > 1 ? 's are' : ' is'}: +

+ + {admins.map((admin) => { + return ( + + + + {admin.name || + admin.username || + admin.email} + + + ); + })} + + + ) : (

- Your Unleash administrator - {admins.length > 1 ? 's are' : ' is'}: + You have no Unleash administrators to + contact.

- - {admins.map((admin) => { - return ( - - - - {admin.name || - admin.username || - admin.email} - - - ); - })} - - - ) : ( -

- You have no Unleash administrators to contact. -

- )} -
-
-
- - - - 2 - Ask a project owner to add you to their project - - - {owners.length ? ( - <> -

Project owners in Unleash:

- - - ) : ( -

- There are no project owners in Unleash to ask - for access. -

- )} -
-
-
- - -
+ )} + + + + + + + 2 + Ask a project owner to add you to their project + + + {owners.length ? ( + <> +

Project owners in Unleash:

+ + + ) : ( +

+ There are no project owners in Unleash to + ask for access. +

+ )} +
+
+
+ + + + ); }; diff --git a/frontend/src/component/personalDashboard/Grid.tsx b/frontend/src/component/personalDashboard/Grid.tsx index d3da090664..e50b6070b4 100644 --- a/frontend/src/component/personalDashboard/Grid.tsx +++ b/frontend/src/component/personalDashboard/Grid.tsx @@ -1,11 +1,11 @@ -import { Box, Grid, styled } from '@mui/material'; +import { Box, 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 }) => { +const ContentGrid = styled('article')(({ theme }) => { return { backgroundColor: theme.palette.divider, borderRadius: `${theme.shape.borderRadiusLarge}px`, @@ -21,8 +21,23 @@ const ContentGrid2 = styled('article')(({ theme }) => { }; }); -export const ProjectGrid = styled(ContentGrid2)(({ theme }) => ({ - '@container (min-width: 1000px)': { +const onWideContainer = + (css: object) => + ({ theme }: { theme: Theme }) => { + const containerBreakpoint = '1000px'; + const screenBreakpoint = theme.breakpoints.up('lg'); + + return { + [`@container (min-width: ${containerBreakpoint})`]: css, + + '@supports not (container-type: inline-size)': { + [screenBreakpoint]: css, + }, + }; + }; + +export const ProjectGrid = styled(ContentGrid)( + onWideContainer({ gridTemplateColumns: '1fr 1fr 1fr', display: 'grid', gridTemplateAreas: ` @@ -30,47 +45,36 @@ export const ProjectGrid = styled(ContentGrid2)(({ theme }) => ({ "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 FlagGrid = styled(ContentGrid)( + onWideContainer({ + gridTemplateColumns: '1fr 1fr 1fr', + display: 'grid', + gridTemplateAreas: ` + "title lifecycle lifecycle" + "flags chart chart" `, - }, - }, -})); + }), +); -export const SpacedGridItem2 = styled('div')(({ theme }) => ({ +export const SpacedGridItem = styled('div', { + shouldForwardProp: (prop) => prop !== 'gridArea', +})<{ gridArea: string }>(({ theme, gridArea }) => ({ padding: theme.spacing(4), + gridArea, })); -export const EmptyGridItem = styled('div')(({ theme }) => ({ +export const EmptyGridItem = styled('div', { + shouldForwardProp: (prop) => prop !== 'gridArea', +})<{ gridArea?: string }>(({ theme, gridArea }) => ({ display: 'none', + gridArea, - '@container (min-width: 1000px)': { + ...onWideContainer({ 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`, -})); - -export const SpacedGridItem = styled(Grid)(({ theme }) => ({ - padding: theme.spacing(4), - border: `0.5px solid ${theme.palette.divider}`, + })({ theme }), })); export const ListItemBox = styled(Box)(({ theme }) => ({ diff --git a/frontend/src/component/personalDashboard/MyProjects.tsx b/frontend/src/component/personalDashboard/MyProjects.tsx index f95a60e286..7021f7dddd 100644 --- a/frontend/src/component/personalDashboard/MyProjects.tsx +++ b/frontend/src/component/personalDashboard/MyProjects.tsx @@ -26,7 +26,7 @@ import { ListItemBox, listItemStyle, ProjectGrid, - SpacedGridItem2, + SpacedGridItem, } from './Grid'; const ActiveProjectDetails: FC<{ @@ -82,29 +82,15 @@ export const MyProjects: FC<{ return ( - + My projects - - + + {setupIncomplete ? ( Setup incomplete ) : null} - - + + - - + + {activeProjectStage === 'onboarded' && personalDashboardProjectDetails ? ( ) : null} - - + + {activeProjectStage === 'onboarded' && personalDashboardProjectDetails ? ( ) : null} - + - + {personalDashboardProjectDetails ? ( ) : null} - + ); diff --git a/frontend/src/component/personalDashboard/PersonalDashboard.tsx b/frontend/src/component/personalDashboard/PersonalDashboard.tsx index f3d8416a52..607bb58691 100644 --- a/frontend/src/component/personalDashboard/PersonalDashboard.tsx +++ b/frontend/src/component/personalDashboard/PersonalDashboard.tsx @@ -24,7 +24,8 @@ import HelpOutline from '@mui/icons-material/HelpOutline'; import useLoading from '../../hooks/useLoading'; import { MyProjects } from './MyProjects'; import { - ContentGrid, + ContentGridContainer, + FlagGrid, ListItemBox, listItemStyle, SpacedGridItem, @@ -180,55 +181,58 @@ export const PersonalDashboard = () => { /> )} - - - My feature flags - - - {activeFlag ? ( - - ) : null} - - - {personalDashboard && personalDashboard.flags.length > 0 ? ( - - {personalDashboard.flags.map((flag) => ( - setActiveFlag(flag)} - /> - ))} - - ) : ( - - You have not created or favorited any feature flags. - Once you do, they will show up here. - - )} - + + + + My feature flags + + + {activeFlag ? ( + + ) : null} + + + {personalDashboard && + personalDashboard.flags.length > 0 ? ( + + {personalDashboard.flags.map((flag) => ( + setActiveFlag(flag)} + /> + ))} + + ) : ( + + You have not created or favorited any feature + flags. Once you do, they will show up here. + + )} + - - {activeFlag ? ( - - ) : ( - - )} - - + + {activeFlag ? ( + + ) : ( + + )} + + + setWelcomeDialog('closed')}