Enhance Dashboard Navigation with New Modal Visibility Handling and Styling
- Introduced state management for modal visibility in the DashboardNavigation component to improve user interaction and layout responsiveness. - Added new CSS styles for dashboard navigation elements, including transitions and layout adjustments for better visual clarity. - Refactored the rendering logic to conditionally display navigation elements based on modal visibility, enhancing the overall user experience.
This commit is contained in:
parent
c39051a891
commit
65417f75b8
@ -112,6 +112,42 @@
|
|||||||
--webkit-user-select: none;
|
--webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-navigation-center {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-navigation-fade {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
transition:
|
||||||
|
opacity 0.2s ease,
|
||||||
|
visibility 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-navigation-fade-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-navigation-window-title {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 14px;
|
||||||
|
font-size: 14px;
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
border-bottom: 1px solid var(--color-header-border);
|
||||||
|
}
|
||||||
|
|
||||||
.electron-navigation-leading,
|
.electron-navigation-leading,
|
||||||
.electron-navigation-trailing {
|
.electron-navigation-trailing {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
|||||||
@ -216,6 +216,7 @@ const DashboardNavigation = () => {
|
|||||||
: mainMenuItems.map((item) => ({ ...item, label: undefined }))
|
: mainMenuItems.map((item) => ({ ...item, label: undefined }))
|
||||||
|
|
||||||
const [userPopoverOpen, setUserPopoverOpen] = useState(false)
|
const [userPopoverOpen, setUserPopoverOpen] = useState(false)
|
||||||
|
const [anyModalVisible, setAnyModalVisible] = useState(false)
|
||||||
|
|
||||||
const userPopoverContent = (
|
const userPopoverContent = (
|
||||||
<UserProfilePopover onClose={() => setUserPopoverOpen(false)} />
|
<UserProfilePopover onClose={() => setUserPopoverOpen(false)} />
|
||||||
@ -255,7 +256,48 @@ const DashboardNavigation = () => {
|
|||||||
const showDesktopLogo = !isElectron && !isMobile
|
const showDesktopLogo = !isElectron && !isMobile
|
||||||
const showMobileLogo = !isElectron && isMobile
|
const showMobileLogo = !isElectron && isMobile
|
||||||
|
|
||||||
const showControls = !isElectron || authenticated
|
useEffect(() => {
|
||||||
|
const isModalWrapVisible = (node) => {
|
||||||
|
if (!(node instanceof Element)) return false
|
||||||
|
if (node.getAttribute('aria-hidden') === 'true') return false
|
||||||
|
const style = window.getComputedStyle(node)
|
||||||
|
return (
|
||||||
|
style.display !== 'none' &&
|
||||||
|
style.visibility !== 'hidden' &&
|
||||||
|
style.pointerEvents !== 'none'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateModalVisibility = () => {
|
||||||
|
const wraps = document.querySelectorAll('.ant-modal-wrap')
|
||||||
|
setAnyModalVisible(Array.from(wraps).some(isModalWrapVisible))
|
||||||
|
}
|
||||||
|
|
||||||
|
let frameId = 0
|
||||||
|
const scheduleUpdate = () => {
|
||||||
|
if (frameId) return
|
||||||
|
frameId = window.requestAnimationFrame(() => {
|
||||||
|
frameId = 0
|
||||||
|
updateModalVisibility()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateModalVisibility()
|
||||||
|
const observer = new MutationObserver(scheduleUpdate)
|
||||||
|
observer.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['style', 'class', 'aria-hidden']
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect()
|
||||||
|
if (frameId) window.cancelAnimationFrame(frameId)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const showControls = (!isElectron || authenticated) && !anyModalVisible
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<Menu
|
<Menu
|
||||||
@ -434,28 +476,35 @@ const DashboardNavigation = () => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const windowTitle = (
|
||||||
|
<Text
|
||||||
|
type='secondary'
|
||||||
|
className={`dashboard-navigation-window-title dashboard-navigation-fade${
|
||||||
|
showControls ? ' dashboard-navigation-fade-hidden' : ''
|
||||||
|
}`}
|
||||||
|
aria-hidden={showControls}
|
||||||
|
>
|
||||||
|
Farm Control
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
|
||||||
const navigationContents = (
|
const navigationContents = (
|
||||||
<Flex style={{ width: '100%' }} align='center'>
|
<Flex style={{ width: '100%' }} align='center'>
|
||||||
{navigationLeading}
|
{navigationLeading}
|
||||||
<div style={{ flexGrow: 1, minWidth: 0 }}>
|
<div className='dashboard-navigation-center'>
|
||||||
{showControls && !isMobile ? (
|
{!isMobile ? (
|
||||||
<Flex align='center' style={{ width: '100%', minWidth: 0 }}>
|
<Flex
|
||||||
|
align='center'
|
||||||
|
className={`dashboard-navigation-fade${
|
||||||
|
showControls ? '' : ' dashboard-navigation-fade-hidden'
|
||||||
|
}`}
|
||||||
|
style={{ width: '100%', minWidth: 0 }}
|
||||||
|
aria-hidden={!showControls}
|
||||||
|
>
|
||||||
{menu}
|
{menu}
|
||||||
</Flex>
|
</Flex>
|
||||||
) : null}
|
) : null}
|
||||||
{!showControls && (
|
{windowTitle}
|
||||||
<Text
|
|
||||||
type='secondary'
|
|
||||||
style={{
|
|
||||||
fontSize: '14px',
|
|
||||||
marginLeft: '8px',
|
|
||||||
userSelect: 'none',
|
|
||||||
'--webkit-user-select': 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Farm Control
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{navigationTrailing}
|
{navigationTrailing}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -473,11 +522,7 @@ const DashboardNavigation = () => {
|
|||||||
className={`electron-navigation-wrapper ${electronDragClass}`}
|
className={`electron-navigation-wrapper ${electronDragClass}`}
|
||||||
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex align='center' className='electron-navigation-leading'>
|
||||||
align='center'
|
|
||||||
className='electron-navigation-leading'
|
|
||||||
style={{ flexGrow: !showControls ? 1 : 0 }}
|
|
||||||
>
|
|
||||||
{navigationLeading}
|
{navigationLeading}
|
||||||
{showControls && !isMobile ? menu : null}
|
{showControls && !isMobile ? menu : null}
|
||||||
{showControls && !isMobile ? (
|
{showControls && !isMobile ? (
|
||||||
@ -491,21 +536,21 @@ const DashboardNavigation = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{!showControls ? (
|
|
||||||
<Text
|
|
||||||
type='secondary'
|
|
||||||
style={{
|
|
||||||
fontSize: '14px',
|
|
||||||
marginLeft: '8px',
|
|
||||||
userSelect: 'none',
|
|
||||||
'--webkit-user-select': 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Farm Control
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
{showControls && !isMobile ? <DashboardTabs /> : null}
|
<div className='dashboard-navigation-center'>
|
||||||
|
{!isMobile ? (
|
||||||
|
<div
|
||||||
|
className={`dashboard-navigation-fade${
|
||||||
|
showControls ? '' : ' dashboard-navigation-fade-hidden'
|
||||||
|
}`}
|
||||||
|
style={{ flex: 1, minWidth: 0, display: 'flex' }}
|
||||||
|
aria-hidden={!showControls}
|
||||||
|
>
|
||||||
|
<DashboardTabs />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{windowTitle}
|
||||||
|
</div>
|
||||||
<Flex align='center' className='electron-navigation-trailing'>
|
<Flex align='center' className='electron-navigation-trailing'>
|
||||||
{navigationTrailing}
|
{navigationTrailing}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user