Conversation
| // Delay to allow click events to fire first (longer for Android) | ||
| setTimeout(() => onClose(), 150) | ||
| } | ||
| }} |
There was a problem hiding this comment.
Stale timeout causes sheet to close unexpectedly
Medium Severity
The setTimeout(() => onClose(), 150) in the search input's onBlur handler is never cleaned up. If a user closes the bottom sheet (e.g., by selecting an option) and quickly reopens it within 150ms, the stale timeout will fire and call onClose(), unexpectedly closing the newly opened sheet. The timeout reference needs to be stored in a ref and cleared when the sheet closes or when the component unmounts.
| const { children, ...rest } = props | ||
| // children is an array: [ClearIndicator, IndicatorSeparator, DropdownIndicator] | ||
| // Reverse to put dropdown first, then clear on the outside | ||
| const reversed = children ? [...children].reverse() : children |
There was a problem hiding this comment.
Spreading children may fail for single element
Low Severity
The [...children].reverse() pattern assumes children is always an array. In React, when there's exactly one child, props.children is that single React element rather than an array. Spreading a non-iterable React element would throw a TypeError. Using React.Children.toArray(children).reverse() handles all cases safely, as demonstrated elsewhere in the codebase in table-of-contents.js.
| document.body.style.left = '' | ||
| document.body.style.right = '' | ||
| document.body.style.overflow = '' | ||
| } |
There was a problem hiding this comment.
Scroll position lost when component unmounts while open
Medium Severity
The cleanup function for the scroll-lock effect resets body styles but doesn't restore the scroll position. When isOpen transitions from true to false, scroll is properly restored in the else branch. However, if the component unmounts while the sheet is open (e.g., via navigation), only the cleanup runs - it clears document.body.style.top without first reading the stored scroll value and calling window.scrollTo(). This causes the page to jump to the top when the user navigates away with the sheet open.
This is an attempt at creating a better multi-select UI for mobile. It's a full width scrollable modal "sheet" that comes up from the bottom when the select is clicked. You can drag it down, click off, hit 'done' on the keyboard, or make a selection to close it.
It works prrrretty great. It's entirely vibed though and I haven't reviewed it much.
Note
Implements a mobile-first multi-select experience and refines desktop behavior.
useIsMobileand a mobile bottom-sheet forMultiSelectwith searchable options, selection toggling, drag-to-close, backdrop click, keyboard-aware layout, and body scroll lockinghandleChange, plus helpers (toggleOption,removeValue,clearAll); preservesonChange(formik, values)behaviormaxMenuHeight/menuPlacement, reverses indicators via customIndicatorsContainer, and keeps custom label/remove componentsmulti-select.module.css: mobile control/overlay/sheet styles, touch target sizing, indicator/tag layout updates, hover-safe media queries, and menu/option truncation improvementsWritten by Cursor Bugbot for commit 6b9f2d5. This will update automatically on new commits. Configure here.