Skip to content

Commit

Permalink
#103: instead of wrapping the input into a button (which slurps space…
Browse files Browse the repository at this point in the history
… key), handle space only case to open combobox manually
  • Loading branch information
toggm committed Dec 9, 2024
1 parent 6ae29b2 commit f6d37ac
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ export const InputSelectAutocomplete: React.FC<Props> = ({
render={({ field: { value, onChange } }) => (
<Combobox
value={value}
onChange={(change: SelectAutocompleteSuggestionType) => onChange(change.id)}
onChange={(change: SelectAutocompleteSuggestionType) => {
if (change?.id) {
onChange(change.id);
}
}}
>
{({ open }) => (
<>
Expand Down
85 changes: 43 additions & 42 deletions frontend/src/components/forms/input/inputTagsAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@
*
*/

import {
Combobox,
ComboboxButton,
ComboboxInput,
ComboboxOptions,
ComboboxOption,
} from '@headlessui/react';
import { Combobox, ComboboxInput, ComboboxOptions, ComboboxOption } from '@headlessui/react';
import { Tag, TagList } from 'components/shared/tagList';
import { differenceBy, filter, noop, uniqBy } from 'lodash';
import { useTranslation } from 'next-i18next';
Expand Down Expand Up @@ -75,15 +69,17 @@ export const InputTagsAdmin: React.FC<Props> = ({ name, tags = [], tagGroupIndex
};

const addTag = (tag: any) => {
const tags = uniqBy([...selectedTags, tag], 'id');
setInputText('');
setSelectedTags(tags);
if (name === 'tagGroups') {
const currentTags = parentFormContext.getValues(name);
currentTags[tagGroupIndex].relatedTags = tags;
parentFormContext.setValue(name, currentTags);
} else {
parentFormContext.setValue(name, tags);
if (tag) {
const tags = uniqBy([...selectedTags, tag], 'id');
setInputText('');
setSelectedTags(tags);
if (name === 'tagGroups') {
const currentTags = parentFormContext.getValues(name);
currentTags[tagGroupIndex].relatedTags = tags;
parentFormContext.setValue(name, currentTags);
} else {
parentFormContext.setValue(name, tags);
}
}
};

Expand All @@ -97,6 +93,15 @@ export const InputTagsAdmin: React.FC<Props> = ({ name, tags = [], tagGroupIndex
if (inputText) e.preventDefault();
};

const inputValueChanged = (e: any) => {
if (e.currentTarget.value == ' ') {
// ignore initial space as this should only open the combobox
setInputText('');
} else {
setInputText(e.currentTarget.value);
}
};

return (
<Box sx={{ label: 'InputTagsAdmin' }}>
{Array.isArray(selectedTags) && selectedTags.length > 0 && (
Expand All @@ -112,32 +117,28 @@ export const InputTagsAdmin: React.FC<Props> = ({ name, tags = [], tagGroupIndex
<Combobox value={selectedTags} onChange={addTag}>
{({ open }) => (
<>
{/* Wrapping the input with a Button is a hack for https://github.com/tailwindlabs/headlessui/discussions/1236,
Without that the combobox does not open when you click in the input */}
<ComboboxButton as={Box}>
<ComboboxInput
as={Input}
onChange={(e) => setInputText(e.currentTarget.value)}
onClick={preventDefault}
displayValue={() => inputText}
placeholder={t('Enter a tag to add it')}
autoComplete="off"
/>
{inputText && (
<Box
sx={{
position: 'absolute',
right: 2,
top: '50%',
transform: 'translateY(-50%)',
...clickableStyle(),
}}
onClick={() => setInputText('')}
>
<Icon name="remove-circle-interface-essential" size={20} />
</Box>
)}
</ComboboxButton>
<ComboboxInput
as={Input}
onChange={inputValueChanged}
onClick={preventDefault}
displayValue={() => inputText}
placeholder={t('Enter a tag to add it')}
autoComplete="off"
/>
{inputText && (
<Box
sx={{
position: 'absolute',
right: 2,
top: '50%',
transform: 'translateY(-50%)',
...clickableStyle(),
}}
onClick={() => setInputText('')}
>
<Icon name="remove-circle-interface-essential" size={20} />
</Box>
)}
<ComboboxOptions as={Box}>
{open && displayCreateTag && (
<DropdownList sx={{ px: 2, display: 'flex', gap: 0, flexWrap: 'wrap' }}>
Expand Down
66 changes: 33 additions & 33 deletions frontend/src/components/forms/input/inputTagsAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@
*
*/

import {
Combobox,
ComboboxInput,
ComboboxButton,
ComboboxOptions,
ComboboxOption,
} from '@headlessui/react';
import { Combobox, ComboboxInput, ComboboxOptions, ComboboxOption } from '@headlessui/react';
import { DropdownList } from 'components/forms/input/shared/dropdownList';
import { Tag, TagList } from 'components/shared/tagList';
import { cleanStrForCmp } from 'lib/strings';
Expand Down Expand Up @@ -96,6 +90,15 @@ export const InputTagsAutocomplete: React.FC<Props> = ({ suggestions = [], name
if (inputText) e.preventDefault();
};

const inputValueChanged = (e: any) => {
if (e.currentTarget.value == ' ') {
// ignore initial space as this should only open the combobox
setInputText('');
} else {
setInputText(e.currentTarget.value);
}
};

return (
<Box sx={{ label: 'InputTagsAutocomplete' }}>
{selectedTags.length > 0 && (
Expand All @@ -111,32 +114,29 @@ export const InputTagsAutocomplete: React.FC<Props> = ({ suggestions = [], name
<Combobox value={selectedTags} onChange={addTag}>
{({ open }) => (
<>
{/* Wrapping the input with a Button is a hack for https://github.com/tailwindlabs/headlessui/discussions/1236,
Without that the combobox does not open when you click in the input */}
<ComboboxButton as={Box}>
<ComboboxInput
as={Input}
onChange={(e) => setInputText(e.currentTarget.value)}
onClick={preventDefault}
displayValue={() => inputText}
placeholder={t('Choose or enter tags')}
autoComplete="off"
/>
{inputText && (
<Box
sx={{
position: 'absolute',
right: 2,
top: '50%',
transform: 'translateY(-50%)',
...clickableStyle(),
}}
onClick={() => setInputText('')}
>
<Icon name="remove-circle-interface-essential" size={20} />
</Box>
)}
</ComboboxButton>
<ComboboxInput
as={Input}
onChange={inputValueChanged}
onClick={preventDefault}
displayValue={() => inputText}
placeholder={t('Choose or enter tags')}
autoComplete="off"
value={inputText}
/>
{inputText && (
<Box
sx={{
position: 'absolute',
right: 2,
top: '50%',
transform: 'translateY(-50%)',
...clickableStyle(),
}}
onClick={() => setInputText('')}
>
<Icon name="remove-circle-interface-essential" size={20} />
</Box>
)}
<ComboboxOptions as={Box}>
{open && (displayCreateTag || availableSuggestions.length > 0) && (
<DropdownList sx={{ px: 2, display: 'flex', gap: 0, flexWrap: 'wrap' }}>
Expand Down

0 comments on commit f6d37ac

Please sign in to comment.