From 462af85a385a0d7c7217856ea7f97db85a8fbdc7 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Thu, 13 Aug 2026 19:24:23 -0400 Subject: [PATCH] Update MUI Joy package version and refactor z-index usage across components --- package-lock.json | 2 +- package.json | 2 +- src/components/common/AppModal.jsx | 14 ++++-- src/constants/zIndex.js | 38 --------------- src/service/AlertsProvider.jsx | 3 +- .../components/ChoreToolbarPrototype.jsx | 46 +++++++++---------- src/views/TestView/AutocompleteDropdown.jsx | 3 -- src/views/components/AddTaskModal.jsx | 1 - .../components/AttachmentPickerField.jsx | 3 +- src/views/components/BaseOptionPicker.jsx | 3 +- src/views/components/NavBar.jsx | 4 +- src/views/components/NetworkBanner.jsx | 4 +- 12 files changed, 39 insertions(+), 84 deletions(-) delete mode 100644 src/constants/zIndex.js diff --git a/package-lock.json b/package-lock.json index acffd35..7d01146 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "@jcesarmobile/capacitor-ocr": "^0.3.0", "@meauxt/react-swipeable-list": "^1.0.0", "@mui/icons-material": "^5.16.13", - "@mui/joy": "^5.0.0-beta.20", + "@mui/joy": "5.0.0-beta.52", "@mui/material": "^5.15.2", "@openreplay/tracker": "^14.0.4", "@revenuecat/purchases-capacitor": "^12.0.0", diff --git a/package.json b/package.json index 714c5e9..1f6146c 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@jcesarmobile/capacitor-ocr": "^0.3.0", "@meauxt/react-swipeable-list": "^1.0.0", "@mui/icons-material": "^5.16.13", - "@mui/joy": "^5.0.0-beta.20", + "@mui/joy": "5.0.0-beta.52", "@mui/material": "^5.15.2", "@openreplay/tracker": "^14.0.4", "@revenuecat/purchases-capacitor": "^12.0.0", diff --git a/src/components/common/AppModal.jsx b/src/components/common/AppModal.jsx index 55fefc6..72c84a7 100644 --- a/src/components/common/AppModal.jsx +++ b/src/components/common/AppModal.jsx @@ -2,7 +2,6 @@ import { Close } from '@mui/icons-material' import { Box, Divider, IconButton, Modal, Sheet, Typography } from '@mui/joy' import useMediaQuery from '@mui/material/useMediaQuery' import { forwardRef, useId } from 'react' -import { Z_INDEX } from '../../constants/zIndex' const WIDTH_BY_SIZE = { sm: 400, @@ -27,6 +26,7 @@ const AppModal = forwardRef( size = 'md', fullWidth = true, isMobile: isMobileProp, + keepMounted = false, mobilePresentation = 'sheet', role = 'dialog', showCloseButton = true, @@ -63,9 +63,16 @@ const AppModal = forwardRef( onClose={handleClose} aria-labelledby={titleId} aria-describedby={descriptionId} - keepMounted + keepMounted={keepMounted} sx={{ - zIndex: Z_INDEX.MODAL_BACKDROP, + // Joy raises portaled listboxes above modals, but its selector misses + // Menu because Menu renders with role="menu". Keep the workaround in + // the modal primitive so individual menus never need a z-index. + ...(open && { + '& ~ [role="menu"]': { + '--unstable_popup-zIndex': 'calc(var(--joy-zIndex-modal) + 1)', + }, + }), display: 'flex', alignItems: isSheet ? 'flex-end' : 'center', justifyContent: 'center', @@ -85,7 +92,6 @@ const AppModal = forwardRef( aria-describedby={descriptionId} variant='outlined' sx={{ - zIndex: Z_INDEX.MODAL_CONTENT, display: 'flex', flexDirection: 'column', width: isFullscreen diff --git a/src/constants/zIndex.js b/src/constants/zIndex.js deleted file mode 100644 index 59ab5e1..0000000 --- a/src/constants/zIndex.js +++ /dev/null @@ -1,38 +0,0 @@ -// Z-index constants for consistent layering -// Lower values appear behind higher values - -export const Z_INDEX = { - // Base layer (0-99) - BASE: 0, - CARD_OVERLAY: 1, - DROPDOWN_ITEM: 2, - TOOLTIP: 3, - - // UI Components (100-999) - SAFE_AREA: 100, - CALENDAR: 110, - SMART_INPUT: 110, - AUTOCOMPLETE: 200, - - // Navigation (1000-1999) - NAVBAR: 1000, - DRAWER: 999, - - // Modals and Overlays (2000-8999) - MODAL_BACKDROP: 2000, - MODAL_CONTENT: 2001, - MODAL_CLOSE_BUTTON: 2002, - // Popups that must float above open modals (portaled to document.body) - MODAL_POPOVER: 2100, - TOAST: 3000, - - // Critical System UI (9000-9999) - LOADING_SCREEN: 9000, - ALERTS: 9500, - NETWORK_BANNER: 9600, - - // Maximum (10000+) - Reserved for absolute emergencies - EMERGENCY: 10000, -} - -export default Z_INDEX diff --git a/src/service/AlertsProvider.jsx b/src/service/AlertsProvider.jsx index 470c36a..62c2afd 100644 --- a/src/service/AlertsProvider.jsx +++ b/src/service/AlertsProvider.jsx @@ -1,7 +1,6 @@ import { Alert, Box } from '@mui/joy' import PropTypes from 'prop-types' import { createContext, useCallback, useContext, useState } from 'react' -import Z_INDEX from '../constants/zIndex' const FADE_DURATION = 400 // ms const ALERT_DURATION = 5000 // ms @@ -48,7 +47,7 @@ export const AlertsProvider = ({ children }) => { top: 0, left: 0, width: '100%', - zIndex: Z_INDEX.ALERTS, + zIndex: 'var(--joy-zIndex-snackbar)', overflow: 'hidden', }} > diff --git a/src/views/Chores/components/ChoreToolbarPrototype.jsx b/src/views/Chores/components/ChoreToolbarPrototype.jsx index 29960b4..cd4e28d 100644 --- a/src/views/Chores/components/ChoreToolbarPrototype.jsx +++ b/src/views/Chores/components/ChoreToolbarPrototype.jsx @@ -38,16 +38,17 @@ import { ButtonGroup, Chip, Divider, + Dropdown, IconButton, Input, Menu, + MenuButton, MenuItem, Typography, } from '@mui/joy' -import { useEffect, useRef, useState } from 'react' +import { useEffect, useState } from 'react' import AppModal from '../../../components/common/AppModal' import ActiveFilterChips from '../../../components/common/filter/ActiveFilterChips' -import { Z_INDEX } from '../../../constants/zIndex' import KeyboardShortcutHint from '../../../components/common/KeyboardShortcutHint' import { FILTER_COLORS } from '../../../utils/Colors' import Priorities from '../../../utils/Priorities' @@ -229,9 +230,8 @@ const ChoreToolbar = ({ const [localSelections, setLocalSelections] = useState(defaultSelections()) const [savingFilter, setSavingFilter] = useState(false) const [saveFilterName, setSaveFilterName] = useState('') - const [saveMenuAnchorEl, setSaveMenuAnchorEl] = useState(null) + const [saveMenuOpen, setSaveMenuOpen] = useState(false) const [editingSavedFilter, setEditingSavedFilter] = useState(null) - const saveMenuRef = useRef(null) const activeConditions = selectionsToConditions(localSelections) // ── badge counts ───────────────────────────────────────────────────────────── @@ -419,13 +419,13 @@ const ChoreToolbar = ({ } setSavingFilter(false) setSaveFilterName('') - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) setFilterSheetOpen(true) } useEffect(() => { if (!filterSheetOpen || savingFilter || activeConditions.length === 0) { - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) } }, [filterSheetOpen, savingFilter, activeConditions.length]) @@ -504,7 +504,7 @@ const ChoreToolbar = ({ onFilterSaved?.(editingSavedFilter.name) }) - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) setFilterSheetOpen(false) } @@ -681,7 +681,7 @@ const ChoreToolbar = ({ open={filterSheetOpen} isMobile onClose={() => { - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) setFilterSheetOpen(false) }} maxHeight='92vh' @@ -747,7 +747,7 @@ const ChoreToolbar = ({ disabled={!hasAnyActive && activeConditions.length === 0} onClick={() => { setLocalSelections(defaultSelections()) - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) onClearAllFilters?.() setFilterSheetOpen(false) }} @@ -756,33 +756,29 @@ const ChoreToolbar = ({ {activeConditions.length > 0 ? ( - <> + setSaveMenuOpen(isOpen)} + > - setSaveMenuAnchorEl(e.currentTarget)} > - + - setSaveMenuAnchorEl(null)} - placement='top-end' - sx={{ zIndex: Z_INDEX.MODAL_CONTENT + 10 }} - > + { - setSaveMenuAnchorEl(null) + setSaveMenuOpen(false) setSaveFilterName( editingSavedFilter ? `${editingSavedFilter.name} Copy` @@ -805,13 +801,13 @@ const ChoreToolbar = ({ Save as New Filter - + ) : (