mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-20 09:24:10 +01:00
📱 fix: Mention Touch UX and MCP Tool UI Consistency (#11627)
* refactor: Reorganize imports in MCPTools component - Updated import statements in MCPTools.tsx for improved clarity and maintainability. - Moved `useAgentPanelContext` import above others and adjusted the order of `PermissionTypes` and `Permissions` imports to enhance readability. * chore: imports * refactor: Update MCPToolItem component props and styles - Added new props: onToggleDefer, onToggleSelect, and onToggleProgrammatic for improved functionality. - Adjusted class names for DropdownMenuLabel and text spans to enhance visual consistency and clarity. - Increased width of DropdownMenuContent for better layout. * refactor: Update DropdownMenu styles for improved visual consistency - Changed background color of DropdownMenuContent and DropdownMenuSubContent from secondary to primary for better alignment with design standards. - Updated text color to ensure readability against the new background, enhancing overall user experience. * refactor: Update Mention component styles and interaction handling - Increased ROW_HEIGHT in Mention and PromptsCommand components for improved layout consistency. - Enhanced MentionItem component with touch event handling to improve mobile interaction experience. - Updated button styles to ensure better visual alignment and responsiveness. * refactor: Enhance MentionItem component event handling and button attributes - Updated the onClick prop type in MentionItem to support both mouse and touch events, improving mobile interaction. - Added a button type attribute for better accessibility and compliance with HTML standards. - Refined event handling to ensure consistent behavior across different input methods. * refactor: Add button type attribute to MentionItem for improved accessibility - Added a type="button" attribute to the MentionItem component to enhance accessibility and compliance with HTML standards. - This change ensures better interaction behavior across different input methods. * refactor: Simplify MentionItem event handling for improved clarity - Removed touch event handling from the MentionItem component, streamlining the onClick prop to only accept mouse events. - This change simplifies the interaction logic, enhancing maintainability while retaining functionality for mouse interactions.
This commit is contained in:
parent
2cef9368ea
commit
e89e514fcb
6 changed files with 18 additions and 17 deletions
|
|
@ -12,7 +12,7 @@ import useMentions from '~/hooks/Input/useMentions';
|
||||||
import { removeCharIfLast } from '~/utils';
|
import { removeCharIfLast } from '~/utils';
|
||||||
import MentionItem from './MentionItem';
|
import MentionItem from './MentionItem';
|
||||||
|
|
||||||
const ROW_HEIGHT = 40;
|
const ROW_HEIGHT = 44;
|
||||||
|
|
||||||
export default function Mention({
|
export default function Mention({
|
||||||
conversation,
|
conversation,
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,16 @@ export default function MentionItem({
|
||||||
}: MentionItemProps) {
|
}: MentionItemProps) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
|
style={style}
|
||||||
tabIndex={index}
|
tabIndex={index}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
id={`${type}-item-${index}`}
|
id={`${type}-item-${index}`}
|
||||||
className="w-full"
|
className="w-full touch-manipulation"
|
||||||
style={style}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-token-text-primary bg-token-main-surface-secondary group flex h-10 items-center gap-2 rounded-lg px-2 text-sm font-medium hover:bg-surface-secondary',
|
'text-token-text-primary bg-token-main-surface-secondary group flex min-h-[44px] items-center gap-2 rounded-lg px-2 text-sm font-medium hover:bg-surface-secondary active:bg-surface-active',
|
||||||
isActive === true ? 'bg-surface-active' : 'bg-transparent',
|
isActive === true ? 'bg-surface-active' : 'bg-transparent',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import { Spinner, useCombobox } from '@librechat/client';
|
||||||
import { useSetRecoilState, useRecoilValue } from 'recoil';
|
import { useSetRecoilState, useRecoilValue } from 'recoil';
|
||||||
import type { TPromptGroup } from 'librechat-data-provider';
|
import type { TPromptGroup } from 'librechat-data-provider';
|
||||||
import type { PromptOption } from '~/common';
|
import type { PromptOption } from '~/common';
|
||||||
import { removeCharIfLast, detectVariables } from '~/utils';
|
|
||||||
import VariableDialog from '~/components/Prompts/Groups/VariableDialog';
|
import VariableDialog from '~/components/Prompts/Groups/VariableDialog';
|
||||||
|
import { removeCharIfLast, detectVariables } from '~/utils';
|
||||||
import { usePromptGroupsContext } from '~/Providers';
|
import { usePromptGroupsContext } from '~/Providers';
|
||||||
import MentionItem from './MentionItem';
|
import MentionItem from './MentionItem';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
|
|
@ -48,7 +48,7 @@ const PopoverContainer = memo(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const ROW_HEIGHT = 40;
|
const ROW_HEIGHT = 44;
|
||||||
|
|
||||||
function PromptsCommand({
|
function PromptsCommand({
|
||||||
index,
|
index,
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@ export default function MCPToolItem({
|
||||||
tool,
|
tool,
|
||||||
isSelected,
|
isSelected,
|
||||||
isDeferred,
|
isDeferred,
|
||||||
|
onToggleDefer,
|
||||||
|
onToggleSelect,
|
||||||
isProgrammatic,
|
isProgrammatic,
|
||||||
|
onToggleProgrammatic,
|
||||||
deferredToolsEnabled,
|
deferredToolsEnabled,
|
||||||
programmaticToolsEnabled,
|
programmaticToolsEnabled,
|
||||||
onToggleSelect,
|
|
||||||
onToggleDefer,
|
|
||||||
onToggleProgrammatic,
|
|
||||||
}: MCPToolItemProps) {
|
}: MCPToolItemProps) {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const hasOptions = isDeferred || isProgrammatic;
|
const hasOptions = isDeferred || isProgrammatic;
|
||||||
|
|
@ -104,10 +104,10 @@ export default function MCPToolItem({
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
align="end"
|
align="end"
|
||||||
side="left"
|
side="left"
|
||||||
className="w-64"
|
className="w-80"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<DropdownMenuLabel className="text-xs font-normal text-text-secondary">
|
<DropdownMenuLabel className="text-xs font-normal text-text-primary">
|
||||||
{tool.metadata.description || localize('com_ui_mcp_no_description')}
|
{tool.metadata.description || localize('com_ui_mcp_no_description')}
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
|
@ -121,7 +121,7 @@ export default function MCPToolItem({
|
||||||
<Clock className="h-4 w-4 text-amber-500" />
|
<Clock className="h-4 w-4 text-amber-500" />
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span>{localize('com_ui_mcp_defer_loading')}</span>
|
<span>{localize('com_ui_mcp_defer_loading')}</span>
|
||||||
<span className="text-xs text-text-tertiary">
|
<span className="text-xs text-text-secondary">
|
||||||
{localize('com_ui_mcp_click_to_defer')}
|
{localize('com_ui_mcp_click_to_defer')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -138,7 +138,7 @@ export default function MCPToolItem({
|
||||||
<Code2 className="h-4 w-4 text-violet-500" />
|
<Code2 className="h-4 w-4 text-violet-500" />
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span>{localize('com_ui_mcp_programmatic')}</span>
|
<span>{localize('com_ui_mcp_programmatic')}</span>
|
||||||
<span className="text-xs text-text-tertiary">
|
<span className="text-xs text-text-secondary">
|
||||||
{localize('com_ui_mcp_click_to_programmatic')}
|
{localize('com_ui_mcp_click_to_programmatic')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
||||||
import UninitializedMCPTool from './UninitializedMCPTool';
|
import UninitializedMCPTool from './UninitializedMCPTool';
|
||||||
import UnconfiguredMCPTool from './UnconfiguredMCPTool';
|
import UnconfiguredMCPTool from './UnconfiguredMCPTool';
|
||||||
import { useAgentPanelContext } from '~/Providers';
|
|
||||||
import { useHasAccess, useLocalize } from '~/hooks';
|
import { useHasAccess, useLocalize } from '~/hooks';
|
||||||
|
import { useAgentPanelContext } from '~/Providers';
|
||||||
import MCPTool from './MCPTool';
|
import MCPTool from './MCPTool';
|
||||||
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
|
||||||
|
|
||||||
export default function MCPTools({
|
export default function MCPTools({
|
||||||
agentId,
|
agentId,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ function DropdownMenuContent({
|
||||||
data-slot="dropdown-menu-content"
|
data-slot="dropdown-menu-content"
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-popover-foreground max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin) z-40 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border border-border-light bg-surface-secondary p-1 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
'max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin) z-40 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border border-border-medium bg-surface-primary p-1 text-text-primary shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
@ -198,7 +198,7 @@ function DropdownMenuSubContent({
|
||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
data-slot="dropdown-menu-sub-content"
|
data-slot="dropdown-menu-sub-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-popover-foreground origin-(--radix-dropdown-menu-content-transform-origin) z-40 min-w-[8rem] overflow-hidden rounded-md border border-border-medium bg-surface-secondary p-1 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
'origin-(--radix-dropdown-menu-content-transform-origin) z-40 min-w-[8rem] overflow-hidden rounded-md border border-border-medium bg-surface-primary p-1 text-text-primary shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue