From 1dd01e0ecab7bb70d007d61c7c4814ac91df3342 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Fri, 14 Aug 2026 08:55:25 -0400 Subject: [PATCH] Fix: Fixing Select start render below the modal make it rendioner in modal but keep the modal small so completely overlap with it. fixing that by applying custom global class --- src/contexts/ThemeContext.jsx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/contexts/ThemeContext.jsx b/src/contexts/ThemeContext.jsx index 955056f..cefd00e 100644 --- a/src/contexts/ThemeContext.jsx +++ b/src/contexts/ThemeContext.jsx @@ -31,6 +31,32 @@ const primaryPalette = getPalette(primaryColor) const CONTROL_RADIUS = '12px' const ICON_BUTTON_RADIUS = '10px' +// Select and Autocomplete both render their popup through @mui/base's Popper, +// which defaults to popper.js's `absolute` strategy — the popup is laid out in +// *document* coordinates. That is fine on desktop, but inside a mobile bottom +// sheet (viewport-pinned, body scroll locked by Modal) it puts the list below +// the fold or lets an overflow:hidden ancestor clip it, so it reads as trapped +// inside the modal. `fixed` positions it in viewport space instead, which no +// ancestor can clip. +// +// Note that slotProps coming from defaultProps are not deep merged: a call site +// passing its own slotProps.listbox replaces this wholesale. +const POPUP_LISTBOX = { + popperOptions: { strategy: 'fixed' }, + modifiers: [ + { name: 'flip', options: { padding: 8 } }, + // altAxis with tether off lets the popup shift fully back into view rather + // than staying glued to an anchor that has no room around it. + { + name: 'preventOverflow', + options: { padding: 8, altAxis: true, tether: false }, + }, + ], + // Joy hardcodes 44vh, and vh resolves to the *large* viewport on mobile — + // taller than what is actually on screen while the browser chrome is up. + sx: { maxHeight: 'min(44dvh, 320px)' }, +} + const themeConfig = { radius: { xs: '6px', @@ -163,6 +189,10 @@ const themeConfig = { theme.direction === 'rtl' ? buttonGroupRtlGeometry(ownerState) : {}, }, }, + JoySelect: { defaultProps: { slotProps: { listbox: POPUP_LISTBOX } } }, + JoyAutocomplete: { + defaultProps: { slotProps: { listbox: POPUP_LISTBOX } }, + }, }, }