1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-12 01:17:04 +02:00

chore(1-3611): inline values list v1 (#9743)

Adds the easy parts of the inline values list: a list of chips that
shows you which values you have and that you can delete. You either
delete them by clicking the "clear" icon or by using del/backspace on
your keyboard.

If you use your keyboard we also handle switching your focus to the
appropriate element. By default, your browser may shift the focus to the
top of the window (which isn't very helpful). Instead, we handle it like
this:
- If you delete an item and there are more elements in the list: 
  - move the element to the next item if exists
  - if your element is the last item, move focus to the previous item
- if there are no more items in the list, move the focus to the Add
Values button

We still need to add the "add values" popover functionality. That's next
on the agenda.

Additionally, this switches how the containing flex container positions
its items along the cross axis (vertically) to "flex-start" instead of
"center". Because the values list can grow to multiple lines, it would
shift the "delete constraint" button and the constraint picker to the
middle of the expanded constraint. Now, instead they stay aligned to the
top. This causes a slight alignment issue with the button (due to the
invisible padding), but I don't want to look at that before the rest of
this is complete and we know how it all fits together. You'll notice
that the spacing between elements in that top row is also off anyway
(look at the value list being smushed up against the case sensitive
icon), so there's more work to do.

<img width="716" alt="image"
src="https://github.com/user-attachments/assets/225fcab8-03e4-46e3-92d4-82912eb40d46"
/>

Focus styles:

<img width="190" alt="image"
src="https://github.com/user-attachments/assets/6b07ab25-0a67-493c-9cac-839932b0d654"
/>

<img width="195" alt="image"
src="https://github.com/user-attachments/assets/9d5b323e-bf65-4eca-9008-a45ce0139a2b"
/>


Hover styles:
<img width="96" alt="image"
src="https://github.com/user-attachments/assets/f19e1945-d2be-4e87-8005-76cb6beb1f50"
/>
This commit is contained in:
Thomas Heartman 2025-04-10 15:50:51 +02:00 committed by GitHub
parent 57b1f406bc
commit e9ec1db3b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 115 additions and 15 deletions

View File

@ -39,6 +39,7 @@ import {
import { ConstraintOperatorSelect } from './ConstraintOperatorSelect';
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
import Delete from '@mui/icons-material/Delete';
import { ValueList } from './ValueList';
const Container = styled('article')(({ theme }) => ({
'--padding': theme.spacing(2),
@ -51,7 +52,7 @@ const TopRow = styled('div')(({ theme }) => ({
padding: 'var(--padding)',
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
alignItems: 'flex-start',
justifyItems: 'space-between',
borderBottom: `1px dashed ${theme.palette.divider}`,
}));
@ -377,21 +378,11 @@ export const EditableConstraint: FC<Props> = ({
{localConstraint.caseInsensitive ? 'Aa' : 'A/a'}
</StyledButton>
) : null}
{/* <ul>
<li>
<Chip
label='value1'
onDelete={() => console.log('Clicked')}
/>
</li>
<li>
<Chip
label='value2'
onDelete={() => console.log('Clicked')}
/>
</li>
</ul> */}
</ConstraintDetails>
<ValueList
values={localConstraint.values}
removeValue={removeValue}
/>
<HtmlTooltip title='Delete constraint' arrow>
<IconButton type='button' size='small' onClick={onDelete}>

View File

@ -0,0 +1,109 @@
import Add from '@mui/icons-material/Add';
import Clear from '@mui/icons-material/Clear';
import { Chip, type ChipProps, styled } from '@mui/material';
import { type FC, forwardRef, useRef } from 'react';
const ValueListWrapper = styled('div')(({ theme }) => ({
display: 'flex',
flexFlow: 'row wrap',
gap: theme.spacing(1),
}));
const StyledList = styled('ul')({
listStyle: 'none',
padding: 0,
display: 'contents',
});
const ValueChipBase = styled(
forwardRef<HTMLDivElement, ChipProps>((props, ref) => (
<Chip size='small' {...props} ref={ref} />
)),
)(({ theme }) => ({
transition: 'all 0.3s ease',
outline: `1px solid #0000`,
background: theme.palette.background.elevation1,
':hover, :focus-visible': {
background: theme.palette.background.elevation1,
},
':focus-visible': {
outlineColor: theme.palette.secondary.dark,
},
}));
const ValueChip = styled(ValueChipBase)(({ theme }) => ({
svg: {
fill: theme.palette.secondary.dark,
borderRadius: '50%',
outline: `2px solid #0000`,
transition: 'inherit',
':focus-visible,:hover': {
backgroundColor: theme.palette.table.headerHover,
outlineColor: theme.palette.table.headerHover,
},
},
}));
const AddValuesButton = styled(ValueChipBase)(({ theme }) => ({
color: theme.palette.primary.main,
svg: {
fill: theme.palette.primary.main,
height: theme.fontSizes.smallerBody,
width: theme.fontSizes.smallerBody,
},
':hover': {
outlineColor: theme.palette.secondary.dark,
},
}));
type Props = {
values: string[] | undefined;
removeValue: (index: number) => void;
};
export const ValueList: FC<Props> = ({ values = [], removeValue }) => {
const constraintElementRefs: React.MutableRefObject<
(HTMLDivElement | null)[]
> = useRef([]);
const addValuesButtonRef = useRef(null);
const nextFocusTarget = (deletedIndex: number) => {
if (deletedIndex === values.length - 1) {
if (deletedIndex === 0) {
return addValuesButtonRef.current;
} else {
return constraintElementRefs.current[deletedIndex - 1];
}
} else {
return constraintElementRefs.current[deletedIndex + 1];
}
};
return (
<ValueListWrapper>
<StyledList>
{values.map((value, index) => (
<li key={value}>
<ValueChip
ref={(el) => {
constraintElementRefs.current[index] = el;
}}
deleteIcon={<Clear />}
label={value}
onDelete={() => {
nextFocusTarget(index)?.focus();
removeValue(index);
}}
/>
</li>
))}
</StyledList>
<AddValuesButton
ref={addValuesButtonRef}
label={'Add values'}
onClick={() => console.log('adding values')}
icon={<Add />}
/>
</ValueListWrapper>
);
};