1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

feat: adds information about project modes to the project creation form (#7250)

This change adds information about the project modes to the new
project creation form, using the tooltip for project creation modes.

In doing so, it updates the config button tooltip to accept extra
elements and adds styling for them.

What it looks like: 


![image](https://github.com/Unleash/unleash/assets/17786332/809fb48e-2404-416b-a867-6fa04978ccc1)

## a11y issues

This solution does present one problem: the popover doesn't get focus,
so it's impossible for you to scroll with only a keyboard. However, this
is something that's present in Unleash already, and not something that I
think would be easily solvable, so I don't think this is when we should
solve it.
This commit is contained in:
Thomas Heartman 2024-06-05 09:20:18 +02:00 committed by GitHub
parent e5c3cc0c8d
commit c129541df6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 77 additions and 14 deletions

View File

@ -10,7 +10,7 @@ import {
type ChangeRequestTableConfigButtonProps = Pick<
ConfigButtonProps,
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltipHeader'
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltip'
> & {
search: {
label: string;

View File

@ -30,3 +30,14 @@ export const ButtonLabel = styled('span', {
width: 'max-content',
},
}));
export const StyledTooltipContent = styled('article')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
paddingBlock: theme.spacing(1),
'& > *': {
margin: 0,
},
}));

View File

@ -6,18 +6,27 @@ import {
StyledPopover,
HiddenDescription,
ButtonLabel,
StyledTooltipContent,
} from './ConfigButton.styles';
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
export type ConfigButtonProps = {
button: { label: string; icon: ReactNode; labelWidth?: string };
button: {
label: string;
icon: ReactNode;
labelWidth?: string;
additionalTooltipContent?: ReactNode;
};
onOpen?: () => void;
onClose?: () => void;
description: string;
preventOpen?: boolean;
anchorEl: HTMLDivElement | null | undefined;
setAnchorEl: (el: HTMLDivElement | null | undefined) => void;
tooltipHeader: string;
tooltip: {
header: string;
additionalContent?: ReactNode;
};
};
export const ConfigButton: FC<PropsWithChildren<ConfigButtonProps>> = ({
@ -29,7 +38,7 @@ export const ConfigButton: FC<PropsWithChildren<ConfigButtonProps>> = ({
preventOpen,
anchorEl,
setAnchorEl,
tooltipHeader,
tooltip,
}) => {
const ref = useRef<HTMLDivElement>(null);
const descriptionId = uuidv4();
@ -49,10 +58,11 @@ export const ConfigButton: FC<PropsWithChildren<ConfigButtonProps>> = ({
<Box ref={ref}>
<TooltipResolver
titleComponent={
<article>
<h3>{tooltipHeader}</h3>
<StyledTooltipContent>
<h3>{tooltip.header}</h3>
<p>{description}</p>
</article>
{tooltip.additionalContent}
</StyledTooltipContent>
}
variant='custom'
>

View File

@ -4,7 +4,7 @@ import { DropdownList, type DropdownListProps } from './DropdownList';
type MultiSelectConfigButtonProps = Pick<
ConfigButtonProps,
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltipHeader'
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltip'
> &
Pick<DropdownListProps, 'search' | 'options'> & {
selectedOptions: Set<string>;

View File

@ -4,7 +4,7 @@ import { DropdownList, type DropdownListProps } from './DropdownList';
type SingleSelectConfigButtonProps = Pick<
ConfigButtonProps,
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltipHeader'
'button' | 'onOpen' | 'onClose' | 'description' | 'tooltip'
> &
Pick<DropdownListProps, 'search' | 'onChange' | 'options'>;

View File

@ -77,3 +77,16 @@ export const FormActions = styled(StyledFormSection)(({ theme }) => ({
},
},
}));
export const StyledDefinitionList = styled('dl')(({ theme }) => ({
dt: {
fontWeight: 'bold',
'&:after': {
content: '":"',
},
},
'dd + dt': {
marginBlockStart: theme.spacing(1),
},
}));

View File

@ -14,6 +14,7 @@ import {
OptionButtons,
ProjectDescriptionContainer,
ProjectNameContainer,
StyledDefinitionList,
StyledForm,
StyledHeader,
StyledIcon,
@ -70,7 +71,30 @@ const configButtonData = {
},
mode: {
icon: <ProjectModeIcon />,
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.',
text: "A project's collaboration mode defines who should be allowed see your project and create change requests in it.",
additionalTooltipContent: (
<>
<p>The modes and their functions are:</p>
<StyledDefinitionList>
<dt>Open</dt>
<dd>
Anyone can see the project and anyone can create change
requests.
</dd>
<dt>Protected</dt>
<dd>
Anyone can see the project, but only admins and project
members can submit change requests.
</dd>
<dt>Private</dt>
<dd>
Hides the project from users with the "viewer" root role
who are not members of the project. Only project members
and admins can submit change requests.
</dd>
</StyledDefinitionList>
</>
),
},
changeRequests: {
icon: <ChangeRequestIcon />,
@ -180,7 +204,7 @@ export const NewProjectForm: React.FC<FormProps> = ({
<OptionButtons>
<MultiSelectConfigButton
tooltipHeader='Select project environments'
tooltip={{ header: 'Select project environments' }}
description={configButtonData.environments.text}
selectedOptions={projectEnvironments}
options={activeEnvironments.map((env) => ({
@ -207,7 +231,7 @@ export const NewProjectForm: React.FC<FormProps> = ({
/>
<SingleSelectConfigButton
tooltipHeader='Set default project stickiness'
tooltip={{ header: 'Set default project stickiness' }}
description={configButtonData.stickiness.text}
options={stickinessOptions.map(({ key, ...rest }) => ({
value: key,
@ -235,7 +259,12 @@ export const NewProjectForm: React.FC<FormProps> = ({
condition={isEnterprise()}
show={
<SingleSelectConfigButton
tooltipHeader='Set project mode'
tooltip={{
header: 'Set project collaboration mode',
additionalContent:
configButtonData.mode
.additionalTooltipContent,
}}
description={configButtonData.mode.text}
options={projectModeOptions}
onChange={(value: any) => {
@ -261,7 +290,7 @@ export const NewProjectForm: React.FC<FormProps> = ({
condition={isEnterprise()}
show={
<ChangeRequestTableConfigButton
tooltipHeader='Configure change requests'
tooltip={{ header: 'Configure change requests' }}
description={configButtonData.changeRequests.text}
activeEnvironments={
availableChangeRequestEnvironments