diff --git a/.changeset/old-tables-flash.md b/.changeset/old-tables-flash.md new file mode 100644 index 0000000000..1a09b6c08a --- /dev/null +++ b/.changeset/old-tables-flash.md @@ -0,0 +1,5 @@ +--- +'@leafygreen-ui/mongo-nav': minor +--- + +Add remaining activeNav values. Unify OnElementClick into NavElement. diff --git a/packages/menu/src/Menu.tsx b/packages/menu/src/Menu.tsx index 88e617104f..d60319dfe7 100644 --- a/packages/menu/src/Menu.tsx +++ b/packages/menu/src/Menu.tsx @@ -97,12 +97,21 @@ function Menu({ const hasSetInitialFocus = useRef(false); const hasSetInitialOpen = useRef(false); + const [focused, setFocused] = useState(refs[0] || null); + const [, setClosed] = useState(false); const [currentSubMenu, setCurrentSubMenu] = useState | null>(null); + const [uncontrolledOpen, uncontrolledSetOpen] = useState(false); + const { setUsingKeyboard } = useUsingKeyboardContext(); + const setOpen = + (typeof controlledOpen === 'boolean' && controlledSetOpen) || + uncontrolledSetOpen; + const open = controlledOpen ?? uncontrolledOpen; + function updateChildren(children: React.ReactNode): React.ReactNode { return React.Children.map(children, child => { if (!React.isValidElement(child) || child.props?.disabled) { @@ -196,13 +205,6 @@ function Menu({ }); } - const [focused, setFocused] = useState(refs[0] || null); - const [uncontrolledOpen, uncontrolledSetOpen] = useState(false); - const setOpen = - (typeof controlledOpen === 'boolean' && controlledSetOpen) || - uncontrolledSetOpen; - const open = controlledOpen ?? uncontrolledOpen; - // When a SubMenu becomes open, it's set to currentSubMenu, and we focus on the first child. useEffect(() => { const focusedRefIndex = refs.indexOf(focused); diff --git a/packages/mongo-nav/src/MongoNav.spec.tsx b/packages/mongo-nav/src/MongoNav.spec.tsx index 57ec86693d..cf27724a84 100644 --- a/packages/mongo-nav/src/MongoNav.spec.tsx +++ b/packages/mongo-nav/src/MongoNav.spec.tsx @@ -4,7 +4,7 @@ import '@testing-library/jest-dom/extend-expect'; import { nullableElement, Queries } from 'packages/lib/src/testHelpers'; import { dataFixtures } from './data'; import MongoNav from './MongoNav'; -import { OnElementClick } from './types'; +import { NavElement } from './types'; // types interface ExpectedElements { @@ -349,7 +349,7 @@ describe('packages/mongo-nav', () => { fireEvent.click(atlas as HTMLElement); expect(onElementClick).toHaveBeenCalled(); expect(onElementClick).toHaveBeenCalledWith( - OnElementClick.Cloud, + NavElement.Cloud, expect.anything(), ); }); @@ -359,7 +359,7 @@ describe('packages/mongo-nav', () => { fireEvent.click(realm as HTMLElement); expect(onElementClick).toHaveBeenCalled(); expect(onElementClick).toHaveBeenCalledWith( - OnElementClick.Realm, + NavElement.Realm, expect.anything(), ); }); @@ -369,7 +369,7 @@ describe('packages/mongo-nav', () => { fireEvent.click(charts as HTMLElement); expect(onElementClick).toHaveBeenCalled(); expect(onElementClick).toHaveBeenCalledWith( - OnElementClick.Charts, + NavElement.Charts, expect.anything(), ); }); @@ -381,7 +381,7 @@ describe('packages/mongo-nav', () => { const logout = expectedElements.userMenuLogout; fireEvent.click(logout as HTMLElement); expect(onElementClick).toHaveBeenCalledWith( - OnElementClick.Logout, + NavElement.Logout, expect.anything(), ); }); @@ -405,7 +405,7 @@ describe('packages/mongo-nav', () => { const logout = expectedElements.onPremLogout; fireEvent.click(logout as HTMLElement); expect(onElementClick).toHaveBeenCalledWith( - OnElementClick.Logout, + NavElement.Logout, expect.anything(), ); }); diff --git a/packages/mongo-nav/src/MongoNav.story.tsx b/packages/mongo-nav/src/MongoNav.story.tsx index 17c2c03d8d..55cbbdfc6e 100644 --- a/packages/mongo-nav/src/MongoNav.story.tsx +++ b/packages/mongo-nav/src/MongoNav.story.tsx @@ -4,7 +4,7 @@ import { select, boolean } from '@storybook/addon-knobs'; import { css } from '@leafygreen-ui/emotion'; import MongoNav from '.'; import LeafygreenProvider from '@leafygreen-ui/leafygreen-provider'; -import { Product, NavItem } from './types'; +import { Product, NavElement } from './types'; const setStorybookWidth = css` width: 100%; @@ -21,14 +21,18 @@ storiesOf('MongoNav', module).add('Default', () => ( Object.values(Product), Product.Cloud, )} - activeNav={select('activeNav', Object.values(NavItem), 'accessManager')} + activeNav={select( + 'activeNav', + Object.values(NavElement), + 'accessManager', + )} onOrganizationChange={() => {}} onProjectChange={() => {}} admin={boolean('admin', true)} onPrem={{ mfa: true, version: '4.4.0', - enabled: boolean('enabled', false), + enabled: boolean('onPrem', false), }} loadData={boolean('loadData', true)} /> diff --git a/packages/mongo-nav/src/MongoNav.tsx b/packages/mongo-nav/src/MongoNav.tsx index ba8aed6864..ee4f7e38c4 100644 --- a/packages/mongo-nav/src/MongoNav.tsx +++ b/packages/mongo-nav/src/MongoNav.tsx @@ -8,12 +8,11 @@ import { Product, URLSInterface, HostsInterface, - NavItem, + NavElement, Mode, DataInterface, ErrorCode, OnPremInterface, - OnElementClick, PostBodyInterface, } from './types'; import { dataFixtures, hostDefaults } from './data'; @@ -40,7 +39,7 @@ interface MongoNavInterface { /** * Determines what nav item is currently active. */ - activeNav?: NavItem; + activeNav?: NavElement; /** * Describes whether or not user is an `admin`. @@ -124,7 +123,7 @@ interface MongoNavInterface { * Click EventHandler that receives a `type` as its first argument and the associated `MouseEvent` as its second * This prop provides a hook into product link and logout link clicks and allows consuming applications to handle routing internally */ - onElementClick?: (type: OnElementClick, event: React.MouseEvent) => void; + onElementClick?: (type: NavElement, event: React.MouseEvent) => void; /** * Determines whether or not the component will fetch data from cloud @@ -183,7 +182,7 @@ function MongoNav({ constructProjectURL: constructProjectURLProp, onError = () => {}, onSuccess = () => {}, - onElementClick = (_type: OnElementClick, _event: React.MouseEvent) => {}, // eslint-disable-line @typescript-eslint/no-unused-vars + onElementClick = (_type: NavElement, _event: React.MouseEvent) => {}, // eslint-disable-line @typescript-eslint/no-unused-vars onPrem = { mfa: false, enabled: false, version: '' }, activeOrgId, activeProjectId, @@ -334,6 +333,7 @@ function MongoNav({ {showProjNav && !onPrem.enabled && ( void; +type OnElementClickType = (type: NavElement, event: React.MouseEvent) => void; interface OnElementClickProviderProps { children: React.ReactNode; diff --git a/packages/mongo-nav/src/helpers/OnPremUserMenu.tsx b/packages/mongo-nav/src/helpers/OnPremUserMenu.tsx index 73e6542b20..6f667bc40c 100644 --- a/packages/mongo-nav/src/helpers/OnPremUserMenu.tsx +++ b/packages/mongo-nav/src/helpers/OnPremUserMenu.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Menu, MenuItem } from '@leafygreen-ui/menu'; import { css } from '@leafygreen-ui/emotion'; -import { URLSInterface, OnElementClick } from '../types'; +import { URLSInterface, NavElement } from '../types'; import { UserMenuTrigger } from '../user-menu/index'; import { useOnElementClick } from '../OnElementClickProvider'; @@ -81,7 +81,7 @@ export default function OnPremUserMenu({ - onElementClick(OnElementClick.Logout, event) + onElementClick(NavElement.Logout, event) } data-testid="om-user-menuitem-sign-out" > diff --git a/packages/mongo-nav/src/index.ts b/packages/mongo-nav/src/index.ts index aeb45d4596..501d5b4e0d 100644 --- a/packages/mongo-nav/src/index.ts +++ b/packages/mongo-nav/src/index.ts @@ -1,7 +1,7 @@ -import MongoNav from './MongoNav'; -import { orgNavHeight } from './org-nav/index'; -import { projectNavHeight } from './project-nav/index'; -import UserMenu from './user-menu/index'; +export { default } from './MongoNav'; -export { UserMenu, orgNavHeight, projectNavHeight }; -export default MongoNav; +export { default as UserMenu } from './user-menu/index'; + +export { NavElement } from './types'; +export { orgNavHeight } from './org-nav/index'; +export { projectNavHeight } from './project-nav/index'; diff --git a/packages/mongo-nav/src/org-nav/OrgNav.tsx b/packages/mongo-nav/src/org-nav/OrgNav.tsx index 5bef3c45b0..d69c5146f4 100644 --- a/packages/mongo-nav/src/org-nav/OrgNav.tsx +++ b/packages/mongo-nav/src/org-nav/OrgNav.tsx @@ -15,7 +15,7 @@ import { OrganizationInterface, Product, URLSInterface, - NavItem, + NavElement, CurrentOrganizationInterface, HostsInterface, OrgPaymentLabel, @@ -124,7 +124,7 @@ interface OrgNav { data?: Array; constructOrganizationURL: (orgID: string) => string; urls: Required; - activeNav?: NavItem; + activeNav?: NavElement; onOrganizationChange: React.ChangeEventHandler; admin: boolean; hosts: Required; @@ -156,7 +156,7 @@ export default function OrgNav({ const { width: viewportWidth } = useViewportSize(); const isTablet = viewportWidth < breakpoints.medium; const isMobile = viewportWidth < breakpoints.small; - const disabled = activeNav === 'userSettings'; + const disabled = activeNav === NavElement.UserSettings; let paymentVariant: Colors | undefined; let key: Colors; @@ -243,7 +243,7 @@ export default function OrgNav({ constructOrganizationURL={constructOrganizationURL} urls={urls} onChange={onOrganizationChange} - isActive={activeNav === 'orgSettings'} + isActive={activeNav === NavElement.OrgSettings} loading={!current} disabled={disabled} isOnPrem={onPremEnabled} @@ -257,7 +257,7 @@ export default function OrgNav({ <> @@ -293,7 +293,7 @@ export default function OrgNav({ @@ -330,7 +330,7 @@ export default function OrgNav({ {!isMobile && ( @@ -341,7 +341,7 @@ export default function OrgNav({ {!isTablet && admin && !onPremEnabled && ( diff --git a/packages/mongo-nav/src/project-nav/ProjectNav.tsx b/packages/mongo-nav/src/project-nav/ProjectNav.tsx index f2d807ae36..707f33caa1 100644 --- a/packages/mongo-nav/src/project-nav/ProjectNav.tsx +++ b/packages/mongo-nav/src/project-nav/ProjectNav.tsx @@ -17,7 +17,7 @@ import { Product, HostsInterface, PlanType, - OnElementClick, + NavElement, } from '../types'; import { iconLoadingStyle, textLoadingStyle } from '../styles'; import { useOnElementClick } from '../OnElementClickProvider'; @@ -206,6 +206,7 @@ interface ProjectNavInterface { hosts: Required; alerts?: number; activeProduct: Product; + activeNav?: NavElement; onProjectChange: React.ChangeEventHandler; } @@ -215,6 +216,7 @@ export default function ProjectNav({ constructProjectURL, urls, activeProduct, + activeNav, onProjectChange, hosts, alerts = 0, @@ -245,6 +247,8 @@ export default function ProjectNav({ [iconLoadingStyle]: !current, }); + const onMenuClick = () => setOpen(false); + return (