diff --git a/src/frontend/package.json b/src/frontend/package.json index 81ddc7dc07..fc25530c64 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -27,6 +27,7 @@ "@mantine/hooks": "<7", "@mantine/modals": "<7", "@mantine/notifications": "<7", + "@mantine/spotlight": "<7", "@naisutech/react-tree": "^3.1.0", "@sentry/react": "^7.109.0", "@tabler/icons-react": "^3.1.0", diff --git a/src/frontend/src/components/buttons/SpotlightButton.tsx b/src/frontend/src/components/buttons/SpotlightButton.tsx new file mode 100644 index 0000000000..c524e0b947 --- /dev/null +++ b/src/frontend/src/components/buttons/SpotlightButton.tsx @@ -0,0 +1,15 @@ +import { t } from '@lingui/macro'; +import { ActionIcon } from '@mantine/core'; +import { spotlight } from '@mantine/spotlight'; +import { IconCommand } from '@tabler/icons-react'; + +/** + * A button which opens the quick command modal + */ +export function SpotlightButton() { + return ( + spotlight.open()} title={t`Open spotlight`}> + + + ); +} diff --git a/src/frontend/src/components/items/MenuLinks.tsx b/src/frontend/src/components/items/MenuLinks.tsx index c75cc565d5..e9e9b10772 100644 --- a/src/frontend/src/components/items/MenuLinks.tsx +++ b/src/frontend/src/components/items/MenuLinks.tsx @@ -16,6 +16,10 @@ export interface MenuLinkItem { docchildren?: React.ReactNode; } +export type menuItemsCollection = { + [key: string]: MenuLinkItem; +}; + function ConditionalDocTooltip({ item, children diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index 755db08a8d..1c344c1d82 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -2,7 +2,7 @@ import { ActionIcon, Container, Group, Indicator, Tabs } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconBell, IconSearch } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useMatch, useNavigate, useParams } from 'react-router-dom'; import { api } from '../../App'; @@ -10,7 +10,9 @@ import { navTabs as mainNavTabs } from '../../defaults/links'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { InvenTreeStyle } from '../../globalStyle'; import { apiUrl } from '../../states/ApiState'; +import { useLocalState } from '../../states/LocalState'; import { ScanButton } from '../buttons/ScanButton'; +import { SpotlightButton } from '../buttons/SpotlightButton'; import { MainMenu } from './MainMenu'; import { NavHoverMenu } from './NavHoverMenu'; import { NavigationDrawer } from './NavigationDrawer'; @@ -19,8 +21,12 @@ import { SearchDrawer } from './SearchDrawer'; export function Header() { const { classes } = InvenTreeStyle(); + const [setNavigationOpen, navigationOpen] = useLocalState((state) => [ + state.setNavigationOpen, + state.navigationOpen + ]); const [navDrawerOpened, { open: openNavDrawer, close: closeNavDrawer }] = - useDisclosure(false); + useDisclosure(navigationOpen); const [ searchDrawerOpened, { open: openSearchDrawer, close: closeSearchDrawer } @@ -59,6 +65,18 @@ export function Header() { refetchOnWindowFocus: false }); + // Sync Navigation Drawer state with zustand + useEffect(() => { + if (navigationOpen === navDrawerOpened) return; + setNavigationOpen(navDrawerOpened); + }, [navDrawerOpened]); + + useEffect(() => { + if (navigationOpen === navDrawerOpened) return; + if (navigationOpen) openNavDrawer(); + else closeNavDrawer(); + }, [navigationOpen]); + return (
@@ -80,6 +98,7 @@ export function Header() { + { export default function LayoutComponent() { const { classes } = InvenTreeStyle(); + const navigate = useNavigate(); + const location = useLocation(); + + const defaultactions = getActions(navigate); + const [actions, setActions] = useState(defaultactions); + const [customActions, setCustomActions] = useState(false); + + function actionsAreChanging(change: []) { + if (change.length > defaultactions.length) setCustomActions(true); + setActions(change); + } + useEffect(() => { + if (customActions) { + setActions(defaultactions); + setCustomActions(false); + } + }, [location]); return ( - -
- - - - -