feat: add ToolsDropdown component to BadgeRow for enhanced tool options

This commit is contained in:
Danny Avila 2025-06-21 22:59:11 -04:00
parent 1d532a864d
commit d247e48212
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
2 changed files with 103 additions and 1 deletions

View file

@ -14,6 +14,7 @@ import CodeInterpreter from './CodeInterpreter';
import type { BadgeItem } from '~/common';
import { useChatBadges } from '~/hooks';
import { Badge } from '~/components/ui';
import ToolsDropdown from './ToolsDropdown';
import MCPSelect from './MCPSelect';
import WebSearch from './WebSearch';
import store from '~/store';
@ -313,7 +314,8 @@ function BadgeRow({
}, [dragState.draggedBadge, handleMouseMove, handleMouseUp]);
return (
<div ref={containerRef} className="relative flex flex-wrap items-center gap-2">
<div ref={containerRef} className="relative flex flex-wrap items-center gap-1">
<ToolsDropdown conversationId={conversationId} />
{tempBadges.map((badge, index) => (
<React.Fragment key={badge.id}>
{dragState.draggedBadge && dragState.insertIndex === index && ghostBadge && (

View file

@ -0,0 +1,100 @@
import React, { useState, useMemo } from 'react';
import * as Ariakit from '@ariakit/react';
import { Settings2, Search, ImageIcon, Globe, PenTool } from 'lucide-react';
import { TooltipAnchor, DropdownPopup } from '~/components';
import { useLocalize } from '~/hooks';
import { cn } from '~/utils';
interface ToolsDropdownProps {
conversationId?: string | null;
disabled?: boolean;
}
const ToolsDropdown = ({ disabled, conversationId }: ToolsDropdownProps) => {
const localize = useLocalize();
const isDisabled = disabled ?? false;
const [isPopoverActive, setIsPopoverActive] = useState(false);
const dropdownItems = useMemo(() => {
return [
{
render: () => (
<div className="px-3 py-2 text-xs font-semibold text-text-secondary">
{localize('com_ui_tools')}
</div>
),
hideOnClick: false,
},
{
label: 'Search connectors',
onClick: () => {
// TODO: Implement search connectors functionality
console.log('Search connectors clicked');
},
icon: <Search className="icon-md" />,
badge: 'NEW',
},
{
label: 'Create an image',
onClick: () => {
// TODO: Implement create image functionality
console.log('Create an image clicked');
},
icon: <ImageIcon className="icon-md" />,
},
{
label: 'Search the web',
onClick: () => {
// TODO: Implement web search functionality
console.log('Search the web clicked');
},
icon: <Globe className="icon-md" />,
},
{
label: 'Write or code',
onClick: () => {
// TODO: Implement write or code functionality
console.log('Write or code clicked');
},
icon: <PenTool className="icon-md" />,
},
];
}, []);
const menuTrigger = (
<TooltipAnchor
render={
<Ariakit.MenuButton
disabled={isDisabled}
id="tools-dropdown-button"
aria-label="Tools Options"
className={cn(
'flex size-9 items-center justify-center rounded-full p-1 transition-colors hover:bg-surface-hover focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50',
)}
>
<div className="flex w-full items-center justify-center gap-2">
<Settings2 className="icon-md" />
</div>
</Ariakit.MenuButton>
}
id="tools-dropdown-button"
description={localize('com_ui_tools')}
disabled={isDisabled}
/>
);
return (
<DropdownPopup
menuId="tools-dropdown-menu"
isOpen={isPopoverActive}
setIsOpen={setIsPopoverActive}
modal={true}
unmountOnHide={true}
trigger={menuTrigger}
items={dropdownItems}
iconClassName="mr-0"
/>
);
};
export default React.memo(ToolsDropdown);