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:
parent
57b1f406bc
commit
e9ec1db3b7
@ -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}>
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user