feat: responsive popovers & menus (#1323)

This commit is contained in:
Aman Harwara
2022-07-21 02:20:14 +05:30
committed by GitHub
parent baf7fb0019
commit 2573407851
44 changed files with 1308 additions and 1415 deletions

View File

@@ -1,26 +1,24 @@
import { observer } from 'mobx-react-lite'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { WebApplication } from '@/Application/Application'
import { useCallback, useRef, FunctionComponent, KeyboardEventHandler } from 'react'
import { useCallback, FunctionComponent, KeyboardEventHandler } from 'react'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { AccountMenuPane } from './AccountMenuPane'
import MenuPaneSelector from './MenuPaneSelector'
type Props = {
export type AccountMenuProps = {
viewControllerManager: ViewControllerManager
application: WebApplication
onClickOutside: () => void
mainApplicationGroup: ApplicationGroup
}
const AccountMenu: FunctionComponent<Props> = ({
const AccountMenu: FunctionComponent<AccountMenuProps> = ({
application,
viewControllerManager,
onClickOutside,
mainApplicationGroup,
}) => {
const { currentPane, shouldAnimateCloseMenu } = viewControllerManager.accountMenuController
const { currentPane } = viewControllerManager.accountMenuController
const closeAccountMenu = useCallback(() => {
viewControllerManager.accountMenuController.closeAccountMenu()
@@ -33,11 +31,6 @@ const AccountMenu: FunctionComponent<Props> = ({
[viewControllerManager],
)
const ref = useRef<HTMLDivElement>(null)
useCloseOnClickOutside(ref, () => {
onClickOutside()
})
const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = useCallback(
(event) => {
switch (event.key) {
@@ -56,22 +49,15 @@ const AccountMenu: FunctionComponent<Props> = ({
)
return (
<div ref={ref} id="account-menu" className="sn-component">
<div
className={`max-h-120 absolute bottom-full left-0 z-footer-bar-item-panel flex min-w-80 max-w-xs cursor-auto flex-col overflow-y-auto rounded bg-default py-2 shadow-main ${
shouldAnimateCloseMenu ? 'slide-up-animation' : 'slide-down-animation transition-transform duration-150'
}`}
onKeyDown={handleKeyDown}
>
<MenuPaneSelector
viewControllerManager={viewControllerManager}
application={application}
mainApplicationGroup={mainApplicationGroup}
menuPane={currentPane}
setMenuPane={setCurrentPane}
closeMenu={closeAccountMenu}
/>
</div>
<div id="account-menu" className="sn-component" onKeyDown={handleKeyDown}>
<MenuPaneSelector
viewControllerManager={viewControllerManager}
application={application}
mainApplicationGroup={mainApplicationGroup}
menuPane={currentPane}
setMenuPane={setCurrentPane}
closeMenu={closeAccountMenu}
/>
</div>
)
}

View File

@@ -23,7 +23,9 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
isOpen,
hideWorkspaceOptions = false,
}: Props) => {
const [applicationDescriptors, setApplicationDescriptors] = useState<ApplicationDescriptor[]>([])
const [applicationDescriptors, setApplicationDescriptors] = useState<ApplicationDescriptor[]>(
mainApplicationGroup.getDescriptors(),
)
useEffect(() => {
const applicationDescriptors = mainApplicationGroup.getDescriptors()

View File

@@ -1,13 +1,13 @@
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants'
import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { FunctionComponent, useCallback, useRef, useState } from 'react'
import Icon from '@/Components/Icon/Icon'
import WorkspaceSwitcherMenu from './WorkspaceSwitcherMenu'
import MenuItem from '@/Components/Menu/MenuItem'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import Popover from '@/Components/Popover/Popover'
type Props = {
mainApplicationGroup: ApplicationGroup
@@ -16,32 +16,11 @@ type Props = {
const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGroup, viewControllerManager }) => {
const buttonRef = useRef<HTMLButtonElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const [isOpen, setIsOpen] = useState(false)
const [menuStyle, setMenuStyle] = useState<SubmenuStyle>()
const toggleMenu = useCallback(() => {
if (!isOpen) {
const menuPosition = calculateSubmenuStyle(buttonRef.current)
if (menuPosition) {
setMenuStyle(menuPosition)
}
}
setIsOpen(!isOpen)
}, [isOpen, setIsOpen])
useEffect(() => {
if (isOpen) {
setTimeout(() => {
const newMenuPosition = calculateSubmenuStyle(buttonRef.current, menuRef.current)
if (newMenuPosition) {
setMenuStyle(newMenuPosition)
}
})
}
}, [isOpen])
setIsOpen((isOpen) => !isOpen)
}, [])
return (
<>
@@ -58,19 +37,20 @@ const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGrou
</div>
<Icon type="chevron-right" className="text-neutral" />
</MenuItem>
{isOpen && (
<div
ref={menuRef}
className="max-h-120 fixed min-w-68 overflow-y-auto rounded bg-default py-2 shadow-main"
style={menuStyle}
>
<WorkspaceSwitcherMenu
mainApplicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
isOpen={isOpen}
/>
</div>
)}
<Popover
align="end"
anchorElement={buttonRef.current}
className="py-2"
open={isOpen}
side="right"
togglePopover={toggleMenu}
>
<WorkspaceSwitcherMenu
mainApplicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
isOpen={isOpen}
/>
</Popover>
</>
)
}