Skip to content

Commit

Permalink
Merge pull request #1543 from zetkin/issue-1423/autocomplete-resize
Browse files Browse the repository at this point in the history
Issue 1423/autocomplete resize
  • Loading branch information
rebecarubio authored Sep 29, 2023
2 parents 48df717 + 123f7bb commit 16d0337
Showing 1 changed file with 78 additions and 23 deletions.
101 changes: 78 additions & 23 deletions src/features/events/components/EventTypeAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { lighten } from '@mui/material/styles';
import makeStyles from '@mui/styles/makeStyles';
import { Add, Clear } from '@mui/icons-material';
import { Autocomplete, Box, TextField, Theme, Tooltip } from '@mui/material';
import { FC, useEffect, useState } from 'react';
import { FC, useEffect, useRef, useState } from 'react';

import EventTypesModel from '../models/EventTypesModel';
import messageIds from '../l10n/messageIds';
Expand All @@ -26,10 +26,25 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
borderColor: ({ showBorder }) =>
showBorder ? lighten(theme.palette.primary.main, 0.65) : '',
borderRadius: 10,
maxWidth: '200px',
paddingLeft: ({ showBorder }) => (showBorder ? 10 : 0),
paddingRight: ({ showBorder }) => (showBorder ? 0 : 10),
transition: 'all 0.2s ease',
},
span: {
// Same styles as input
'&:focus, &:hover': {
borderColor: lighten(theme.palette.primary.main, 0.65),
paddingLeft: 10,
paddingRight: 0,
},
border: '2px dotted transparent',
borderRadius: 10,
fontSize: '1rem',
paddingRight: 10,
// But invisible and positioned absolutely to not affect flow
position: 'absolute',
visibility: 'hidden',
},
}));

type EventTypeAutocompleteProps = {
Expand Down Expand Up @@ -58,21 +73,37 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
typesModel,
value,
}) => {
const messages = useMessages(messageIds);
const uncategorizedMsg = messages.type.uncategorized();
const [createdType, setCreatedType] = useState<string>('');
const [text, setText] = useState<string>(value?.title ?? uncategorizedMsg);
const [dropdownListWidth, setDropdownListWidth] = useState(0);

const spanRef = useRef<HTMLSpanElement>(null);
const classes = useStyles({ showBorder });
const messages = useMessages(messageIds);

useEffect(() => {
//When a user creates a new type, it is missing an event ID.
//In here, when the length of the type changes,
//it searches for the created event and updates event with an ID.
if (createdType !== '') {
const newId = types.find((item) => item.title === createdType)!.id;
onChangeNewOption(newId!);
const newEventType = types.find((item) => item.title === createdType);
setText(newEventType!.title);
onChangeNewOption(newEventType!.id);
}
}, [types.length]);

useEffect(() => {
if (spanRef.current) {
const width = spanRef.current.offsetWidth;
setDropdownListWidth(width);
}
}, [spanRef.current, text]);

useEffect(() => {
setText(value ? value.title : uncategorizedMsg);
}, [value]);

const allTypes: EventTypeOption[] = [
...types,
{
Expand All @@ -93,6 +124,12 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
classes={{
root: classes.inputRoot,
}}
componentsProps={{
popper: {
placement: 'bottom-start',
style: { maxWidth: 380, minWidth: 180, width: dropdownListWidth },
},
}}
disableClearable
filterOptions={(options, { inputValue }) => {
const searchedResults = fuse.search(inputValue);
Expand All @@ -109,7 +146,7 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
}),
{
id: 'UNCATEGORIZED',
title: messages.type.uncategorized(),
title: uncategorizedMsg,
},
];
if (
Expand All @@ -128,11 +165,21 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
});
return inputValue ? filteredResult : options;
}}
fullWidth
getOptionLabel={(option) => option.title!}
isOptionEqualToValue={(option, value) => option.title === value.title}
onBlur={() => onBlur()}
onBlur={() => {
// show 'uncategorized' in textField when blurring
if (!value && text !== uncategorizedMsg) {
setText(uncategorizedMsg);
}
//set text to previous input value when clicking away
if (value && text !== value.title) {
setText(value.title);
}
onBlur();
}}
onChange={(_, value) => {
setText(value.title);
if (value.id == 'CREATE') {
typesModel.addType(value.title!);
setCreatedType(value.title!);
Expand All @@ -150,19 +197,27 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
onFocus={() => onFocus()}
options={allTypes}
renderInput={(params) => (
<TextField
{...params}
InputLabelProps={{
shrink: false,
style: {
maxWidth: 180,
},
}}
InputProps={{
...params.InputProps,
}}
size="small"
/>
<>
<span ref={spanRef} className={classes.span}>
{text}
</span>
<TextField
{...params}
InputLabelProps={{
shrink: false,
}}
InputProps={{
...params.InputProps,
style: {
maxWidth: 380,
minWidth: 60,
width: dropdownListWidth + 50,
},
}}
onChange={(e) => setText(e.target.value)}
size="small"
/>
</>
)}
renderOption={(props, option) => {
return (
Expand All @@ -173,7 +228,7 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
{option.id == 'UNCATEGORIZED' && (
<li {...props}>
<Clear />
{messages.type.uncategorized()}
{uncategorizedMsg}
</li>
)}
{option.id == 'CREATE' && (
Expand All @@ -190,7 +245,7 @@ const EventTypeAutocomplete: FC<EventTypeAutocompleteProps> = ({
? value
: {
id: 'UNCATEGORIZED',
title: messages.type.uncategorized(),
title: text,
}
}
/>
Expand Down

0 comments on commit 16d0337

Please sign in to comment.