1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-04 01:18:20 +02:00

chore: finish up disabled strategies (#9579)

Aligns the design of disabled strategies with the sketches. Most notable
changes:
- makes the disabled badge warning yellow
- greys out the preceding "or" separator
- makes the segment "preview" button *not* grey (because it's still
interactable)

As a bonus: uses a list for the constraint value lists instead of a div
and updates the design to match the sketches (no chips).


![image](https://github.com/user-attachments/assets/1b3ddfa0-b0e8-4856-ae01-26e507590a4f)

With strat variants:

![image](https://github.com/user-attachments/assets/dc143fbf-256b-4e96-872b-a6aa84df2111)


Bonus fix: 
Lets the constraint value list wrap so that we avoid this kind of
blowout:

![image](https://github.com/user-attachments/assets/4c0977ac-f8a4-41cc-8fb7-194e8b09c0a3)

Instead: 

![image](https://github.com/user-attachments/assets/a68ed4cf-c68c-43a1-9d6c-b90e85a0841f)
This commit is contained in:
Thomas Heartman 2025-03-19 15:40:23 +01:00 committed by GitHub
parent f5b26340e7
commit 038c10f612
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 38 deletions

View File

@ -1,4 +1,5 @@
import { Chip, type ChipProps, styled } from '@mui/material';
import { styled } from '@mui/material';
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
import type { FC, ReactNode } from 'react';
type StrategyItemProps = {
@ -19,6 +20,10 @@ const StyledContent = styled('div')(({ theme }) => ({
gap: theme.spacing(1),
flexWrap: 'wrap',
alignItems: 'center',
[`.${disabledStrategyClassName} &`]: {
filter: 'grayscale(1)',
color: theme.palette.text.secondary,
},
}));
const StyledType = styled('span')(({ theme }) => ({
@ -30,17 +35,23 @@ const StyledType = styled('span')(({ theme }) => ({
width: theme.spacing(10),
}));
const StyledValuesGroup = styled('div')(({ theme }) => ({
const StyledValuesGroup = styled('ul')(({ theme }) => ({
display: 'flex',
flexFlow: 'row wrap',
alignItems: 'center',
gap: theme.spacing(0.5),
listStyle: 'none',
padding: 0,
}));
const StyledValue = styled(({ ...props }: ChipProps) => (
<Chip size='small' {...props} />
))(({ theme }) => ({
padding: theme.spacing(0.5),
background: theme.palette.background.elevation1,
const StyledValue = styled('li')(({ theme }) => ({
[`.${disabledStrategyClassName} &`]: {
filter: 'grayscale(1)',
color: theme.palette.text.secondary,
},
':not(&:last-of-type)::after': {
content: '", "',
},
}));
/**
@ -58,7 +69,9 @@ export const StrategyEvaluationItem: FC<StrategyItemProps> = ({
{values && values?.length > 0 ? (
<StyledValuesGroup>
{values?.map((value, index) => (
<StyledValue key={`${value}#${index}`} label={value} />
<StyledValue key={`${value}#${index}`}>
{value}
</StyledValue>
))}
</StyledValuesGroup>
) : null}

View File

@ -8,6 +8,7 @@ import type { PlaygroundStrategySchema } from 'openapi';
import { Badge } from '../Badge/Badge';
import { Link } from 'react-router-dom';
import { Truncator } from '../Truncator/Truncator';
import { disabledStrategyClassName } from './disabled-strategy-utils';
type StrategyItemContainerProps = {
strategyHeaderLevel?: 1 | 2 | 3 | 4 | 5 | 6;
@ -87,7 +88,10 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
: ({ children }) => <> {children} </>;
return (
<Box sx={{ position: 'relative' }}>
<Box
className={strategy.disabled ? disabledStrategyClassName : ''}
sx={{ position: 'relative' }}
>
<StyledContainer style={style} className={className}>
<StyledHeader disabled={Boolean(strategy?.disabled)}>
{onDragStart ? (
@ -136,9 +140,6 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
</StyledHeaderContainer>
</StrategyHeaderLink>
{strategy.disabled ? (
<Badge color='disabled'>Disabled</Badge>
) : null}
{headerItemsLeft}
</StyledHeaderInner>
<Box
@ -148,6 +149,9 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
alignItems: 'center',
}}
>
{strategy.disabled ? (
<Badge color='warning'>Strategy disabled</Badge>
) : null}
{headerItemsRight}
</Box>
</StyledHeader>

View File

@ -0,0 +1,2 @@
export const disabledStrategyClassName =
'disabled-strategy-55d37c31-ca3f-4c19-bf86-9158824899bf';

View File

@ -13,6 +13,10 @@ const Chip = styled('div')(({ theme }) => ({
left: theme.spacing(4),
}));
export const StrategySeparator = () => {
return <Chip role='separator'>OR</Chip>;
export const StrategySeparator = ({ className }: { className?: string }) => {
return (
<Chip role='separator' className={className}>
OR
</Chip>
);
};

View File

@ -22,6 +22,7 @@ import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePla
import { ReleasePlan } from '../../../ReleasePlan/ReleasePlan';
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
import { ProjectEnvironmentStrategyDraggableItem } from './StrategyDraggableItem/ProjectEnvironmentStrategyDraggableItem';
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
interface IEnvironmentAccordionBodyProps {
isDisabled: boolean;
@ -77,6 +78,13 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
marginInline: theme.spacing(2), // should consider finding a variable here
}));
const StyledStrategySeparator = styled(StrategySeparator)(({ theme }) => ({
[`&:has(+ *:not(ol) .${disabledStrategyClassName}), &:has(+ ol > li:first-of-type .${disabledStrategyClassName})`]:
{
filter: 'grayscale(1)',
},
}));
export const EnvironmentAccordionBody = ({
featureEnvironment,
isDisabled,
@ -243,7 +251,7 @@ export const EnvironmentAccordionBody = ({
<StyledContentList>
{strategies.map((strategy, index) => (
<StyledListItem key={strategy.id}>
{index > 0 ? <StrategySeparator /> : null}
{index > 0 ? <StyledStrategySeparator /> : null}
<ProjectEnvironmentStrategyDraggableItem
strategy={strategy}
@ -268,7 +276,7 @@ export const EnvironmentAccordionBody = ({
<StyledContentList>
{page.map((strategy, index) => (
<StyledListItem key={strategy.id}>
{index > 0 ? <StrategySeparator /> : null}
{index > 0 ? <StyledStrategySeparator /> : null}
<ProjectEnvironmentStrategyDraggableItem
strategy={strategy}
@ -303,7 +311,7 @@ export const EnvironmentAccordionBody = ({
))}
{strategies.length > 0 ? (
<li>
<StrategySeparator />
<StyledStrategySeparator />
{strategyList}
</li>
) : null}

View File

@ -17,6 +17,7 @@ import { UPDATE_FEATURE_STRATEGY } from '@server/types/permissions';
import { StrategyDraggableItem } from './StrategyDraggableItem';
type ProjectEnvironmentStrategyDraggableItemProps = {
className?: string;
strategy: IFeatureStrategy;
environmentName: string;
index: number;
@ -36,6 +37,7 @@ type ProjectEnvironmentStrategyDraggableItemProps = {
const onDragNoOp = () => () => {};
export const ProjectEnvironmentStrategyDraggableItem = ({
className,
strategy,
index,
environmentName,
@ -74,6 +76,7 @@ export const ProjectEnvironmentStrategyDraggableItem = ({
return (
<Box
className={className}
key={strategy.id}
ref={ref}
onDragOver={onDragOver(ref, index)}

View File

@ -1,5 +1,4 @@
import type { FC } from 'react';
import { styled } from '@mui/material';
import type { FeatureStrategySchema } from 'openapi';
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
import { useUiFlag } from 'hooks/useUiFlag';
@ -13,12 +12,6 @@ import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
const FilterContainer = styled('div', {
shouldForwardProp: (prop) => prop !== 'grayscale',
})<{ grayscale: boolean }>(({ grayscale }) =>
grayscale ? { filter: 'grayscale(1)', opacity: 0.67 } : {},
);
type StrategyExecutionProps = {
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
displayGroupId?: boolean;
@ -52,7 +45,6 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
}
return (
<FilterContainer grayscale={strategy.disabled === true}>
<ConstraintsList>
{strategySegments?.map((segment) => (
<SegmentItem segment={segment} key={segment.id} />
@ -65,6 +57,5 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
))}
{isCustomStrategy ? customStrategyItems : strategyParameters}
</ConstraintsList>
</FilterContainer>
);
};