From 4ef5ae6f7154e0d23812ea32f4cf5ca15a71e339 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:59:09 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A1=20style:=20switched=20to=20Ariakit?= =?UTF-8?q?'s=20tooltip=20(#3748)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * inital Tooltip implementation and test * style(tooltip): L/R sidePanel and Nav * style(tooltip): unarchive button; refactor: `useArchiveHandler` and `ArchiveButton` * style(tooltip): Delete button * refactor: remove unused className prop in DeleteButton component * style(tooltip): finish final tooltip and fix bookmark edit and delete button * refactor(ui): remove TooltipTest and DropDownMenu component and unused imports * style: update mobile UI * fix: sidePanel icon not showing * feat(AttachFile): add tooltip * fix(NavToggle): remove button without this button, kb users don't have to manually press 2 times to change the focus Also, tooltips with buttons focus don't trigger * fix: right side panel issue with double button * fix: merge issues * fix: sharedLink table issue * chore: update ariakit and framer-motion version * a11y: kb toggle for sidebar * feat: tooltip for some buttons --- client/package.json | 3 +- .../Bookmarks/DeleteBookmarkButton.tsx | 64 ++++-- .../Bookmarks/EditBookmarkButton.tsx | 28 ++- client/src/components/Chat/AddMultiConvo.tsx | 21 +- .../components/Chat/Input/AudioRecorder.tsx | 41 ++-- .../Chat/Input/Files/AttachFile.tsx | 14 +- .../components/Chat/Input/HeaderOptions.tsx | 23 +- .../src/components/Chat/Input/SendButton.tsx | 52 ++--- client/src/components/Chat/Landing.tsx | 114 +++++----- .../src/components/Chat/Menus/PresetsMenu.tsx | 18 +- .../ConvoOptions/ConvoOptions.tsx | 3 +- .../ConvoOptions/DeleteButton.tsx | 33 +-- .../Conversations/ConvoOptions/index.ts | 1 - .../components/Conversations/DropDownMenu.tsx | 71 ------ .../components/Nav/Bookmarks/BookmarkNav.tsx | 4 +- client/src/components/Nav/MobileNav.tsx | 6 +- client/src/components/Nav/Nav.tsx | 188 ++++++++-------- client/src/components/Nav/NavToggle.tsx | 79 ++++--- client/src/components/Nav/NewChat.tsx | 71 +++--- client/src/components/Nav/SearchBar.tsx | 2 +- .../Nav/SettingsTabs/Data/SharedLinkTable.tsx | 68 ++---- .../Nav/SettingsTabs/Data/SharedLinks.tsx | 14 +- .../General/ArchivedChatsTable.tsx | 102 ++++----- .../Builder/AssistantConversationStarters.tsx | 58 ++--- client/src/components/SidePanel/Nav.tsx | 62 +++--- client/src/components/SidePanel/SidePanel.tsx | 210 +++++++++--------- client/src/components/svg/Spinner.tsx | 23 +- .../src/components/ui/SelectDropDownPop.tsx | 2 +- client/src/components/ui/Tooltip.tsx | 101 +++++---- client/src/components/ui/TooltipIcon.tsx | 96 -------- client/src/hooks/Conversations/index.ts | 1 + .../Conversations/useArchiveHandler.ts} | 45 +--- client/src/localization/languages/Eng.ts | 2 + client/src/localization/languages/It.ts | 10 +- .../localization/prompts/instructions/It.md | 4 +- client/src/style.css | 27 ++- package-lock.json | 53 ++++- 37 files changed, 747 insertions(+), 967 deletions(-) delete mode 100644 client/src/components/Conversations/DropDownMenu.tsx delete mode 100644 client/src/components/ui/TooltipIcon.tsx rename client/src/{components/Conversations/ConvoOptions/ArchiveButton.tsx => hooks/Conversations/useArchiveHandler.ts} (55%) diff --git a/client/package.json b/client/package.json index 2419d66774..da3064c983 100644 --- a/client/package.json +++ b/client/package.json @@ -28,7 +28,7 @@ }, "homepage": "https://librechat.ai", "dependencies": { - "@ariakit/react": "^0.4.8", + "@ariakit/react": "^0.4.11", "@codesandbox/sandpack-react": "^2.18.2", "@dicebear/collection": "^7.0.4", "@dicebear/core": "^7.0.4", @@ -63,6 +63,7 @@ "downloadjs": "^1.4.7", "export-from-json": "^1.7.2", "filenamify": "^6.0.0", + "framer-motion": "^11.5.4", "html-to-image": "^1.11.11", "image-blob-reduce": "^4.1.0", "js-cookie": "^3.0.5", diff --git a/client/src/components/Bookmarks/DeleteBookmarkButton.tsx b/client/src/components/Bookmarks/DeleteBookmarkButton.tsx index 1e422659ae..d33d368c2b 100644 --- a/client/src/components/Bookmarks/DeleteBookmarkButton.tsx +++ b/client/src/components/Bookmarks/DeleteBookmarkButton.tsx @@ -1,11 +1,11 @@ -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import type { FC } from 'react'; +import { Label, OGDialog, OGDialogTrigger, TooltipAnchor } from '~/components/ui'; import { useDeleteConversationTagMutation } from '~/data-provider'; -import TooltipIcon from '~/components/ui/TooltipIcon'; +import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; import { NotificationSeverity } from '~/common'; import { useToastContext } from '~/Providers'; import { TrashIcon } from '~/components/svg'; -import { Label } from '~/components/ui'; import { useLocalize } from '~/hooks'; const DeleteBookmarkButton: FC<{ @@ -16,6 +16,7 @@ const DeleteBookmarkButton: FC<{ }> = ({ bookmark, tabIndex = 0, onFocus, onBlur }) => { const localize = useLocalize(); const { showToast } = useToastContext(); + const [open, setOpen] = useState(false); const deleteBookmarkMutation = useDeleteConversationTagMutation({ onSuccess: () => { @@ -35,23 +36,48 @@ const DeleteBookmarkButton: FC<{ await deleteBookmarkMutation.mutateAsync(bookmark); }, [bookmark, deleteBookmarkMutation]); + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + event.preventDefault(); + event.stopPropagation(); + setOpen(!open); + } + }; + return ( - - {localize('com_ui_bookmark_delete_confirm')} {bookmark} - - } - confirm={confirmDelete} - className="transition-colors flex size-7 items-center justify-center rounded-lg duration-200 hover:bg-surface-hover" - icon={} - tabIndex={tabIndex} - onFocus={onFocus} - onBlur={onBlur} - /> + <> + + + setOpen(!open)} + onKeyDown={handleKeyDown} + > + + + + + {localize('com_ui_bookmark_delete_confirm')} {bookmark} + + } + selection={{ + selectHandler: confirmDelete, + selectClasses: + 'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 text-white', + selectText: localize('com_ui_delete'), + }} + /> + + ); }; diff --git a/client/src/components/Bookmarks/EditBookmarkButton.tsx b/client/src/components/Bookmarks/EditBookmarkButton.tsx index 78a3a96a76..14eee24822 100644 --- a/client/src/components/Bookmarks/EditBookmarkButton.tsx +++ b/client/src/components/Bookmarks/EditBookmarkButton.tsx @@ -2,9 +2,9 @@ import { useState } from 'react'; import type { FC } from 'react'; import type { TConversationTag } from 'librechat-data-provider'; import BookmarkEditDialog from './BookmarkEditDialog'; +import { TooltipAnchor } from '~/components/ui'; import { EditIcon } from '~/components/svg'; import { useLocalize } from '~/hooks'; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/components/ui'; const EditBookmarkButton: FC<{ bookmark: TConversationTag; @@ -15,6 +15,12 @@ const EditBookmarkButton: FC<{ const localize = useLocalize(); const [open, setOpen] = useState(false); + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + setOpen(!open); + } + }; + return ( <> - + + ); }; diff --git a/client/src/components/Chat/AddMultiConvo.tsx b/client/src/components/Chat/AddMultiConvo.tsx index 34b11e4074..8ee85ebb3a 100644 --- a/client/src/components/Chat/AddMultiConvo.tsx +++ b/client/src/components/Chat/AddMultiConvo.tsx @@ -2,13 +2,15 @@ import { PlusCircle } from 'lucide-react'; import { isAssistantsEndpoint } from 'librechat-data-provider'; import type { TConversation } from 'librechat-data-provider'; import { useChatContext, useAddedChatContext } from '~/Providers'; +import { TooltipAnchor } from '~/components'; import { mainTextareaId } from '~/common'; -import { Button } from '~/components/ui'; +import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; -function AddMultiConvo({ className = '' }: { className?: string }) { +function AddMultiConvo() { const { conversation } = useChatContext(); const { setConversation: setAddedConvo } = useAddedChatContext(); + const localize = useLocalize(); const clickHandler = () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -33,15 +35,18 @@ function AddMultiConvo({ className = '' }: { className?: string }) { } return ( - + + ); } diff --git a/client/src/components/Chat/Input/AudioRecorder.tsx b/client/src/components/Chat/Input/AudioRecorder.tsx index eb0c9093ed..1c950b5180 100644 --- a/client/src/components/Chat/Input/AudioRecorder.tsx +++ b/client/src/components/Chat/Input/AudioRecorder.tsx @@ -1,8 +1,8 @@ import { useEffect } from 'react'; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; import { ListeningIcon, Spinner } from '~/components/svg'; import { useLocalize, useSpeechToText } from '~/hooks'; import { useChatFormContext } from '~/Providers'; +import { TooltipAnchor } from '~/components/ui'; import { globalAudioId } from '~/common'; import { cn } from '~/utils'; @@ -74,29 +74,20 @@ export default function AudioRecorder({ }; return ( - - - - - - - {localize('com_ui_use_micrphone')} - - - + + {renderIcon()} + ); } diff --git a/client/src/components/Chat/Input/Files/AttachFile.tsx b/client/src/components/Chat/Input/Files/AttachFile.tsx index d422e30d46..a39bf25433 100644 --- a/client/src/components/Chat/Input/Files/AttachFile.tsx +++ b/client/src/components/Chat/Input/Files/AttachFile.tsx @@ -5,10 +5,10 @@ import { fileConfig as defaultFileConfig, mergeFileConfig, } from 'librechat-data-provider'; +import { FileUpload, TooltipAnchor } from '~/components/ui'; +import { useFileHandling, useLocalize } from '~/hooks'; import { useGetFileConfig } from '~/data-provider'; import { AttachmentIcon } from '~/components/svg'; -import { FileUpload } from '~/components/ui'; -import { useFileHandling } from '~/hooks'; import { cn } from '~/utils'; const AttachFile = ({ @@ -22,6 +22,7 @@ const AttachFile = ({ isRTL: boolean; disabled?: boolean | null; }) => { + const localize = useLocalize(); const { handleFileChange } = useFileHandling(); const { data: fileConfig = defaultFileConfig } = useGetFileConfig({ select: (data) => mergeFileConfig(data), @@ -42,17 +43,18 @@ const AttachFile = ({ )} > - + ); diff --git a/client/src/components/Chat/Input/HeaderOptions.tsx b/client/src/components/Chat/Input/HeaderOptions.tsx index 652e971280..e7baa5d065 100644 --- a/client/src/components/Chat/Input/HeaderOptions.tsx +++ b/client/src/components/Chat/Input/HeaderOptions.tsx @@ -5,13 +5,12 @@ import { useState, useEffect, useMemo } from 'react'; import { tPresetUpdateSchema, EModelEndpoint, paramEndpoints } from 'librechat-data-provider'; import type { TPreset, TInterfaceConfig } from 'librechat-data-provider'; import { EndpointSettings, SaveAsPresetDialog, AlternativeSettings } from '~/components/Endpoints'; +import { PluginStoreDialog, TooltipAnchor } from '~/components'; import { ModelSelect } from '~/components/Input/ModelSelect'; -import { PluginStoreDialog } from '~/components'; +import { useSetIndexOptions, useLocalize } from '~/hooks'; import OptionsPopover from './OptionsPopover'; import PopoverButtons from './PopoverButtons'; -import { useSetIndexOptions } from '~/hooks'; import { useChatContext } from '~/Providers'; -import { Button } from '~/components/ui'; import store from '~/store'; export default function HeaderOptions({ @@ -23,6 +22,7 @@ export default function HeaderOptions({ const [showPluginStoreDialog, setShowPluginStoreDialog] = useRecoilState( store.showPluginStoreDialog, ); + const localize = useLocalize(); const { showPopover, conversation, latestMessage, setShowPopover, setShowBingToneSetting } = useChatContext(); @@ -84,17 +84,18 @@ export default function HeaderOptions({ {!noSettings[endpoint] && interfaceConfig?.parameters === true && !paramEndpoints.has(endpoint) && ( - + + )} {interfaceConfig?.parameters === true && !paramEndpoints.has(endpoint) && ( diff --git a/client/src/components/Chat/Input/SendButton.tsx b/client/src/components/Chat/Input/SendButton.tsx index 1da7b591a5..917c312c58 100644 --- a/client/src/components/Chat/Input/SendButton.tsx +++ b/client/src/components/Chat/Input/SendButton.tsx @@ -1,7 +1,7 @@ import React, { forwardRef } from 'react'; import { useWatch } from 'react-hook-form'; import type { Control } from 'react-hook-form'; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; +import { TooltipAnchor } from '~/components/ui'; import { SendIcon } from '~/components/svg'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; @@ -17,33 +17,29 @@ const SubmitButton = React.memo( (props: { disabled: boolean; isRTL: boolean }, ref: React.ForwardedRef) => { const localize = useLocalize(); return ( - - - - - - - {localize('com_nav_send_message')} - - - + + + + + + } + > ); }, ), diff --git a/client/src/components/Chat/Landing.tsx b/client/src/components/Chat/Landing.tsx index 4b6fe03bf5..0693937090 100644 --- a/client/src/components/Chat/Landing.tsx +++ b/client/src/components/Chat/Landing.tsx @@ -2,11 +2,11 @@ import { useMemo } from 'react'; import { EModelEndpoint, isAssistantsEndpoint, Constants } from 'librechat-data-provider'; import { useGetEndpointsQuery, useGetStartupConfig } from 'librechat-data-provider/react-query'; import type { ReactNode } from 'react'; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; import { useChatContext, useAssistantsMapContext } from '~/Providers'; import { useGetAssistantDocsQuery } from '~/data-provider'; import ConvoIcon from '~/components/Endpoints/ConvoIcon'; import { useLocalize, useSubmitMessage } from '~/hooks'; +import { TooltipAnchor } from '~/components/ui'; import { BirthdayIcon } from '~/components/svg'; import { getIconEndpoint, cn } from '~/utils'; import ConvoStarter from './ConvoStarter'; @@ -58,66 +58,58 @@ export default function Landing({ Header }: { Header?: ReactNode }) { const sendConversationStarter = (text: string) => submitMessage({ text }); return ( - - -
-
{Header != null ? Header : null}
-
-
- - {startupConfig?.showBirthdayIcon === true ? ( -
- - - - - {localize('com_ui_happy_birthday')} - -
- ) : null} -
- {assistantName ? ( -
-
- {assistantName} -
-
- {assistantDesc ? assistantDesc : localize('com_nav_welcome_message')} -
- {/*
-
By Daniel Avila
-
*/} -
- ) : ( -

- {isAssistant - ? conversation?.greeting ?? localize('com_nav_welcome_assistant') - : conversation?.greeting ?? localize('com_nav_welcome_message')} -

- )} -
- {conversation_starters.length > 0 && - conversation_starters - .slice(0, Constants.MAX_CONVO_STARTERS) - .map((text, index) => ( - sendConversationStarter(text)} - /> - ))} -
-
+
+
{Header != null ? Header : null}
+
+
+ + {startupConfig?.showBirthdayIcon === true ? ( + + + + ) : null}
- - + {assistantName ? ( +
+
{assistantName}
+
+ {assistantDesc ? assistantDesc : localize('com_nav_welcome_message')} +
+ {/*
+
By Daniel Avila
+
*/} +
+ ) : ( +

+ {isAssistant + ? conversation?.greeting ?? localize('com_nav_welcome_assistant') + : conversation?.greeting ?? localize('com_nav_welcome_message')} +

+ )} +
+ {conversation_starters.length > 0 && + conversation_starters + .slice(0, Constants.MAX_CONVO_STARTERS) + .map((text, index) => ( + sendConversationStarter(text)} + /> + ))} +
+
+
); } diff --git a/client/src/components/Chat/Menus/PresetsMenu.tsx b/client/src/components/Chat/Menus/PresetsMenu.tsx index ff5d7c1032..3032fa813e 100644 --- a/client/src/components/Chat/Menus/PresetsMenu.tsx +++ b/client/src/components/Chat/Menus/PresetsMenu.tsx @@ -4,7 +4,7 @@ import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover'; import { EditPresetDialog, PresetItems } from './Presets'; import { useLocalize, usePresets } from '~/hooks'; import { useChatContext } from '~/Providers'; -import { Button } from '~/components/ui'; +import { TooltipAnchor } from '~/components'; const PresetsMenu: FC = () => { const localize = useLocalize(); @@ -25,17 +25,17 @@ const PresetsMenu: FC = () => { return ( - + +
void; title: string; - className?: string; showDeleteDialog?: boolean; setShowDeleteDialog?: (value: boolean) => void; }; @@ -30,7 +21,6 @@ export default function DeleteButton({ conversationId, retainView, title, - className = '', showDeleteDialog, setShowDeleteDialog, }: DeleteButtonProps) { @@ -92,20 +82,13 @@ export default function DeleteButton({ return ( - - - - - - - - - {localize('com_ui_delete')} - - - + + + + + {dialogContent} ); diff --git a/client/src/components/Conversations/ConvoOptions/index.ts b/client/src/components/Conversations/ConvoOptions/index.ts index 6f8794d063..60ceeb2675 100644 --- a/client/src/components/Conversations/ConvoOptions/index.ts +++ b/client/src/components/Conversations/ConvoOptions/index.ts @@ -1,4 +1,3 @@ -export { default as ArchiveButton } from './ArchiveButton'; export { default as DeleteButton } from './DeleteButton'; export { default as ShareButton } from './ShareButton'; export { default as SharedLinkButton } from './SharedLinkButton'; diff --git a/client/src/components/Conversations/DropDownMenu.tsx b/client/src/components/Conversations/DropDownMenu.tsx deleted file mode 100644 index 1cc18ae8b4..0000000000 --- a/client/src/components/Conversations/DropDownMenu.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { cloneElement, type FC } from 'react'; -import { DotsIcon } from '~/components/svg'; -import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover'; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; -import { useToggle } from './ToggleContext'; -import { useLocalize } from '~/hooks'; -import { cn } from '~/utils'; - -type DropDownMenuProps = { - children: React.ReactNode; - icon?: React.ReactElement; - tooltip?: string; - className?: string; -}; -const DropDownMenu: FC = ({ - children, - icon = , - tooltip = 'More', - className, -}: DropDownMenuProps) => { - const localize = useLocalize(); - const { isPopoverActive, setPopoverActive } = useToggle(); - - return ( - setPopoverActive(open)}> - -
- - - - - - - {tooltip} - - - -
-
- - - {children} - - -
- ); -}; - -export default DropDownMenu; diff --git a/client/src/components/Nav/Bookmarks/BookmarkNav.tsx b/client/src/components/Nav/Bookmarks/BookmarkNav.tsx index fc3ffbe8fd..d0fae61c46 100644 --- a/client/src/components/Nav/Bookmarks/BookmarkNav.tsx +++ b/client/src/components/Nav/Bookmarks/BookmarkNav.tsx @@ -14,9 +14,10 @@ import store from '~/store'; type BookmarkNavProps = { tags: string[]; setTags: (tags: string[]) => void; + isSmallScreen: boolean; }; -const BookmarkNav: FC = ({ tags, setTags }: BookmarkNavProps) => { +const BookmarkNav: FC = ({ tags, setTags, isSmallScreen }: BookmarkNavProps) => { const localize = useLocalize(); const location = useLocation(); @@ -40,6 +41,7 @@ const BookmarkNav: FC = ({ tags, setTags }: BookmarkNavProps) className={cn( 'mt-text-sm flex h-10 w-full items-center gap-2 rounded-lg p-2 text-sm transition-colors duration-200 hover:bg-surface-hover', open ? 'bg-surface-hover' : '', + isSmallScreen ? 'h-14 rounded-2xl' : '', )} data-testid="bookmark-menu" > diff --git a/client/src/components/Nav/MobileNav.tsx b/client/src/components/Nav/MobileNav.tsx index 35defea508..7845a0fdb1 100644 --- a/client/src/components/Nav/MobileNav.tsx +++ b/client/src/components/Nav/MobileNav.tsx @@ -15,11 +15,11 @@ export default function MobileNav({ const { title = 'New Chat' } = conversation || {}; return ( -
+
- +
+ +
); } diff --git a/client/src/components/Nav/NewChat.tsx b/client/src/components/Nav/NewChat.tsx index 8766924a4a..22aa888eb0 100644 --- a/client/src/components/Nav/NewChat.tsx +++ b/client/src/components/Nav/NewChat.tsx @@ -2,14 +2,14 @@ import { Search } from 'lucide-react'; import { useRecoilValue } from 'recoil'; import { useNavigate } from 'react-router-dom'; import { useGetEndpointsQuery } from 'librechat-data-provider/react-query'; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui'; +import type { TConversation } from 'librechat-data-provider'; import { getEndpointField, getIconEndpoint, getIconKey } from '~/utils'; import { icons } from '~/components/Chat/Menus/Endpoints/Icons'; import ConvoIconURL from '~/components/Endpoints/ConvoIconURL'; import { useLocalize, useNewConvo } from '~/hooks'; +import { TooltipAnchor } from '~/components/ui'; import { NewChatIcon } from '~/components/svg'; import store from '~/store'; -import type { TConversation } from 'librechat-data-provider'; const NewChatButtonIcon = ({ conversation }: { conversation: TConversation | null }) => { const searchQuery = useRecoilValue(store.searchQuery); @@ -80,43 +80,36 @@ export default function NewChat({ }; return ( - - -
- ); } diff --git a/client/src/components/Nav/SearchBar.tsx b/client/src/components/Nav/SearchBar.tsx index 6efebf419e..90d0bb981f 100644 --- a/client/src/components/Nav/SearchBar.tsx +++ b/client/src/components/Nav/SearchBar.tsx @@ -61,7 +61,7 @@ const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) = ref={ref} className={cn( 'group relative mt-1 flex h-10 cursor-pointer items-center gap-3 rounded-lg border-border-medium px-3 py-2 text-text-primary transition-colors duration-200 focus-within:bg-surface-hover hover:bg-surface-hover', - isSmallScreen === true ? 'h-16 rounded-2xl' : '', + isSmallScreen === true ? 'mb-2 h-14 rounded-2xl' : '', )} > { diff --git a/client/src/components/Nav/SettingsTabs/Data/SharedLinkTable.tsx b/client/src/components/Nav/SettingsTabs/Data/SharedLinkTable.tsx index 1e09c8d8ec..13084667a3 100644 --- a/client/src/components/Nav/SettingsTabs/Data/SharedLinkTable.tsx +++ b/client/src/components/Nav/SettingsTabs/Data/SharedLinkTable.tsx @@ -1,20 +1,13 @@ -import { useMemo, useState, MouseEvent } from 'react'; +import { useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; -import { MessageSquare, Link as LinkIcon } from 'lucide-react'; +import { Link as LinkIcon } from 'lucide-react'; import type { SharedLinksResponse, TSharedLink } from 'librechat-data-provider'; import { useDeleteSharedLinkMutation, useSharedLinksInfiniteQuery } from '~/data-provider'; import { useAuthContext, useLocalize, useNavScrolling } from '~/hooks'; +import { Spinner, TooltipAnchor, TrashIcon } from '~/components'; import { NotificationSeverity } from '~/common'; import { useToastContext } from '~/Providers'; import { cn } from '~/utils'; -import { - Spinner, - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, - TrashIcon, -} from '~/components'; function SharedLinkDeleteButton({ shareId, @@ -36,7 +29,7 @@ function SharedLinkDeleteButton({ }, }); - const handleDelete = async (e: MouseEvent) => { + const handleDelete = async (e: React.MouseEvent) => { e.preventDefault(); if (mutation.isLoading) { return; @@ -46,36 +39,14 @@ function SharedLinkDeleteButton({ setIsDeleting(false); }; return ( - - - - - - - {localize('com_ui_delete')} - - - - ); -} -function SourceChatButton({ conversationId }: { conversationId: string }) { - const localize = useLocalize(); - - return ( - - - - - - - - - {localize('com_nav_source_chat')} - - - + + + ); } @@ -114,15 +85,12 @@ function ShareLinkRow({ sharedLink }: { sharedLink: TSharedLink }) { )} > {sharedLink.conversationId && ( - <> - -
- -
- +
+ +
)}
diff --git a/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx b/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx index 80ff43c684..9bd707f197 100644 --- a/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx +++ b/client/src/components/Nav/SettingsTabs/Data/SharedLinks.tsx @@ -1,6 +1,6 @@ import { useLocalize } from '~/hooks'; -import { Dialog, DialogTrigger } from '~/components/ui'; -import DialogTemplate from '~/components/ui/DialogTemplate'; +import { OGDialog, OGDialogTrigger } from '~/components/ui'; +import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; import ShareLinkTable from './SharedLinkTable'; @@ -11,19 +11,19 @@ export default function SharedLinks() {
{localize('com_nav_shared_links')}
- - + + - - + } /> - +
); } diff --git a/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx b/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx index 205326f151..4e38876f26 100644 --- a/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx +++ b/client/src/components/Nav/SettingsTabs/General/ArchivedChatsTable.tsx @@ -1,17 +1,18 @@ -import { useMemo, useState } from 'react'; +import { useMemo, useState, useCallback } from 'react'; import { MessageCircle, ArchiveRestore } from 'lucide-react'; import { useConversationsInfiniteQuery } from '~/data-provider'; -import { useAuthContext, useLocalize, useNavScrolling } from '~/hooks'; -import ArchiveButton from '~/components/Conversations/ConvoOptions/ArchiveButton'; -import DeleteButton from '~/components/Conversations/ConvoOptions/DeleteButton'; +import { ConversationListResponse } from 'librechat-data-provider'; +import { useAuthContext, useLocalize, useNavScrolling, useArchiveHandler } from '~/hooks'; +import { DeleteButton } from '~/components/Conversations/ConvoOptions'; +import { TooltipAnchor } from '~/components/ui'; import { Spinner } from '~/components/svg'; import { cn } from '~/utils'; -import { ConversationListResponse } from 'librechat-data-provider'; -export default function ArchivedChatsTable({ className }: { className?: string }) { +export default function ArchivedChatsTable() { const localize = useLocalize(); const { isAuthenticated } = useAuthContext(); const [showLoading, setShowLoading] = useState(false); + const [conversationId, setConversationId] = useState(null); const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useConversationsInfiniteQuery( { pageNumber: '1', isArchived: true }, @@ -30,14 +31,9 @@ export default function ArchivedChatsTable({ className }: { className?: string } [data], ); - const classProp: { className?: string } = { - className: 'p-1 hover:text-black dark:hover:text-white', - }; - if (className) { - classProp.className = className; - } + const archiveHandler = useArchiveHandler(conversationId ?? '', false, moveToTop); - if (!conversations || conversations.length === 0) { + if (!data || conversations.length === 0) { return
{localize('com_nav_archived_chats_empty')}
; } @@ -58,48 +54,52 @@ export default function ArchivedChatsTable({ className }: { className?: string } - {conversations.map((conversation) => ( - - - - {conversation.title} - - -
-
- {new Date(conversation.createdAt).toLocaleDateString('en-US', { - month: 'long', - day: 'numeric', - year: 'numeric', - })} -
-
- {conversation.conversationId && ( - <> - { + if (!conversation.conversationId) { + return null; + } + return ( + + + + {conversation.title} + + +
+
+ {new Date(conversation.createdAt).toLocaleDateString('en-US', { + month: 'long', + day: 'numeric', + year: 'numeric', + })} +
+
+ { + setConversationId(conversation.conversationId); + archiveHandler(); + }} + className="cursor-pointer hover:text-black dark:hover:text-white" + > + + +
+ } + title={conversation.title ?? ''} /> -
- -
- - )} +
+
-
- - - ))} + + + ); + })} {(isFetchingNextPage || showLoading) && ( diff --git a/client/src/components/SidePanel/Builder/AssistantConversationStarters.tsx b/client/src/components/SidePanel/Builder/AssistantConversationStarters.tsx index 9d673044a5..30b9157f1c 100644 --- a/client/src/components/SidePanel/Builder/AssistantConversationStarters.tsx +++ b/client/src/components/SidePanel/Builder/AssistantConversationStarters.tsx @@ -2,7 +2,7 @@ import React, { useRef, useState } from 'react'; import { Plus, X } from 'lucide-react'; import { Transition } from 'react-transition-group'; import { Constants } from 'librechat-data-provider'; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/components/ui'; +import { TooltipAnchor } from '~/components/ui'; import { useLocalize } from '~/hooks'; interface AssistantConversationStartersProps { @@ -106,25 +106,19 @@ const AssistantConversationStarters: React.FC - - - - - - - {hasReachedMax - ? localize('com_assistants_max_starters_reached') - : localize('com_ui_add')} - - - + + +
)} @@ -143,22 +137,14 @@ const AssistantConversationStarters: React.FC - - - - - - - {localize('com_ui_delete')} - - - + handleDeleteStarter(index)} + > + +
))} diff --git a/client/src/components/SidePanel/Nav.tsx b/client/src/components/SidePanel/Nav.tsx index 2bcd3aded9..4ef9db659b 100644 --- a/client/src/components/SidePanel/Nav.tsx +++ b/client/src/components/SidePanel/Nav.tsx @@ -2,9 +2,9 @@ import { useState } from 'react'; import * as AccordionPrimitive from '@radix-ui/react-accordion'; import type { NavLink, NavProps } from '~/common'; import { Accordion, AccordionItem, AccordionContent } from '~/components/ui/Accordion'; -import { Tooltip, TooltipContent, TooltipTrigger } from '~/components/ui/Tooltip'; import { buttonVariants } from '~/components/ui/Button'; import { cn, removeFocusOutlines } from '~/utils'; +import { TooltipAnchor } from '~/components/ui'; import { useLocalize } from '~/hooks'; export default function Nav({ links, isCollapsed, resize, defaultActive }: NavProps) { @@ -30,42 +30,30 @@ export default function Nav({ links, isCollapsed, resize, defaultActive }: NavPr {links.map((link, index) => { const variant = getVariant(link); return isCollapsed ? ( - - - - - - {localize(link.title)} - {link.label && ( - {link.label} - )} - - + { + if (link.onClick) { + link.onClick(e); + setActive(''); + return; + } + setActive(link.id); + resize && resize(25); + }} + description={localize(link.title)} + side="left" + > + + {link.title} + ) : ( - - throttledSaveLayout(sizes)} - className="transition-width relative h-full w-full flex-1 overflow-auto bg-white dark:bg-gray-800" + throttledSaveLayout(sizes)} + className="transition-width relative h-full w-full flex-1 overflow-auto bg-white dark:bg-gray-800" + > + - - {children} - - {artifacts != null && ( - <> - - - {artifacts} - - - )} - - -
setIsHovering(true)} - onMouseLeave={() => setIsHovering(false)} - className="relative flex w-px items-center justify-center" - > - -
-
-
- {(!isCollapsed || minSize > 0) && !isSmallScreen && !fullCollapse && ( - - )} - { - setIsCollapsed(false); - localStorage.setItem('react-resizable-panels:collapsed', 'false'); - }} - onCollapse={() => { - setIsCollapsed(true); - localStorage.setItem('react-resizable-panels:collapsed', 'true'); - }} + {children} + + {artifacts != null && ( + <> + + + {artifacts} + + + )} +
setIsHovering(true)} + onMouseLeave={() => setIsHovering(false)} + className="relative flex w-px items-center justify-center" + > + - {interfaceConfig.modelSelect && ( -
- -
- )} -
+ {(!isCollapsed || minSize > 0) && !isSmallScreen && !fullCollapse && ( + + )} + { + setIsCollapsed(false); + localStorage.setItem('react-resizable-panels:collapsed', 'false'); + }} + onCollapse={() => { + setIsCollapsed(true); + localStorage.setItem('react-resizable-panels:collapsed', 'true'); + }} + className={cn( + 'sidenav hide-scrollbar border-l border-border-light bg-surface-primary-alt transition-opacity', + isCollapsed ? 'min-w-[50px]' : 'min-w-[340px] sm:min-w-[352px]', + (isSmallScreen && isCollapsed && (minSize === 0 || collapsedSize === 0)) || fullCollapse + ? 'hidden min-w-0' + : 'opacity-100', + )} + > + {interfaceConfig.modelSelect && ( +
+ +
+ )} +