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

chore: second design pass for editable constraints (#9843)

Fix a number of visual issues with the main editable constraint
component.

I've introduced a few more layers of container nesting to make the
layout break the right ways:
- Put everything on the same line when on wide.
- At 700px place selected values on the row below
- From 700px down, when necessary, also wrap operator options


Support super long context names without breaking layout
<img width="399" alt="image"
src="https://github.com/user-attachments/assets/07555e9c-d875-417f-ae6b-d4600731d5eb"
/>

Wrap values at 700px width container:
<img width="703" alt="image"
src="https://github.com/user-attachments/assets/deb6e059-57d4-4e47-88da-3ec5d6bce751"
/>

Wrap operator options when necessary
<img width="359" alt="image"
src="https://github.com/user-attachments/assets/ff96db40-f47d-4ddf-bed7-dfced4d69973"
/>

Absolutely position delete button to allow to not push it out of the
container on narrow screens:
<img width="330" alt="image"
src="https://github.com/user-attachments/assets/c7b8f88d-538a-46a1-ae3f-e5a761b50289"
/>

Remove extra focus styling from MUI (darken select background):
Before:
<img width="348" alt="image"
src="https://github.com/user-attachments/assets/99aff08d-c1af-46c0-8a75-40c1ea3c103f"
/>

<img width="357" alt="image"
src="https://github.com/user-attachments/assets/b7a0edac-2716-48a7-b50c-b3437e5f5be8"
/>

After:
<img width="379" alt="image"
src="https://github.com/user-attachments/assets/74da884c-7b1a-4b9a-8383-31592326a71b"
/>
<img width="350" alt="image"
src="https://github.com/user-attachments/assets/0ebea696-5f7d-4d4e-b91c-b087a8fc56a3"
/>
This commit is contained in:
Thomas Heartman 2025-04-25 12:37:04 +02:00 committed by GitHub
parent 44e9023fb3
commit 44082b24a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 105 additions and 49 deletions

View File

@ -47,6 +47,9 @@ const StyledSelect = styled(Select)(({ theme }) => ({
'.MuiInput-input': {
paddingBlock: theme.spacing(0.25),
},
':focus-within .MuiSelect-select': {
background: 'none',
},
}));
const StyledMenuItem = styled(MenuItem, {

View File

@ -32,22 +32,44 @@ const Container = styled('article')(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadiusLarge,
border: `1px solid ${theme.palette.divider}`,
containerType: 'inline-size',
}));
const onNarrowContainer = '@container (max-width: 700px)';
const TopRow = styled('div')(({ theme }) => ({
'--gap': theme.spacing(1),
padding: 'var(--padding)',
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'flex-start',
justifyItems: 'space-between',
gap: 'var(--gap)',
}));
const ConstraintOptions = styled('div')(({ theme }) => ({
display: 'flex',
flexFlow: 'row nowrap',
gap: 'var(--gap)',
alignSelf: 'flex-start',
[onNarrowContainer]: {
flexFlow: 'row wrap',
},
}));
const OperatorOptions = styled(ConstraintOptions)(({ theme }) => ({
flexFlow: 'row nowrap',
}));
const ConstraintDetails = styled('div')(({ theme }) => ({
display: 'flex',
gap: theme.spacing(1),
gap: 'var(--gap)',
flexFlow: 'row nowrap',
width: '100%',
height: 'min-content',
[onNarrowContainer]: {
flexDirection: 'column',
},
}));
const InputContainer = styled('div')(({ theme }) => ({
@ -57,6 +79,10 @@ const InputContainer = styled('div')(({ theme }) => ({
const StyledSelect = styled(GeneralSelect)(({ theme }) => ({
fieldset: { border: 'none', borderRadius: 0 },
maxWidth: '25ch',
':focus-within .MuiSelect-select': {
background: 'none',
},
':focus-within fieldset': { borderBottomStyle: 'solid' },
'label + &': {
// mui adds a margin top to 'standard' selects with labels
@ -67,10 +93,19 @@ const StyledSelect = styled(GeneralSelect)(({ theme }) => ({
},
}));
const StyledIconButton = styled(IconButton)(({ theme }) => ({
position: 'absolute',
right: theme.spacing(1),
}));
const StyledButton = styled('button')(({ theme }) => ({
// todo (`addEditStrategy`): this is pretty rough, but it needs to be the
// same height as the input fields, which are 27.25 px at the moment.
// Consider editing this when we get new icons for the buttons. There may be
// a better solution.
height: `calc(${theme.typography.body1.fontSize} + ${theme.spacing(1.5)})`,
width: '5ch',
borderRadius: theme.shape.borderRadius,
padding: theme.spacing(0.25, 0),
fontSize: theme.fontSizes.smallerBody,
background: theme.palette.secondary.light,
border: `1px solid ${theme.palette.secondary.border}`,
@ -82,6 +117,14 @@ const StyledButton = styled('button')(({ theme }) => ({
},
}));
const ButtonPlaceholder = styled('div')(({ theme }) => ({
// this is a trick that lets us use absolute positioning for the button so
// that it can go over the operator context fields when necessary (narrow
// screens), but still retain necessary space for the button when it's all
// on one line.
width: theme.spacing(2),
}));
const StyledCaseInsensitiveIcon = styled(CaseInsensitiveIcon)(({ theme }) => ({
path: {
fill: theme.palette.text.disabled,
@ -218,6 +261,7 @@ export const EditableConstraint: FC<Props> = ({
<Container>
<TopRow>
<ConstraintDetails>
<ConstraintOptions>
<StyledSelect
visuallyHideLabel
id='context-field-select'
@ -230,6 +274,7 @@ export const EditableConstraint: FC<Props> = ({
variant='standard'
/>
<OperatorOptions>
<StyledButton
type='button'
onClick={toggleInvertedOperator}
@ -263,7 +308,8 @@ export const EditableConstraint: FC<Props> = ({
</ScreenReaderOnly>
</CaseButton>
) : null}
</OperatorOptions>
</ConstraintOptions>
<ValueList
values={localConstraint.values}
removeValue={removeValue}
@ -290,16 +336,16 @@ export const EditableConstraint: FC<Props> = ({
) : null}
</ValueList>
</ConstraintDetails>
<ButtonPlaceholder />
<HtmlTooltip title='Delete constraint' arrow>
<IconButton
<StyledIconButton
type='button'
size='small'
onClick={onDelete}
ref={deleteButtonRef}
>
<Delete />
</IconButton>
<Delete fontSize='inherit' />
</StyledIconButton>
</HtmlTooltip>
</TopRow>
{showInputField ? (

View File

@ -94,6 +94,13 @@ export const ValueList: FC<PropsWithChildren<Props>> = ({
ref={(el) => {
constraintElementRefs.current[index] = el;
}}
sx={{
height: 'auto',
'& .MuiChip-label': {
display: 'block',
whiteSpace: 'normal',
},
}}
deleteIcon={<Clear />}
label={value}
onDelete={() => {