diff --git a/client/src/common/types.ts b/client/src/common/types.ts index 7bbb786548..cd8b45f6b7 100644 --- a/client/src/common/types.ts +++ b/client/src/common/types.ts @@ -508,7 +508,10 @@ export interface ModelItemProps { className?: string; } -export type ContextType = { navVisible: boolean; setNavVisible: (visible: boolean) => void }; +export type ContextType = { + navVisible: boolean; + setNavVisible: React.Dispatch>; +}; export interface SwitcherProps { endpoint?: t.EModelEndpoint | null; diff --git a/client/src/components/Chat/Header.tsx b/client/src/components/Chat/Header.tsx index b5379c72aa..4f491f4b05 100644 --- a/client/src/components/Chat/Header.tsx +++ b/client/src/components/Chat/Header.tsx @@ -3,7 +3,7 @@ import { useOutletContext } from 'react-router-dom'; import { getConfigDefaults, PermissionTypes, Permissions } from 'librechat-data-provider'; import type { ContextType } from '~/common'; import ModelSelector from './Menus/Endpoints/ModelSelector'; -import { PresetsMenu, HeaderNewChat } from './Menus'; +import { PresetsMenu, HeaderNewChat, OpenSidebar } from './Menus'; import { useGetStartupConfig } from '~/data-provider'; import ExportAndShareMenu from './ExportAndShareMenu'; import { useMediaQuery, useHasAccess } from '~/hooks'; @@ -15,7 +15,7 @@ const defaultInterface = getConfigDefaults().interface; export default function Header() { const { data: startupConfig } = useGetStartupConfig(); - const { navVisible } = useOutletContext(); + const { navVisible, setNavVisible } = useOutletContext(); const interfaceConfig = useMemo( () => startupConfig?.interface ?? defaultInterface, [startupConfig], @@ -37,6 +37,7 @@ export default function Header() {
+ {!navVisible && } {!navVisible && } {} {interfaceConfig.presets === true && interfaceConfig.modelSelect && } diff --git a/client/src/components/Chat/Menus/HeaderNewChat.tsx b/client/src/components/Chat/Menus/HeaderNewChat.tsx index f59f570ec8..0569157494 100644 --- a/client/src/components/Chat/Menus/HeaderNewChat.tsx +++ b/client/src/components/Chat/Menus/HeaderNewChat.tsx @@ -1,36 +1,37 @@ import { useQueryClient } from '@tanstack/react-query'; import { QueryKeys, Constants } from 'librechat-data-provider'; import type { TMessage } from 'librechat-data-provider'; -import { useMediaQuery, useLocalize } from '~/hooks'; -import { Button, NewChatIcon } from '~/components'; +import { TooltipAnchor, Button } from '~/components/ui'; +import { NewChatIcon } from '~/components/svg'; import { useChatContext } from '~/Providers'; +import { useLocalize } from '~/hooks'; export default function HeaderNewChat() { + const localize = useLocalize(); const queryClient = useQueryClient(); const { conversation, newConversation } = useChatContext(); - const isSmallScreen = useMediaQuery('(max-width: 768px)'); - const localize = useLocalize(); - - if (isSmallScreen) { - return null; - } return ( - + { + queryClient.setQueryData( + [QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO], + [], + ); + newConversation(); + }} + > + + + } + /> ); } diff --git a/client/src/components/Chat/Menus/OpenSidebar.tsx b/client/src/components/Chat/Menus/OpenSidebar.tsx new file mode 100644 index 0000000000..4c4f29414f --- /dev/null +++ b/client/src/components/Chat/Menus/OpenSidebar.tsx @@ -0,0 +1,33 @@ +import { TooltipAnchor, Button } from '~/components/ui'; +import { Sidebar } from '~/components/svg'; +import { useLocalize } from '~/hooks'; + +export default function OpenSidebar({ + setNavVisible, +}: { + setNavVisible: React.Dispatch>; +}) { + const localize = useLocalize(); + return ( + + setNavVisible((prev) => { + localStorage.setItem('navVisible', JSON.stringify(!prev)); + return !prev; + }) + } + > + + + } + /> + ); +} diff --git a/client/src/components/Chat/Menus/index.ts b/client/src/components/Chat/Menus/index.ts index 33b7e7d498..79ae61315b 100644 --- a/client/src/components/Chat/Menus/index.ts +++ b/client/src/components/Chat/Menus/index.ts @@ -1,2 +1,3 @@ export { default as PresetsMenu } from './PresetsMenu'; +export { default as OpenSidebar } from './OpenSidebar'; export { default as HeaderNewChat } from './HeaderNewChat'; diff --git a/client/src/components/Nav/Bookmarks/BookmarkNav.tsx b/client/src/components/Nav/Bookmarks/BookmarkNav.tsx index fa8ab06d6a..d0edeaf081 100644 --- a/client/src/components/Nav/Bookmarks/BookmarkNav.tsx +++ b/client/src/components/Nav/Bookmarks/BookmarkNav.tsx @@ -1,10 +1,12 @@ -import { type FC } from 'react'; +import { useMemo } from 'react'; +import type { FC } from 'react'; import { useRecoilValue } from 'recoil'; import { Menu, MenuButton, MenuItems } from '@headlessui/react'; import { BookmarkFilledIcon, BookmarkIcon } from '@radix-ui/react-icons'; import { BookmarkContext } from '~/Providers/BookmarkContext'; import { useGetConversationTags } from '~/data-provider'; import BookmarkNavItems from './BookmarkNavItems'; +import { TooltipAnchor } from '~/components/ui'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; import store from '~/store'; @@ -19,33 +21,41 @@ const BookmarkNav: FC = ({ tags, setTags, isSmallScreen }: Boo const localize = useLocalize(); const { data } = useGetConversationTags(); const conversation = useRecoilValue(store.conversationByIndex(0)); + const label = useMemo( + () => (tags.length > 0 ? tags.join(', ') : localize('com_ui_bookmarks')), + [tags, localize], + ); return ( {({ open }) => ( <> - -
-
- {tags.length > 0 ? ( -
-
- {tags.length > 0 ? tags.join(', ') : localize('com_ui_bookmarks')} -
- - + data-testid="bookmark-menu" + > + {tags.length > 0 ? ( +