1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-19 17:52:45 +02:00

chore: update release templates empty states in new add strategy modal (#10656)

https://linear.app/unleash/issue/2-3876/update-the-release-templates-section-accordingly

Updates the release templates empty states in the new add strategy modal
to match the new design sketches.

Also fixes a few details in the modal base design.

<img width="989" height="583" alt="image"
src="https://github.com/user-attachments/assets/b3148fe1-eb61-48d5-84cb-3dc4381f7c0c"
/>

<img width="981" height="581" alt="image"
src="https://github.com/user-attachments/assets/54f9a4d7-8cde-4f4b-bc9d-dc7114d7e17f"
/>
This commit is contained in:
Nuno Góis 2025-09-11 11:19:55 +01:00 committed by GitHub
parent c0eedba400
commit be4665f3f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 51 deletions

View File

@ -38,8 +38,8 @@ const StyledContainer = styled(Box)(() => ({
})); }));
const StyledScrollableContent = styled(Box)(({ theme }) => ({ const StyledScrollableContent = styled(Box)(({ theme }) => ({
width: '100%', width: theme.breakpoints.values.md,
maxHeight: theme.spacing(62), height: theme.spacing(52),
overflowY: 'auto', overflowY: 'auto',
padding: theme.spacing(4), padding: theme.spacing(4),
paddingTop: theme.spacing(1), paddingTop: theme.spacing(1),

View File

@ -1,9 +1,9 @@
import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates'; import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import FactCheckOutlinedIcon from '@mui/icons-material/FactCheckOutlined'; import { ReactComponent as ReleaseTemplateIcon } from 'assets/img/releaseTemplates.svg';
import { FeatureReleasePlanCard } from '../FeatureReleasePlanCard/FeatureReleasePlanCard.tsx'; import { FeatureReleasePlanCard } from '../FeatureReleasePlanCard/FeatureReleasePlanCard.tsx';
import type { IReleasePlanTemplate } from 'interfaces/releasePlans.ts'; import type { IReleasePlanTemplate } from 'interfaces/releasePlans.ts';
import { Box, Button, styled, Typography } from '@mui/material'; import { Box, Button, styled } from '@mui/material';
import type { StrategyFilterValue } from './FeatureStrategyMenuCards.tsx'; import type { StrategyFilterValue } from './FeatureStrategyMenuCards.tsx';
import type { Dispatch, SetStateAction } from 'react'; import type { Dispatch, SetStateAction } from 'react';
import { Link as RouterLink } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom';
@ -14,38 +14,61 @@ import {
const RELEASE_TEMPLATE_DISPLAY_LIMIT = 5; const RELEASE_TEMPLATE_DISPLAY_LIMIT = 5;
const StyledIcon = styled('span')(({ theme }) => ({ const StyledIcon = styled('span', {
width: theme.spacing(3), shouldForwardProp: (prop) => prop !== 'solo',
})<{ solo?: boolean }>(({ theme, solo }) => ({
'& > svg': { '& > svg': {
fill: theme.palette.primary.main, fill: theme.palette.primary.main,
width: theme.spacing(2.25), width: theme.spacing(6),
height: theme.spacing(2.25), height: theme.spacing(6),
...(solo && {
width: theme.spacing(10),
height: theme.spacing(10),
}),
}, },
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
})); }));
const StyledNoTemplatesContainer = styled(Box)(({ theme }) => ({ const StyledNoTemplatesContainer = styled(Box, {
display: 'flex', shouldForwardProp: (prop) => prop !== 'solo',
flexDirection: 'column', })<{ solo?: boolean }>(({ theme, solo }) => ({
alignItems: 'flex-start',
justifyContent: 'flex-start',
backgroundColor: theme.palette.neutral.light,
borderRadius: theme.shape.borderRadiusMedium,
padding: theme.spacing(3),
width: 'auto',
}));
const StyledNoTemplatesTitle = styled(Typography)(({ theme }) => ({
fontSize: theme.typography.caption.fontSize,
fontWeight: theme.typography.fontWeightBold,
marginBottom: theme.spacing(1),
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
backgroundColor: theme.palette.neutral.light,
borderRadius: theme.shape.borderRadiusMedium,
padding: theme.spacing(2),
gap: theme.spacing(1),
width: 'auto',
...(solo && {
backgroundColor: undefined,
flexDirection: 'column',
maxWidth: theme.spacing(70),
margin: 'auto',
gap: theme.spacing(2.5),
}),
})); }));
const StyledNoTemplatesDescription = styled(Typography)(({ theme }) => ({ const StyledNoTemplatesBody = styled(Box, {
shouldForwardProp: (prop) => prop !== 'solo',
})<{ solo?: boolean }>(({ theme, solo }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(0.5),
fontSize: theme.typography.caption.fontSize, fontSize: theme.typography.caption.fontSize,
...(solo && {
alignItems: 'center',
textAlign: 'center',
gap: theme.spacing(2),
fontSize: theme.typography.body2.fontSize,
}),
}));
const StyledNoTemplatesTitle = styled('p')(({ theme }) => ({
fontWeight: theme.typography.fontWeightBold,
}));
const StyledNoTemplatesDescription = styled('p')(({ theme }) => ({
color: theme.palette.text.secondary, color: theme.palette.text.secondary,
})); }));
@ -83,34 +106,46 @@ export const FeatureStrategyMenuCardsReleaseTemplates = ({
return null; return null;
} }
const slicedTemplates = const isFiltered = filter === 'releaseTemplates';
filter === 'releaseTemplates' const shouldShowHeader = !isFiltered || templates.length > 0;
? templates
: templates.slice(0, RELEASE_TEMPLATE_DISPLAY_LIMIT); const slicedTemplates = isFiltered
? templates
: templates.slice(0, RELEASE_TEMPLATE_DISPLAY_LIMIT);
return ( return (
<Box> <Box>
<StyledStrategyModalSectionHeader> {shouldShowHeader && (
<Typography color='inherit' variant='body2'> <StyledStrategyModalSectionHeader>
Release templates Release templates
</Typography> </StyledStrategyModalSectionHeader>
</StyledStrategyModalSectionHeader> )}
{!templates.length ? ( {!templates.length ? (
<StyledNoTemplatesContainer> <StyledNoTemplatesContainer solo={isFiltered}>
<StyledNoTemplatesTitle> <StyledIcon solo={isFiltered}>
<StyledIcon> <ReleaseTemplateIcon />
<FactCheckOutlinedIcon /> </StyledIcon>
</StyledIcon> <StyledNoTemplatesBody solo={isFiltered}>
Create your own release templates <StyledNoTemplatesTitle>
</StyledNoTemplatesTitle> You don't have any release templates set up yet
<StyledNoTemplatesDescription> </StyledNoTemplatesTitle>
Standardize your rollouts and save time by reusing <StyledNoTemplatesDescription>
predefined strategies. Find release templates in the Go to{' '}
side menu under{' '} <StyledLink to='/release-templates'>
<StyledLink to='/release-templates'> Configure &gt; Release templates
Configure &gt; Release templates </StyledLink>{' '}
</StyledLink> in the side menu to make your rollouts more
</StyledNoTemplatesDescription> efficient and streamlined. Read more in our{' '}
<StyledLink
to='https://docs.getunleash.io/reference/release-templates'
target='_blank'
rel='noreferrer'
>
documentation
</StyledLink>
.
</StyledNoTemplatesDescription>
</StyledNoTemplatesBody>
</StyledNoTemplatesContainer> </StyledNoTemplatesContainer>
) : ( ) : (
<FeatureStrategyMenuCardsSection> <FeatureStrategyMenuCardsSection>

View File

@ -1,4 +1,4 @@
import { Box, styled, Typography } from '@mui/material'; import { Box, styled } from '@mui/material';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
export const StyledStrategyModalSectionHeader = styled(Box)(({ theme }) => ({ export const StyledStrategyModalSectionHeader = styled(Box)(({ theme }) => ({
@ -7,6 +7,7 @@ export const StyledStrategyModalSectionHeader = styled(Box)(({ theme }) => ({
gap: theme.spacing(0.5), gap: theme.spacing(0.5),
marginBottom: theme.spacing(0.5), marginBottom: theme.spacing(0.5),
width: '100%', width: '100%',
fontSize: theme.typography.body2.fontSize,
})); }));
const StyledStrategyModalSectionGrid = styled(Box)(({ theme }) => ({ const StyledStrategyModalSectionGrid = styled(Box)(({ theme }) => ({
@ -28,9 +29,7 @@ export const FeatureStrategyMenuCardsSection = ({
<Box> <Box>
{title && ( {title && (
<StyledStrategyModalSectionHeader> <StyledStrategyModalSectionHeader>
<Typography color='inherit' variant='body2'> {title}
{title}
</Typography>
</StyledStrategyModalSectionHeader> </StyledStrategyModalSectionHeader>
)} )}
<StyledStrategyModalSectionGrid> <StyledStrategyModalSectionGrid>