diff --git a/webapp/src/properties/multiselect/multiselect.test.tsx b/webapp/src/properties/multiselect/multiselect.test.tsx
index 3807d5e40..24d9a3b42 100644
--- a/webapp/src/properties/multiselect/multiselect.test.tsx
+++ b/webapp/src/properties/multiselect/multiselect.test.tsx
@@ -57,6 +57,12 @@ describe('properties/multiSelect', () => {
const board = createBoard()
const card = createCard()
+ const expectOptionsMenuToBeVisible = (template: IPropertyTemplate) => {
+ for (const option of template.options) {
+ expect(screen.getByRole('menuitem', {name: option.value})).toBeInTheDocument()
+ }
+ }
+
beforeEach(() => {
jest.resetAllMocks()
})
@@ -128,6 +134,7 @@ describe('properties/multiSelect', () => {
userEvent.type(screen.getByRole('combobox', {name: /value selector/i}), 'b{enter}')
expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, ['multi-option-1', 'multi-option-2'])
+ expectOptionsMenuToBeVisible(propertyTemplate)
})
it('can unselect a option', async () => {
@@ -152,6 +159,58 @@ describe('properties/multiSelect', () => {
userEvent.click(screen.getAllByRole('button', {name: /clear/i})[0])
expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, ['multi-option-2'])
+ expectOptionsMenuToBeVisible(propertyTemplate)
+ })
+
+ it('can unselect a option via backspace', async () => {
+ const propertyTemplate = buildMultiSelectPropertyTemplate()
+ const propertyValue = ['multi-option-1', 'multi-option-2']
+
+ render(
+ ,
+ {wrapper: Wrapper},
+ )
+
+ userEvent.click(screen.getByTestId(nonEditableMultiSelectTestId))
+
+ userEvent.type(screen.getByRole('combobox', {name: /value selector/i}), '{backspace}')
+
+ expect(mockedMutator.changePropertyValue).toHaveBeenCalledWith(board.id, card, propertyTemplate.id, ['multi-option-1'])
+ expectOptionsMenuToBeVisible(propertyTemplate)
+ })
+
+ it('can close menu on escape', async () => {
+ const propertyTemplate = buildMultiSelectPropertyTemplate()
+ const propertyValue = ['multi-option-1', 'multi-option-2']
+
+ render(
+ ,
+ {wrapper: Wrapper},
+ )
+
+ userEvent.click(screen.getByTestId(nonEditableMultiSelectTestId))
+
+ userEvent.type(screen.getByRole('combobox', {name: /value selector/i}), '{escape}')
+
+ for (const option of propertyTemplate.options) {
+ expect(screen.queryByRole('menuitem', {name: option.value})).toBeNull()
+ }
})
it('can create a new option', async () => {
@@ -177,6 +236,7 @@ describe('properties/multiSelect', () => {
userEvent.type(screen.getByRole('combobox', {name: /value selector/i}), 'new-value{enter}')
expect(mockedMutator.insertPropertyOption).toHaveBeenCalledWith(board.id, board.cardProperties, propertyTemplate, expect.objectContaining({value: 'new-value'}), 'add property option')
+ expectOptionsMenuToBeVisible(propertyTemplate)
})
it('can delete a option', () => {
diff --git a/webapp/src/widgets/valueSelector.scss b/webapp/src/widgets/valueSelector.scss
index d0053e8f9..08d44914c 100644
--- a/webapp/src/widgets/valueSelector.scss
+++ b/webapp/src/widgets/valueSelector.scss
@@ -30,8 +30,8 @@
.IconButton.delete-value {
@include z-index(value-selector-delete);
width: 16px;
- min-width: 16px;
height: 16px;
+ flex: 0 0 auto;
i {
font-size: 16px;
diff --git a/webapp/src/widgets/valueSelector.tsx b/webapp/src/widgets/valueSelector.tsx
index 21092ad72..4c701c051 100644
--- a/webapp/src/widgets/valueSelector.tsx
+++ b/webapp/src/widgets/valueSelector.tsx
@@ -71,7 +71,10 @@ const ValueSelectorLabel = (props: LabelProps): JSX.Element => {
)
}
return (
-
+
@@ -162,7 +165,6 @@ function ValueSelector(props: Props): JSX.Element {
captureMenuScroll={true}
maxMenuHeight={1200}
isMulti={props.isMulti}
- menuIsOpen={true}
isClearable={true}
styles={valueSelectorStyle}
formatOptionLabel={(option: IPropertyOption, meta: FormatOptionLabelMeta
) => (
@@ -181,24 +183,32 @@ function ValueSelector(props: Props): JSX.Element {
getOptionLabel={(o: IPropertyOption) => o.value}
getOptionValue={(o: IPropertyOption) => o.id}
onChange={(value: OnChangeValue, action: ActionMeta): void => {
- if (action.action === 'select-option') {
+ if (action.action === 'select-option' || action.action === 'pop-value') {
if (Array.isArray(value)) {
props.onChange((value as IPropertyOption[]).map((option) => option.id))
} else {
props.onChange((value as IPropertyOption).id)
+ props.onBlur?.()
}
} else if (action.action === 'clear') {
props.onChange('')
}
}}
+ onKeyDown={(event) => {
+ if (event.key === 'Escape') {
+ props.onBlur?.()
+ }
+ }}
onBlur={props.onBlur}
onCreateOption={props.onCreate}
autoFocus={true}
value={props.value || null}
- closeMenuOnSelect={true}
+ closeMenuOnSelect={!props.isMulti}
placeholder={props.emptyValue}
hideSelectedOptions={false}
defaultMenuIsOpen={true}
+ menuIsOpen={props.isMulti}
+ blurInputOnSelect={!props.isMulti}
/>
)
}