From 78fcdbf132cb3570fc34496d8745afaaa9eb9105 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Wed, 22 May 2024 13:45:47 +0200 Subject: [PATCH] feat: show docs with icons in sidebar (#7109) Adds icons to sidebar documentation and removes the link when you can't interact with it. I'm a little concerned that this won't be very accessible at the moment, because we don't announce that anything has changed (i.e. there's no way to find out that the text has changed if you can't see it), and the text isn't labeled as describing anything. (this is being addressed in #7110 ) ![image](https://github.com/Unleash/unleash/assets/17786332/2f482aa1-b74d-4b0f-97aa-2dbc1d1f82f9) There's a few caveats to this: 1. we don't set a min height at the moment. I've avoided this because we use the sidebar a number of other places and I wanted to touch as little as possible. This means we can still get height adjustments 2. The new project icon doesn't have the same proportions as the mui icons. This adds some additional jank. We should probably look at this, though. --- .../src/assets/icons/projectIconSmall.svg | 8 ++-- .../common/FormTemplate/FormTemplate.tsx | 44 +++++++++++++++---- .../NewProjectCard/NewProjectCard.styles.ts | 3 +- .../CreateProjectDialog.tsx | 31 ++++++++++--- .../Project/CreateProject/NewProjectForm.tsx | 34 ++++++++------ 5 files changed, 86 insertions(+), 34 deletions(-) diff --git a/frontend/src/assets/icons/projectIconSmall.svg b/frontend/src/assets/icons/projectIconSmall.svg index 61a65151c0..7e6546eedb 100644 --- a/frontend/src/assets/icons/projectIconSmall.svg +++ b/frontend/src/assets/icons/projectIconSmall.svg @@ -1,5 +1,5 @@ - - - - + diff --git a/frontend/src/component/common/FormTemplate/FormTemplate.tsx b/frontend/src/component/common/FormTemplate/FormTemplate.tsx index 90e65bc826..1783b6a95d 100644 --- a/frontend/src/component/common/FormTemplate/FormTemplate.tsx +++ b/frontend/src/component/common/FormTemplate/FormTemplate.tsx @@ -23,8 +23,9 @@ import { relative } from 'themes/themeStyles'; interface ICreateProps { title?: ReactNode; description: string; - documentationLink: string; - documentationLinkLabel: string; + documentationLink?: string; + documentationIcon?: ReactNode; + documentationLinkLabel?: string; loading?: boolean; modal?: boolean; disablePadding?: boolean; @@ -165,16 +166,26 @@ const StyledSidebar = styled('aside')(({ theme }) => ({ }, })); -const StyledDescription = styled('p')(({ theme }) => ({ - color: theme.palette.common.white, +const StyledDescriptionCard = styled('article')(({ theme }) => ({ + display: 'flex', + flexFlow: 'column nowrap', + gap: theme.spacing(2), + alignItems: 'center', zIndex: 1, + color: theme.palette.common.white, position: 'relative', + marginBlockEnd: theme.spacing(3), +})); + +const StyledDescription = styled('p')(({ theme }) => ({ + width: '100%', })); const StyledLinkContainer = styled('div')(({ theme }) => ({ margin: theme.spacing(3, 0), display: 'flex', alignItems: 'center', + width: '100%', })); const StyledLinkIcon = styled(MenuBookIcon)(({ theme }) => ({ @@ -195,6 +206,7 @@ const FormTemplate: React.FC = ({ description, children, documentationLink, + documentationIcon, documentationLinkLabel, loading, modal, @@ -261,6 +273,7 @@ const FormTemplate: React.FC = ({ @@ -300,6 +313,7 @@ const FormTemplate: React.FC = ({ condition={showGuidance && !smallScreen} show={ = ({ interface IMobileGuidance { description: string; - documentationLink: string; + documentationLink?: string; + documentationIcon?: ReactNode; documentationLinkLabel?: string; } @@ -327,6 +342,7 @@ const MobileGuidance = ({ description, documentationLink, documentationLinkLabel, + documentationIcon, }: IMobileGuidance) => { const [open, setOpen] = useState(false); @@ -345,6 +361,7 @@ const MobileGuidance = ({ = ({ description, children, documentationLink, + documentationIcon, documentationLinkLabel = 'Learn more', showDescription = true, showLink = true, @@ -374,11 +393,19 @@ const Guidance: React.FC = ({ {description}} + show={ + + + {description} + + } /> @@ -392,7 +419,6 @@ const Guidance: React.FC = ({ } /> - {children} ); diff --git a/frontend/src/component/project/NewProjectCard/NewProjectCard.styles.ts b/frontend/src/component/project/NewProjectCard/NewProjectCard.styles.ts index 439258af82..7b3660abe2 100644 --- a/frontend/src/component/project/NewProjectCard/NewProjectCard.styles.ts +++ b/frontend/src/component/project/NewProjectCard/NewProjectCard.styles.ts @@ -76,7 +76,8 @@ export const StyledParagraphInfo = styled('p')(({ theme }) => ({ })); export const StyledProjectIcon = styled(ProjectIcon)(({ theme }) => ({ - color: theme.palette.primary.main, + fill: theme.palette.primary.main, + stroke: theme.palette.primary.main, })); export const StyledIconBox = styled(Box)(({ theme }) => ({ diff --git a/frontend/src/component/project/Project/CreateProject/CreateProjectDialog/CreateProjectDialog.tsx b/frontend/src/component/project/Project/CreateProject/CreateProjectDialog/CreateProjectDialog.tsx index bea4b15afe..35f8a588f2 100644 --- a/frontend/src/component/project/Project/CreateProject/CreateProjectDialog/CreateProjectDialog.tsx +++ b/frontend/src/component/project/Project/CreateProject/CreateProjectDialog/CreateProjectDialog.tsx @@ -9,11 +9,12 @@ import useProjectForm, { DEFAULT_PROJECT_STICKINESS, } from '../../hooks/useProjectForm'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; -import { useState } from 'react'; +import { type ReactNode, useState } from 'react'; import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { useNavigate } from 'react-router-dom'; import { Button, Dialog, styled } from '@mui/material'; +import { ReactComponent as ProjectIcon } from 'assets/icons/projectIconSmall.svg'; interface ICreateProjectDialogueProps { open: boolean; @@ -24,6 +25,7 @@ const StyledDialog = styled(Dialog)(({ theme, maxWidth }) => ({ '& .MuiDialog-paper': { borderRadius: theme.shape.borderRadiusLarge, maxWidth: theme.spacing(170), + width: '100%', backgroundColor: 'transparent', }, padding: 0, @@ -35,6 +37,11 @@ const StyledButton = styled(Button)(({ theme }) => ({ marginLeft: theme.spacing(3), })); +const StyledProjectIcon = styled(ProjectIcon)(({ theme }) => ({ + fill: theme.palette.common.white, + stroke: theme.palette.common.white, +})); + export const CreateProjectDialogue = ({ open, onClose, @@ -67,8 +74,18 @@ export const CreateProjectDialogue = ({ errors, } = useProjectForm(); - const generalDocumentation = - 'Projects allows you to group feature flags together in the management UI.'; + const generalDocumentation: { + icon: ReactNode; + text: string; + link?: { url: string; label: string }; + } = { + icon: , + text: 'Projects allows you to group feature flags together in the management UI.', + link: { + url: 'https://docs.getunleash.io/reference/projects', + label: 'Projects documentation', + }, + }; const [documentation, setDocumentation] = useState(generalDocumentation); @@ -115,14 +132,16 @@ export const CreateProjectDialogue = ({ } } }; + return ( ({ @@ -38,7 +39,8 @@ const TopGrid = styled(StyledFormSection)(({ theme }) => ({ })); const StyledIcon = styled(ProjectIcon)(({ theme }) => ({ - color: theme.palette.primary.main, + fill: theme.palette.primary.main, + stroke: theme.palette.primary.main, })); const StyledHeader = styled(Typography)(({ theme }) => ({ @@ -101,7 +103,7 @@ type FormProps = { mode: 'Create' | 'Edit'; clearErrors: () => void; validateProjectId: () => void; - overrideDocumentation: (description: string) => void; + overrideDocumentation: (args: { text: string; icon: ReactNode }) => void; clearDocumentationOverride: () => void; }; @@ -223,9 +225,10 @@ export const NewProjectForm: React.FC = ({ placeholder: 'Select project environments', }} onOpen={() => - overrideDocumentation( - `Each feature flag can have a separate configuration per environment. This setting configures which environments your project should start with.`, - ) + overrideDocumentation({ + icon: , + text: `Each feature flag can have a separate configuration per environment. This setting configures which environments your project should start with.`, + }) } onClose={clearDocumentationOverride} /> @@ -247,9 +250,10 @@ export const NewProjectForm: React.FC = ({ placeholder: 'Select default stickiness', }} onOpen={() => - overrideDocumentation( - 'Stickiness is used to guarantee that your users see the same result when using a gradual rollout. Default stickiness allows you to choose which field is used by default in this project.', - ) + overrideDocumentation({ + icon: , + text: 'Stickiness is used to guarantee that your users see the same result when using a gradual rollout. Default stickiness allows you to choose which field is used by default in this project.', + }) } onClose={clearDocumentationOverride} /> @@ -271,9 +275,10 @@ export const NewProjectForm: React.FC = ({ placeholder: 'Select project mode', }} onOpen={() => - overrideDocumentation( - 'Mode defines who should be allowed to interact and see your project. Private mode hides the project from anyone except the project owner and members.', - ) + overrideDocumentation({ + icon: , + text: 'Mode defines who should be allowed to interact and see your project. Private mode hides the project from anyone except the project owner and members.', + }) } onClose={clearDocumentationOverride} /> @@ -316,9 +321,10 @@ export const NewProjectForm: React.FC = ({ projectChangeRequestConfiguration } onOpen={() => - overrideDocumentation( - 'Change requests can be configured per environment and require changes to go through an approval process before being applied.', - ) + overrideDocumentation({ + icon: , + text: 'Change requests can be configured per environment and require changes to go through an approval process before being applied.', + }) } onClose={clearDocumentationOverride} />