1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-19 17:52:45 +02:00
unleash.unleash/frontend/src/component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider.tsx
Nuno Góis 4167a60588
feat: biome lint frontend (#4903)
Follows up on https://github.com/Unleash/unleash/pull/4853 to add Biome
to the frontend as well.


![image](https://github.com/Unleash/unleash/assets/14320932/1906faf1-fc29-4172-a4d4-b2716d72cd65)

Added a few `biome-ignore` to speed up the process but we may want to
check and fix them in the future.
2023-10-02 13:25:46 +01:00

207 lines
6.4 KiB
TypeScript

import { Box, Typography, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
import { IFeatureVariant } from 'interfaces/featureToggle';
const StyledContainer = styled(Box)(() => ({
display: 'flex',
width: '100%',
position: 'relative',
}));
const StyledTrack = styled(Box)(({ theme }) => ({
position: 'absolute',
height: theme.spacing(3),
width: '100%',
display: 'flex',
overflow: 'hidden',
}));
const StyledSegment = styled(Box)(() => ({
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
width: '100%',
}));
const StyledSegmentTrack = styled(Box, {
shouldForwardProp: (prop) => prop !== 'index',
})<{ index: number }>(({ theme, index }) => ({
height: theme.spacing(1.8),
width: '100%',
position: 'relative',
background: theme.palette.variants[index % theme.palette.variants.length],
}));
const StyledHeaderContainer = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
marginBottom: theme.spacing(1),
}));
const StyledTypography = styled(Typography)(({ theme }) => ({
marginY: theme.spacing(1),
}));
const StyledVariantBoxContainer = styled(Box)(() => ({
display: 'flex',
alignItems: 'center',
marginLeft: 'auto',
}));
const StyledVariantBox = styled(Box, {
shouldForwardProp: (prop) => prop !== 'index',
})<{ index: number }>(({ theme, index }) => ({
display: 'flex',
alignItems: 'center',
marginRight: theme.spacing(2),
'& div': {
width: theme.spacing(1.6),
height: theme.spacing(1.6),
borderRadius: '50%',
marginRight: theme.spacing(1),
background:
theme.palette.variants[index % theme.palette.variants.length],
},
}));
const StyledTypographySubtitle = styled(Typography)(({ theme }) => ({
marginTop: theme.spacing(1),
}));
interface ISplitPreviewSliderProps {
variants: IFeatureVariant[];
}
const SplitPreviewSlider = ({ variants }: ISplitPreviewSliderProps) => {
if (variants.length < 1) {
return null;
}
return (
<Box sx={(theme) => ({ marginTop: theme.spacing(2) })}>
<SplitPreviewHeader variants={variants} />
<StyledContainer>
<StyledTrack />
{variants.map((variant, index) => {
const value = variant.weight / 10;
return (
<TooltipResolver
variant='custom'
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
key={index}
arrow
onClick={(e) => e.preventDefault()}
titleComponent={
<SplitPreviewTooltip
variant={variant}
index={index}
/>
}
>
<Box
style={{
width: `${value}%`,
}}
>
{' '}
<StyledSegment>
<StyledSegmentTrack index={index} />
<StyledTypographySubtitle variant='subtitle2'>
{value}%
</StyledTypographySubtitle>
</StyledSegment>
</Box>
</TooltipResolver>
);
})}
</StyledContainer>
</Box>
);
};
const SplitPreviewHeader = ({ variants }: ISplitPreviewSliderProps) => {
return (
<StyledHeaderContainer>
<StyledTypography variant='body2'>
Feature variants ({variants.length})
</StyledTypography>
<StyledVariantBoxContainer>
{variants.map((variant, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<StyledVariantBox key={index} index={index}>
<Box />
<StyledTypography variant='body2'>
{variant.name}
</StyledTypography>
</StyledVariantBox>
))}
</StyledVariantBoxContainer>
</StyledHeaderContainer>
);
};
interface ISplitPreviewTooltip {
variant: IFeatureVariant;
index: number;
}
const StyledTooltipContainer = styled(Box)(() => ({
display: 'flex',
flexDirection: 'column',
}));
const StyledVariantContainer = styled(Box)(() => ({
display: 'flex',
alignItems: 'center',
minWidth: '250px',
}));
const StyledPayloadContainer = styled(Box)(({ theme }) => ({
marginTop: theme.spacing(1),
display: 'flex',
flexDirection: 'column',
}));
const StyledPayloadLabel = styled(Typography)(({ theme }) => ({
marginBottom: theme.spacing(1),
}));
const SplitPreviewTooltip = ({ variant, index }: ISplitPreviewTooltip) => {
return (
<StyledTooltipContainer>
<StyledVariantContainer>
<StyledVariantBox index={index}>
<Box />
</StyledVariantBox>
<Typography variant='subtitle2'>
{variant.weight / 10}% - {variant.name}
</Typography>
</StyledVariantContainer>
{variant.payload ? (
<StyledPayloadContainer>
<StyledPayloadLabel variant='body2'>
Payload
</StyledPayloadLabel>
<ConditionallyRender
condition={variant.payload.type === 'json'}
show={<code>{variant.payload.value}</code>}
elseShow={
<Typography variant='body2'>
{variant.payload.value}
</Typography>
}
/>
</StyledPayloadContainer>
) : null}
</StyledTooltipContainer>
);
};
export default SplitPreviewSlider;