1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: new in unleash tooltip (#7991)

This commit is contained in:
Mateusz Kwasniewski 2024-08-27 15:47:55 +02:00 committed by GitHub
parent 742504793c
commit c69036c5a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 245 additions and 48 deletions

View File

@ -105,7 +105,7 @@ const StageBox = styled(Box, {
const ColorFill = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
borderRadius: theme.spacing(0, 0, 1, 1), // has to match the parent tooltip container
borderRadius: `0 0 ${theme.shape.borderRadiusMedium}px ${theme.shape.borderRadiusMedium}px`, // has to match the parent tooltip container
margin: theme.spacing(-1, -1.5), // has to match the parent tooltip container
padding: theme.spacing(2, 3),
}));

View File

@ -12,7 +12,6 @@ import {
styled,
} from '@mui/material';
import Signals from '@mui/icons-material/Sensors';
import { useNavigate } from 'react-router-dom';
import type { NavigationMode } from 'component/layout/MainLayout/NavigationSidebar/NavigationMode';
import { NewInUnleashItem } from './NewInUnleashItem';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
@ -71,7 +70,9 @@ type NewItem = {
label: string;
icon: ReactNode;
link: string;
docsLink: string;
show: boolean;
longDescription: ReactNode;
};
interface INewInUnleashProps {
@ -86,7 +87,6 @@ export const NewInUnleash = ({
onMiniModeClick,
}: INewInUnleashProps) => {
const { trackEvent } = usePlausibleTracker();
const navigate = useNavigate();
const [seenItems, setSeenItems] = useLocalStorageState(
'new-in-unleash-seen:v1',
new Set(),
@ -99,7 +99,35 @@ export const NewInUnleash = ({
label: 'Signals & Actions',
icon: <StyledSignalsIcon />,
link: '/integrations/signals',
docsLink: 'https://docs.getunleash.io/reference/signals',
show: isEnterprise() && signalsEnabled,
longDescription: (
<>
<p>
It allows you to respond to events in your real-time
monitoring system by automating tasks such as disabling
a beta feature in response to an increase in errors or a
drop in conversion rates.
</p>
<p>
<ul>
<li>
<b>Signal endpoints</b> are used to send signals
to Unleash. This allows you to integrate Unleash
with any external tool.
</li>
<li>
<b>Actions</b>, which are configured inside
projects, allow you to react to those signals
and enable or disable flags based on certain
conditions.
</li>
</ul>
</p>
</>
),
},
];
@ -135,31 +163,32 @@ export const NewInUnleash = ({
New in Unleash
</StyledNewInUnleashHeader>
<StyledNewInUnleashList>
{visibleItems.map(({ label, icon, link }) => (
<NewInUnleashItem
key={label}
icon={icon}
onClick={() => {
trackEvent('new-in-unleash-click', {
props: {
label,
},
});
navigate(link);
onItemClick?.();
}}
onDismiss={() => {
trackEvent('new-in-unleash-dismiss', {
props: {
label,
},
});
setSeenItems(new Set([...seenItems, label]));
}}
>
{label}
</NewInUnleashItem>
))}
{visibleItems.map(
({ label, icon, link, longDescription, docsLink }) => (
<NewInUnleashItem
onClick={() => {
trackEvent('new-in-unleash-click', {
props: {
label,
},
});
}}
onDismiss={() => {
trackEvent('new-in-unleash-dismiss', {
props: {
label,
},
});
setSeenItems(new Set([...seenItems, label]));
}}
label={label}
icon={icon}
link={link}
longDescription={longDescription}
docsLink={docsLink}
/>
),
)}
</StyledNewInUnleashList>
</StyledNewInUnleash>
);

View File

@ -1,12 +1,14 @@
import type { ReactNode } from 'react';
import type * as React from 'react';
import { type ReactNode, useState } from 'react';
import {
IconButton,
ListItem,
ListItemButton,
Tooltip,
styled,
Tooltip,
} from '@mui/material';
import Close from '@mui/icons-material/Close';
import { NewInUnleashTooltip } from './NewInUnleashTooltip';
const StyledItemButton = styled(ListItemButton)(({ theme }) => ({
justifyContent: 'space-between',
@ -30,37 +32,74 @@ interface INewInUnleashItemProps {
icon: ReactNode;
onClick: () => void;
onDismiss: () => void;
children: ReactNode;
label: string;
longDescription: ReactNode;
link: string;
docsLink: string;
}
const useTooltip = () => {
const [open, setOpen] = useState(false);
const handleTooltipClose = () => {
setOpen(false);
};
const handleTooltipOpen = () => {
setOpen(true);
};
return { open, handleTooltipOpen, handleTooltipClose };
};
export const NewInUnleashItem = ({
icon,
onClick,
onDismiss,
children,
label,
longDescription,
link,
docsLink,
}: INewInUnleashItemProps) => {
const { open, handleTooltipOpen, handleTooltipClose } = useTooltip();
const onDismissClick = (e: React.MouseEvent) => {
e.stopPropagation();
onDismiss();
};
return (
<ListItem disablePadding onClick={onClick}>
<StyledItemButton>
<StyledItemButtonContent>
{icon}
{children}
</StyledItemButtonContent>
<Tooltip title='Dismiss' arrow>
<StyledItemButtonClose
aria-label='dismiss'
onClick={onDismissClick}
size='small'
>
<Close fontSize='inherit' />
</StyledItemButtonClose>
</Tooltip>
</StyledItemButton>
<ListItem
disablePadding
onClick={() => {
onClick();
handleTooltipOpen();
}}
>
<NewInUnleashTooltip
open={open}
onClose={handleTooltipClose}
title={label}
longDescription={longDescription}
link={link}
docsLink={docsLink}
>
<StyledItemButton>
<StyledItemButtonContent>
{icon}
{label}
</StyledItemButtonContent>
<Tooltip title='Dismiss' arrow>
<StyledItemButtonClose
aria-label='dismiss'
onClick={onDismissClick}
size='small'
>
<Close fontSize='inherit' />
</StyledItemButtonClose>
</Tooltip>
</StyledItemButton>
</NewInUnleashTooltip>
</ListItem>
);
};

View File

@ -0,0 +1,129 @@
import type * as React from 'react';
import type { FC, ReactNode } from 'react';
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
import {
Box,
Button,
Link,
styled,
Typography,
ClickAwayListener,
} from '@mui/material';
import { type Link as RouterLink, useNavigate } from 'react-router-dom';
import OpenInNew from '@mui/icons-material/OpenInNew';
import { ReactComponent as UnleashLogo } from 'assets/img/logoWithWhiteText.svg';
const Header = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
borderRadius: `${theme.shape.borderRadiusMedium}px ${theme.shape.borderRadiusMedium}px 0 0`, // has to match the parent tooltip container
margin: theme.spacing(-1, -1.5), // has to match the parent tooltip container
padding: theme.spacing(2, 3),
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '120px',
}));
const Body = styled(Box)(({ theme }) => ({
padding: theme.spacing(2),
}));
const StyledLink = styled(Link<typeof RouterLink | 'a'>)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
padding: 0,
color: theme.palette.links,
fontWeight: theme.fontWeight.medium,
'&:hover, &:focus': {
textDecoration: 'underline',
},
}));
const StyledOpenInNew = styled(OpenInNew)(({ theme }) => ({
fontSize: theme.spacing(2.25),
}));
const StyledUnleashLogo = styled(UnleashLogo)({ width: '150px' });
const LongDescription = styled(Box)(({ theme }) => ({
ul: {
paddingLeft: theme.spacing(2),
},
}));
const Title = styled(Typography)(({ theme }) => ({
margin: theme.spacing(2, 0),
}));
const ReadMore = styled(Box)(({ theme }) => ({
margin: theme.spacing(3, 0),
}));
export const NewInUnleashTooltip: FC<{
children: React.ReactElement<any, any>;
title: string;
longDescription: ReactNode;
docsLink: string;
link: string;
open: boolean;
onClose: () => void;
}> = ({ children, title, longDescription, link, docsLink, open, onClose }) => {
const navigate = useNavigate();
return (
<HtmlTooltip
disableFocusListener
disableHoverListener
disableTouchListener
onClose={onClose}
open={open}
maxHeight={800}
maxWidth={350}
arrow
tabIndex={0}
placement='right-end'
title={
<ClickAwayListener onClickAway={onClose}>
<Box>
<Header>
<StyledUnleashLogo />
</Header>
<Body>
<Title>{title}</Title>
<LongDescription>{longDescription}</LongDescription>
<ReadMore>
<StyledLink
component='a'
href={docsLink}
underline='hover'
rel='noopener noreferrer'
target='_blank'
>
<StyledOpenInNew /> Read more in our
documentation
</StyledLink>
</ReadMore>
<Button
variant='contained'
color='primary'
type='submit'
size='small'
onClick={(event) => {
event.stopPropagation();
onClose();
navigate(link);
}}
>
Check it out
</Button>
</Body>
</Box>
</ClickAwayListener>
}
>
{children}
</HtmlTooltip>
);
};