1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-09 01:17:06 +02:00
unleash.unleash/frontend/src/component/feature/FeatureView/FeatureOverview/StrategyDragTooltip.tsx
Thomas Heartman 138e93c41a
chore: drag-n-drop tooltip for strategies (#9623)
Implements the drag-n-drop tooltip the first time the user sees a
strategy drag handle on the feature env overview. It uses React Joyride,
which is the same system we use for the demo.

The design is a little different from the sketches because I couldn't
find a quick way to move the content (and the arrow) to be shifted
correctly.

If the demo is also active the first time a user visits a strategy page,
it'll render both the demo steps and this, but this tooltip doesn't
prevent the user from finishing the tour. It might be possible to avoid
that through checking state in localstorage, but I'd like to get this
approved first.

The tooltip uses the auth splash system to decide whether to show the
tooltip, meaning it's stored per user in the DB. To avoid it
re-rendering before you refetch from the back end, we also use a
temporary variable to check whether the user has closed it.

Rendered:

![image](https://github.com/user-attachments/assets/5912d055-10d5-4a1d-93f4-f12ff4ef7419)

If the tour is also active:

![image](https://github.com/user-attachments/assets/b0028a0f-3a0f-48aa-9ab9-8d7cf399055a)
2025-03-27 11:16:37 +01:00

102 lines
2.8 KiB
TypeScript

import Close from '@mui/icons-material/Close';
import { Box, Button, IconButton, styled } from '@mui/material';
import type { FC } from 'react';
import Joyride, { type TooltipRenderProps } from 'react-joyride';
const StyledTooltip = styled(Box)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
maxWidth: '300px',
background: '#201e42',
borderRadius: theme.shape.borderRadiusMedium,
color: theme.palette.common.white,
padding: theme.spacing(2),
paddingRight: theme.spacing(1),
fontSize: theme.typography.body2.fontSize,
}));
const OkButton = styled(Button)(({ theme }) => ({
color: theme.palette.secondary.border,
alignSelf: 'start',
marginLeft: theme.spacing(-1),
}));
const StyledCloseButton = styled(IconButton)(({ theme }) => ({
color: theme.palette.common.white,
background: 'none',
border: 'none',
position: 'absolute',
top: theme.spacing(1),
right: theme.spacing(1),
svg: {
width: theme.spacing(2),
height: theme.spacing(2),
},
}));
const StyledHeader = styled('p')(({ theme }) => ({
fontSize: theme.typography.body1.fontSize,
fontWeight: 'bold',
}));
const CustomTooltip = ({ closeProps }: TooltipRenderProps) => {
return (
<StyledTooltip component='article'>
<StyledCloseButton type='button' {...closeProps}>
<Close />
</StyledCloseButton>
<StyledHeader>Decide the order evaluation</StyledHeader>
<p>
Strategies are evaluated in the order presented here. Drag and
rearrange the strategies to get the order you prefer.
</p>
<OkButton
type='button'
data-action={closeProps['data-action']}
onClick={closeProps.onClick}
>
Ok, got it!
</OkButton>
</StyledTooltip>
);
};
type Props = {
show: boolean;
onClose: () => void;
};
export const StrategyDragTooltip: FC<Props> = ({ show, onClose }) => {
return (
<Joyride
callback={({ action }) => {
if (action === 'close') {
onClose();
}
}}
floaterProps={{
styles: {
arrow: {
color: '#201e42',
spread: 16,
length: 10,
},
},
}}
run={show}
disableOverlay
disableScrolling
tooltipComponent={CustomTooltip}
steps={[
{
disableBeacon: true,
offset: 0,
target: '.strategy-drag-handle',
content: <></>,
},
]}
/>
);
};