feat(组件): 新增 Tooltip 组件并优化输入区交互体验
- 新增通用 Tooltip 组件,支持上下左右四个方向显示 - ChatInput 组件使用 Tooltip 替代原生 title 属性 - ChatInput 添加附件图标改为 Paperclip,更直观 - ToolsDropdown 工具按钮添加 Tooltip 提示 - 优化按钮 cursor 样式,提升交互体验
This commit is contained in:
parent
3b0683faf9
commit
f50766b742
@ -1,10 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useRef } from 'react';
|
||||
import { Plus, ArrowUp, Upload } from 'lucide-react';
|
||||
import { Paperclip, ArrowUp, Upload } from 'lucide-react';
|
||||
import { ModelSelector } from './ModelSelector';
|
||||
import { ToolsDropdown } from './ToolsDropdown';
|
||||
import { FilePreviewList } from './FilePreviewList';
|
||||
import { Tooltip } from '@/components/ui/Tooltip';
|
||||
import { useFileUpload } from '@/hooks/useFileUpload';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { Model, Tool } from '@/types';
|
||||
@ -136,17 +137,18 @@ export function ChatInput({
|
||||
{/* 左侧按钮 */}
|
||||
<div className="flex items-center gap-1">
|
||||
{/* 添加附件 */}
|
||||
<Tooltip content="添加附件">
|
||||
<button
|
||||
onClick={openFileDialog}
|
||||
className={cn(
|
||||
'w-8 h-8 flex items-center justify-center rounded-lg transition-colors',
|
||||
'w-8 h-8 flex items-center justify-center rounded-lg transition-colors cursor-pointer',
|
||||
'text-[var(--color-text-tertiary)] hover:bg-[var(--color-bg-hover)] hover:text-[var(--color-text-secondary)]',
|
||||
files.length > 0 && 'text-[var(--color-primary)]'
|
||||
)}
|
||||
title="添加附件"
|
||||
>
|
||||
<Plus size={20} />
|
||||
<Paperclip size={20} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
{/* 隐藏的文件输入 */}
|
||||
<input
|
||||
@ -176,19 +178,20 @@ export function ChatInput({
|
||||
/>
|
||||
|
||||
{/* 发送按钮 */}
|
||||
<Tooltip content="发送消息">
|
||||
<button
|
||||
onClick={handleSend}
|
||||
disabled={!message.trim() && files.length === 0}
|
||||
className={cn(
|
||||
'w-[38px] h-[38px] flex items-center justify-center bg-[var(--color-primary)] text-white rounded-xl transition-all duration-150',
|
||||
'w-[38px] h-[38px] flex items-center justify-center bg-[var(--color-primary)] text-white rounded-xl transition-all duration-150 cursor-pointer',
|
||||
message.trim() || files.length > 0
|
||||
? 'hover:bg-[var(--color-primary-hover)] hover:-translate-y-0.5'
|
||||
: 'opacity-50 cursor-not-allowed'
|
||||
)}
|
||||
title="Send message"
|
||||
>
|
||||
<ArrowUp size={18} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Wrench, Search, Terminal, Globe, Check } from 'lucide-react';
|
||||
import { Toggle } from '@/components/ui/Toggle';
|
||||
import { Tooltip } from '@/components/ui/Tooltip';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { Tool } from '@/types';
|
||||
|
||||
@ -41,20 +42,21 @@ export function ToolsDropdown({ tools, onToolToggle, onEnableAllToggle }: ToolsD
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
{/* 触发按钮 */}
|
||||
<div className="relative">
|
||||
<Tooltip content="工具" position="top">
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className={cn(
|
||||
'w-8 h-8 flex items-center justify-center rounded-lg transition-colors',
|
||||
'w-8 h-8 flex items-center justify-center rounded-lg transition-colors cursor-pointer',
|
||||
enabledCount > 0
|
||||
? 'text-[var(--color-primary)] bg-[var(--color-primary-light)]'
|
||||
: 'text-[var(--color-text-tertiary)] hover:bg-[var(--color-bg-hover)] hover:text-[var(--color-text-secondary)]'
|
||||
)}
|
||||
title="Tools"
|
||||
>
|
||||
<Wrench size={20} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
{enabledCount > 0 && (
|
||||
<span className="absolute -top-0.5 -right-0.5 min-w-4 h-4 bg-[var(--color-primary)] text-white text-[10px] font-semibold rounded-full flex items-center justify-center px-1">
|
||||
<span className="absolute -top-0.5 -right-0.5 min-w-4 h-4 bg-[var(--color-primary)] text-white text-[10px] font-semibold rounded-full flex items-center justify-center px-1 pointer-events-none">
|
||||
{enabledCount}
|
||||
</span>
|
||||
)}
|
||||
|
||||
55
src/components/ui/Tooltip.tsx
Normal file
55
src/components/ui/Tooltip.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface TooltipProps {
|
||||
children: ReactNode;
|
||||
content: string;
|
||||
position?: 'top' | 'bottom' | 'left' | 'right';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltip 组件
|
||||
* 鼠标悬停时显示提示文字
|
||||
*/
|
||||
export function Tooltip({ children, content, position = 'top', className }: TooltipProps) {
|
||||
const positionStyles = {
|
||||
top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
|
||||
bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
|
||||
left: 'right-full top-1/2 -translate-y-1/2 mr-2',
|
||||
right: 'left-full top-1/2 -translate-y-1/2 ml-2',
|
||||
};
|
||||
|
||||
const arrowStyles = {
|
||||
top: 'top-full left-1/2 -translate-x-1/2 border-t-gray-800 border-x-transparent border-b-transparent',
|
||||
bottom: 'bottom-full left-1/2 -translate-x-1/2 border-b-gray-800 border-x-transparent border-t-transparent',
|
||||
left: 'left-full top-1/2 -translate-y-1/2 border-l-gray-800 border-y-transparent border-r-transparent',
|
||||
right: 'right-full top-1/2 -translate-y-1/2 border-r-gray-800 border-y-transparent border-l-transparent',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn('relative group/tooltip inline-flex', className)}>
|
||||
{children}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute z-50 px-2.5 py-1.5 text-xs font-medium text-white bg-gray-800 rounded-md',
|
||||
'opacity-0 invisible group-hover/tooltip:opacity-100 group-hover/tooltip:visible',
|
||||
'transition-all duration-200 whitespace-nowrap pointer-events-none',
|
||||
'shadow-lg',
|
||||
positionStyles[position]
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
{/* 小三角箭头 */}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute w-0 h-0 border-4',
|
||||
arrowStyles[position]
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user