mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 05:11:24 +08:00
Remove deprecated icon components and their associated stories
- Deleted the FilePngIcon and FileSvgIcon components from the icons directory due to low usage. - Removed the ToolsCallingIcon component and its related stories, as it did not meet the UI library extraction criteria. - Updated the index.ts file to reflect these removals and cleaned up the export list accordingly. - Ensured that all related story files for the removed icons were also deleted to maintain a clean codebase.
This commit is contained in:
parent
1156b12ac6
commit
6abe5ab8c3
@ -1,86 +0,0 @@
|
||||
// Original path: src/renderer/src/components/Icons/FileIcons.tsx
|
||||
import type { CSSProperties, SVGProps } from 'react'
|
||||
|
||||
interface BaseFileIconProps extends SVGProps<SVGSVGElement> {
|
||||
size?: string | number
|
||||
text?: string
|
||||
}
|
||||
|
||||
const textStyle: CSSProperties = {
|
||||
fontStyle: 'italic',
|
||||
fontSize: '7.70985px',
|
||||
lineHeight: 0.8,
|
||||
fontFamily: "'Times New Roman'",
|
||||
textAlign: 'center',
|
||||
writingMode: 'horizontal-tb',
|
||||
direction: 'ltr',
|
||||
textAnchor: 'middle',
|
||||
fill: 'none',
|
||||
stroke: '#000000',
|
||||
strokeWidth: '0.289119',
|
||||
strokeLinejoin: 'round',
|
||||
strokeDasharray: 'none'
|
||||
}
|
||||
|
||||
const tspanStyle: CSSProperties = {
|
||||
fontStyle: 'normal',
|
||||
fontVariant: 'normal',
|
||||
fontWeight: 'normal',
|
||||
fontStretch: 'condensed',
|
||||
fontSize: '7.70985px',
|
||||
lineHeight: 0.8,
|
||||
fontFamily: 'Arial',
|
||||
fill: '#000000',
|
||||
fillOpacity: 1,
|
||||
strokeWidth: '0.289119',
|
||||
strokeDasharray: 'none'
|
||||
}
|
||||
|
||||
const BaseFileIcon = ({ size = '1.1em', text = 'SVG', ...props }: BaseFileIconProps) => (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
<defs id="defs4" />
|
||||
<path d="m 14,2 v 4 a 2,2 0 0 0 2,2 h 4" id="path3" />
|
||||
<path d="M 15,2 H 6 A 2,2 0 0 0 4,4 v 16 a 2,2 0 0 0 2,2 h 12 a 2,2 0 0 0 2,-2 V 7 Z" id="path4" />
|
||||
<text
|
||||
xmlSpace="preserve"
|
||||
style={textStyle}
|
||||
x="12.478625"
|
||||
y="17.170216"
|
||||
id="text4"
|
||||
transform="scale(0.96196394,1.03954)">
|
||||
<tspan id="tspan4" x="12.478625" y="17.170216" style={tspanStyle}>
|
||||
{text}
|
||||
</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
)
|
||||
|
||||
/**
|
||||
* @deprecated 此图标使用频率仅为 1 次,不符合 UI 库提取标准(需 ≥3 次)
|
||||
* 计划在未来版本中移除。
|
||||
*
|
||||
* This icon has only 1 usage and does not meet the UI library extraction criteria (requires ≥3 usages).
|
||||
* Planned for removal in future versions.
|
||||
*/
|
||||
export const FileSvgIcon = (props: Omit<BaseFileIconProps, 'text'>) => <BaseFileIcon text="SVG" {...props} />
|
||||
|
||||
/**
|
||||
* @deprecated 此图标使用频率仅为 2 次,不符合 UI 库提取标准(需 ≥3 次)
|
||||
* 计划在未来版本中移除。
|
||||
*
|
||||
* This icon has only 2 usages and does not meet the UI library extraction criteria (requires ≥3 usages).
|
||||
* Planned for removal in future versions.
|
||||
*/
|
||||
export const FilePngIcon = (props: Omit<BaseFileIconProps, 'text'>) => <BaseFileIcon text="PNG" {...props} />
|
||||
@ -1,53 +0,0 @@
|
||||
import type { LucideIcon } from 'lucide-react'
|
||||
import {
|
||||
AlignLeft,
|
||||
Copy,
|
||||
Eye,
|
||||
Pencil,
|
||||
RefreshCw,
|
||||
RotateCcw,
|
||||
ScanLine,
|
||||
Search,
|
||||
Trash,
|
||||
WrapText,
|
||||
Wrench
|
||||
} from 'lucide-react'
|
||||
import React from 'react'
|
||||
|
||||
// 创建一个 Icon 工厂函数
|
||||
export function createIcon(IconComponent: LucideIcon, defaultSize: string | number = '1rem') {
|
||||
const Icon = ({
|
||||
ref,
|
||||
...props
|
||||
}: React.ComponentProps<typeof IconComponent> & { ref?: React.RefObject<SVGSVGElement | null> }) => (
|
||||
<IconComponent ref={ref} size={defaultSize} {...props} />
|
||||
)
|
||||
Icon.displayName = `Icon(${IconComponent.displayName || IconComponent.name})`
|
||||
return Icon
|
||||
}
|
||||
|
||||
// 预定义的常用图标(向后兼容,只导入需要的图标)
|
||||
export const CopyIcon = createIcon(Copy)
|
||||
export const DeleteIcon = createIcon(Trash)
|
||||
export const EditIcon = createIcon(Pencil)
|
||||
export const RefreshIcon = createIcon(RefreshCw)
|
||||
export const ResetIcon = createIcon(RotateCcw)
|
||||
|
||||
/**
|
||||
* @deprecated 此组件使用频率为 0 次,不符合 UI 库提取标准(需 ≥3 次)
|
||||
* 计划在未来版本中移除。虽然主项目中有本地副本,但完全未被导入使用。
|
||||
*
|
||||
* This icon has 0 usages and does not meet the UI library extraction criteria (requires ≥3 usages).
|
||||
* Planned for removal in future versions.
|
||||
*/
|
||||
export const ToolIcon = createIcon(Wrench)
|
||||
|
||||
export const VisionIcon = createIcon(Eye)
|
||||
export const WebSearchIcon = createIcon(Search)
|
||||
export const WrapIcon = createIcon(WrapText)
|
||||
export const UnWrapIcon = createIcon(AlignLeft)
|
||||
export const OcrIcon = createIcon(ScanLine)
|
||||
|
||||
// 导出 createIcon 以便用户自行创建图标组件
|
||||
export type { LucideIcon }
|
||||
export type { LucideProps } from 'lucide-react'
|
||||
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @deprecated 此组件使用频率为 0 次,不符合 UI 库提取标准(需 ≥3 次)
|
||||
* 计划在未来版本中移除。虽然主项目中有本地副本,但完全未被导入使用。
|
||||
*
|
||||
* This component has 0 usages and does not meet the UI library extraction criteria (requires ≥3 usages).
|
||||
* Planned for removal in future versions.
|
||||
*/
|
||||
|
||||
// Original path: src/renderer/src/components/Icons/SvgSpinners180Ring.tsx
|
||||
import type { SVGProps } from 'react'
|
||||
|
||||
import { cn } from '../../../utils'
|
||||
|
||||
interface SvgSpinners180RingProps extends SVGProps<SVGSVGElement> {
|
||||
size?: number | string
|
||||
}
|
||||
|
||||
export function SvgSpinners180Ring(props: SvgSpinners180RingProps) {
|
||||
const { size = '1em', className, ...svgProps } = props
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
{...svgProps}
|
||||
className={cn('animate-spin', className)}>
|
||||
{/* Icon from SVG Spinners by Utkarsh Verma - https://github.com/n3r4zzurr0/svg-spinners/blob/main/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default SvgSpinners180Ring
|
||||
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* @deprecated 此组件使用频率仅为 1 次,不符合 UI 库提取标准(需 ≥3 次)
|
||||
* 计划在未来版本中移除。建议直接使用 lucide-react 的 Wrench 图标。
|
||||
*
|
||||
* This component has only 1 usage and does not meet the UI library extraction criteria (requires ≥3 usages).
|
||||
* Planned for removal in future versions. Consider using Wrench icon from lucide-react directly.
|
||||
*/
|
||||
|
||||
// Original: src/renderer/src/components/Icons/ToolsCallingIcon.tsx
|
||||
import { Tooltip, type TooltipProps } from '@heroui/react'
|
||||
import { Wrench } from 'lucide-react'
|
||||
import React from 'react'
|
||||
|
||||
import { cn } from '../../../utils'
|
||||
|
||||
interface ToolsCallingIconProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
className?: string
|
||||
iconClassName?: string
|
||||
TooltipProps?: TooltipProps
|
||||
}
|
||||
|
||||
const ToolsCallingIcon = ({ className, iconClassName, TooltipProps, ...props }: ToolsCallingIconProps) => {
|
||||
return (
|
||||
<div className={cn('flex justify-center items-center', className)} {...props}>
|
||||
<Tooltip {...TooltipProps}>
|
||||
<Wrench className={cn('w-4 h-4 mr-1.5 text-[#00b96b]', iconClassName)} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ToolsCallingIcon
|
||||
@ -22,24 +22,6 @@ export { default as Scrollbar } from './composites/Scrollbar'
|
||||
export { default as ThinkingEffect } from './composites/ThinkingEffect'
|
||||
|
||||
// Icon Components
|
||||
export { FilePngIcon, FileSvgIcon } from './icons/FileIcons'
|
||||
// export type { LucideIcon, LucideProps } from './icons/Icon'
|
||||
// export {
|
||||
// CopyIcon,
|
||||
// createIcon,
|
||||
// DeleteIcon,
|
||||
// EditIcon,
|
||||
// OcrIcon,
|
||||
// RefreshIcon,
|
||||
// ResetIcon,
|
||||
// ToolIcon,
|
||||
// UnWrapIcon,
|
||||
// VisionIcon,
|
||||
// WebSearchIcon,
|
||||
// WrapIcon
|
||||
// } from './icons/Icon'
|
||||
export { default as SvgSpinners180Ring } from './icons/SvgSpinners180Ring'
|
||||
export { default as ToolsCallingIcon } from './icons/ToolsCallingIcon'
|
||||
|
||||
// Brand Logo Icons (彩色品牌 Logo 图标 - 84个)
|
||||
// 推荐使用 '@cherrystudio/ui/icons' 路径导入
|
||||
|
||||
@ -1,270 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { FilePngIcon, FileSvgIcon } from '../../../src/components/icons/FileIcons'
|
||||
|
||||
// Create a dummy component for the story
|
||||
const FileIconsShowcase = () => <div />
|
||||
|
||||
const meta: Meta<typeof FileIconsShowcase> = {
|
||||
title: 'Components/Icons/FileIcons',
|
||||
component: FileIconsShowcase,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
size: {
|
||||
description: '图标大小',
|
||||
control: { type: 'text' },
|
||||
defaultValue: '1.1em'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Basic File Icons
|
||||
export const BasicFileIcons: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">文件类型图标 (默认尺寸: 1.1em)</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon />
|
||||
<span className="text-xs text-gray-600">SVG 文件</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon />
|
||||
<span className="text-xs text-gray-600">PNG 文件</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Different Sizes
|
||||
export const DifferentSizes: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同尺寸的 SVG 图标</h3>
|
||||
<div className="flex items-end gap-4">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="16" />
|
||||
<span className="text-xs text-gray-600">16px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="24" />
|
||||
<span className="text-xs text-gray-600">24px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" />
|
||||
<span className="text-xs text-gray-600">32px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="48" />
|
||||
<span className="text-xs text-gray-600">48px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="64" />
|
||||
<span className="text-xs text-gray-600">64px</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同尺寸的 PNG 图标</h3>
|
||||
<div className="flex items-end gap-4">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="16" />
|
||||
<span className="text-xs text-gray-600">16px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="24" />
|
||||
<span className="text-xs text-gray-600">24px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" />
|
||||
<span className="text-xs text-gray-600">32px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="48" />
|
||||
<span className="text-xs text-gray-600">48px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="64" />
|
||||
<span className="text-xs text-gray-600">64px</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Custom Colors
|
||||
export const CustomColors: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">自定义颜色 - SVG 图标</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" color="#3B82F6" />
|
||||
<span className="text-xs text-gray-600">蓝色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" color="#10B981" />
|
||||
<span className="text-xs text-gray-600">绿色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" color="#F59E0B" />
|
||||
<span className="text-xs text-gray-600">橙色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" color="#EF4444" />
|
||||
<span className="text-xs text-gray-600">红色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileSvgIcon size="32" color="#8B5CF6" />
|
||||
<span className="text-xs text-gray-600">紫色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">自定义颜色 - PNG 图标</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" color="#3B82F6" />
|
||||
<span className="text-xs text-gray-600">蓝色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" color="#10B981" />
|
||||
<span className="text-xs text-gray-600">绿色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" color="#F59E0B" />
|
||||
<span className="text-xs text-gray-600">橙色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" color="#EF4444" />
|
||||
<span className="text-xs text-gray-600">红色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FilePngIcon size="32" color="#8B5CF6" />
|
||||
<span className="text-xs text-gray-600">紫色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// In File List Context
|
||||
export const InFileListContext: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">文件列表中的使用示例</h3>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-3 rounded p-2 hover:bg-gray-50">
|
||||
<FileSvgIcon size="20" />
|
||||
<span className="flex-1">illustration.svg</span>
|
||||
<span className="text-xs text-gray-500">45 KB</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 rounded p-2 hover:bg-gray-50">
|
||||
<FilePngIcon size="20" />
|
||||
<span className="flex-1">screenshot.png</span>
|
||||
<span className="text-xs text-gray-500">1.2 MB</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 rounded p-2 hover:bg-gray-50">
|
||||
<FileSvgIcon size="20" />
|
||||
<span className="flex-1">logo.svg</span>
|
||||
<span className="text-xs text-gray-500">12 KB</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 rounded p-2 hover:bg-gray-50">
|
||||
<FilePngIcon size="20" />
|
||||
<span className="flex-1">background.png</span>
|
||||
<span className="text-xs text-gray-500">2.8 MB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// File Type Grid
|
||||
export const FileTypeGrid: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">文件类型网格展示</h3>
|
||||
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div className="flex flex-col items-center gap-2 rounded-lg border border-gray-200 p-4 hover:border-blue-500">
|
||||
<FileSvgIcon size="48" />
|
||||
<span className="text-sm font-medium">SVG</span>
|
||||
<span className="text-xs text-gray-600">矢量图形</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-2 rounded-lg border border-gray-200 p-4 hover:border-blue-500">
|
||||
<FilePngIcon size="48" />
|
||||
<span className="text-sm font-medium">PNG</span>
|
||||
<span className="text-xs text-gray-600">位图图像</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-2 rounded-lg border border-gray-200 p-4 hover:border-blue-500">
|
||||
<FileSvgIcon size="48" color="#10B981" />
|
||||
<span className="text-sm font-medium">SVG</span>
|
||||
<span className="text-xs text-gray-600">已处理</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-2 rounded-lg border border-gray-200 p-4 hover:border-blue-500">
|
||||
<FilePngIcon size="48" color="#EF4444" />
|
||||
<span className="text-sm font-medium">PNG</span>
|
||||
<span className="text-xs text-gray-600">错误状态</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Interactive Example
|
||||
export const InteractiveExample: Story = {
|
||||
render: () => {
|
||||
const fileTypes = [
|
||||
{ icon: FileSvgIcon, name: 'Vector Graphics', ext: 'SVG', color: '#3B82F6' },
|
||||
{ icon: FilePngIcon, name: 'Raster Image', ext: 'PNG', color: '#10B981' }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">交互式文件类型选择器</h3>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{fileTypes.map((fileType, index) => {
|
||||
const IconComponent = fileType.icon
|
||||
return (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
className="flex items-center gap-3 rounded-lg border border-gray-200 p-4 text-left transition-all hover:border-blue-500 hover:shadow-md focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20">
|
||||
<IconComponent size="32" color={fileType.color} />
|
||||
<div>
|
||||
<div className="font-medium">{fileType.ext} 文件</div>
|
||||
<div className="text-sm text-gray-600">{fileType.name}</div>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,339 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import SvgSpinners180Ring from '../../../src/components/icons/SvgSpinners180Ring'
|
||||
|
||||
const meta: Meta<typeof SvgSpinners180Ring> = {
|
||||
title: 'Components/Icons/SvgSpinners180Ring',
|
||||
component: SvgSpinners180Ring,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'⚠️ **已废弃** - 此组件使用频率为 0 次,不符合 UI 库提取标准(需 ≥3 次)。计划在未来版本中移除。虽然主项目中有本地副本,但完全未被导入使用。'
|
||||
}
|
||||
}
|
||||
},
|
||||
tags: ['autodocs', 'deprecated'],
|
||||
argTypes: {
|
||||
size: {
|
||||
description: '加载图标大小',
|
||||
control: { type: 'text' },
|
||||
defaultValue: '1em'
|
||||
},
|
||||
className: {
|
||||
description: '自定义 CSS 类名',
|
||||
control: { type: 'text' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Basic Spinner
|
||||
export const BasicSpinner: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">基础加载动画</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
<SvgSpinners180Ring />
|
||||
<span className="text-sm text-gray-600">默认尺寸 (1em)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Different Sizes
|
||||
export const DifferentSizes: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同尺寸的加载动画</h3>
|
||||
<div className="flex items-end gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="12" />
|
||||
<span className="text-xs text-gray-600">12px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="16" />
|
||||
<span className="text-xs text-gray-600">16px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="20" />
|
||||
<span className="text-xs text-gray-600">20px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" />
|
||||
<span className="text-xs text-gray-600">24px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="32" />
|
||||
<span className="text-xs text-gray-600">32px</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="48" />
|
||||
<span className="text-xs text-gray-600">48px</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Different Colors
|
||||
export const DifferentColors: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同颜色的加载动画</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-blue-500" />
|
||||
<span className="text-xs text-gray-600">蓝色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-green-500" />
|
||||
<span className="text-xs text-gray-600">绿色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-orange-500" />
|
||||
<span className="text-xs text-gray-600">橙色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-red-500" />
|
||||
<span className="text-xs text-gray-600">红色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-purple-500" />
|
||||
<span className="text-xs text-gray-600">紫色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="text-gray-500" />
|
||||
<span className="text-xs text-gray-600">灰色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Loading States in Buttons
|
||||
export const LoadingStatesInButtons: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">按钮中的加载状态</h3>
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
|
||||
disabled>
|
||||
<SvgSpinners180Ring size="16" />
|
||||
<span>加载中...</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded bg-green-500 px-4 py-2 text-white hover:bg-green-600"
|
||||
disabled>
|
||||
<SvgSpinners180Ring size="16" />
|
||||
<span>保存中</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded bg-orange-500 px-4 py-2 text-white hover:bg-orange-600"
|
||||
disabled>
|
||||
<SvgSpinners180Ring size="16" />
|
||||
<span>上传中</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded border border-gray-300 bg-white px-4 py-2 text-gray-700 hover:bg-gray-50"
|
||||
disabled>
|
||||
<SvgSpinners180Ring size="16" className="text-gray-500" />
|
||||
<span>处理中</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Loading Cards
|
||||
export const LoadingCards: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">加载状态卡片</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<SvgSpinners180Ring size="20" className="text-blue-500" />
|
||||
<div>
|
||||
<h4 className="font-medium">AI 模型响应中</h4>
|
||||
<p className="text-sm text-gray-600">正在生成回复...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<SvgSpinners180Ring size="20" className="text-green-500" />
|
||||
<div>
|
||||
<h4 className="font-medium">文件上传中</h4>
|
||||
<p className="text-sm text-gray-600">75% 完成</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<SvgSpinners180Ring size="20" className="text-orange-500" />
|
||||
<div>
|
||||
<h4 className="font-medium">数据同步中</h4>
|
||||
<p className="text-sm text-gray-600">请稍候...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<SvgSpinners180Ring size="20" className="text-purple-500" />
|
||||
<div>
|
||||
<h4 className="font-medium">模型训练中</h4>
|
||||
<p className="text-sm text-gray-600">预计2分钟</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Inline Loading States
|
||||
export const InlineLoadingStates: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">行内加载状态</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<SvgSpinners180Ring size="14" className="text-blue-500" />
|
||||
<span className="text-sm">正在检查网络连接...</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<SvgSpinners180Ring size="14" className="text-green-500" />
|
||||
<span className="text-sm">正在保存更改...</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<SvgSpinners180Ring size="14" className="text-orange-500" />
|
||||
<span className="text-sm">正在验证凭据...</span>
|
||||
</div>
|
||||
|
||||
<div className="rounded bg-blue-50 p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<SvgSpinners180Ring size="16" className="text-blue-600" />
|
||||
<span className="text-sm text-blue-800">系统正在处理您的请求,请稍候...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Loading States with Different Speeds
|
||||
export const LoadingStatesWithDifferentSpeeds: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同速度的加载动画</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="animate-spin" style={{ animationDuration: '2s' }} />
|
||||
<span className="text-xs text-gray-600">慢速 (2s)</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" />
|
||||
<span className="text-xs text-gray-600">默认速度</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<SvgSpinners180Ring size="24" className="animate-spin" style={{ animationDuration: '0.5s' }} />
|
||||
<span className="text-xs text-gray-600">快速 (0.5s)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Full Page Loading
|
||||
export const FullPageLoading: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">全屏加载示例</h3>
|
||||
<div className="relative h-64 w-full overflow-hidden rounded-lg border border-gray-200 bg-white">
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center bg-white/80">
|
||||
<SvgSpinners180Ring size="32" className="text-blue-500" />
|
||||
<p className="mt-4 text-sm text-gray-600">页面加载中,请稍候...</p>
|
||||
</div>
|
||||
|
||||
{/* 模拟页面内容 */}
|
||||
<div className="p-6 opacity-30">
|
||||
<div className="mb-4 h-6 w-1/3 rounded bg-gray-200"></div>
|
||||
<div className="mb-2 h-4 w-full rounded bg-gray-200"></div>
|
||||
<div className="mb-2 h-4 w-5/6 rounded bg-gray-200"></div>
|
||||
<div className="mb-4 h-4 w-4/6 rounded bg-gray-200"></div>
|
||||
<div className="mb-2 h-4 w-full rounded bg-gray-200"></div>
|
||||
<div className="h-4 w-3/4 rounded bg-gray-200"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Interactive Loading Demo
|
||||
export const InteractiveLoadingDemo: Story = {
|
||||
render: () => {
|
||||
const loadingStates = [
|
||||
{ text: '发送消息', color: 'text-blue-500', bgColor: 'bg-blue-500' },
|
||||
{ text: '上传文件', color: 'text-green-500', bgColor: 'bg-green-500' },
|
||||
{ text: '生成内容', color: 'text-purple-500', bgColor: 'bg-purple-500' },
|
||||
{ text: '搜索结果', color: 'text-orange-500', bgColor: 'bg-orange-500' }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">交互式加载演示</h3>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{loadingStates.map((state, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
className={`flex items-center justify-center gap-2 rounded-lg ${state.bgColor} px-4 py-3 text-white transition-all hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2`}
|
||||
onClick={() => {
|
||||
// 演示用途 - 在实际应用中这里会触发真实的加载状态
|
||||
alert(`触发 ${state.text} 加载状态`)
|
||||
}}>
|
||||
<SvgSpinners180Ring size="16" />
|
||||
<span>{state.text}中...</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-gray-500">点击按钮查看加载状态的交互效果</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,374 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import ToolsCallingIcon from '../../../src/components/icons/ToolsCallingIcon'
|
||||
|
||||
const meta: Meta<typeof ToolsCallingIcon> = {
|
||||
title: 'Components/Icons/ToolsCallingIcon',
|
||||
component: ToolsCallingIcon,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'⚠️ **已废弃** - 此组件使用频率仅为 1 次,不符合 UI 库提取标准(需 ≥3 次)。计划在未来版本中移除。建议直接使用 lucide-react 的 Wrench 图标。'
|
||||
}
|
||||
}
|
||||
},
|
||||
tags: ['autodocs', 'deprecated'],
|
||||
argTypes: {
|
||||
className: {
|
||||
description: '容器的自定义 CSS 类名',
|
||||
control: { type: 'text' }
|
||||
},
|
||||
iconClassName: {
|
||||
description: '图标的自定义 CSS 类名',
|
||||
control: { type: 'text' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Basic Tools Calling Icon
|
||||
export const BasicToolsCallingIcon: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">基础工具调用图标</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
<ToolsCallingIcon />
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-gray-600">悬停图标查看工具提示,显示"函数调用"文本</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Different Sizes
|
||||
export const DifferentSizes: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同尺寸的工具调用图标</h3>
|
||||
<div className="flex items-end gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-3 h-3" />
|
||||
<span className="text-xs text-gray-600">小号</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon />
|
||||
<span className="text-xs text-gray-600">默认</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-5 h-5" />
|
||||
<span className="text-xs text-gray-600">中号</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-6 h-6" />
|
||||
<span className="text-xs text-gray-600">大号</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-8 h-8" />
|
||||
<span className="text-xs text-gray-600">特大号</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Different Colors
|
||||
export const DifferentColors: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="mb-3 font-semibold">不同颜色的工具调用图标</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon />
|
||||
<span className="text-xs text-gray-600">默认绿色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-blue-500" />
|
||||
<span className="text-xs text-gray-600">蓝色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-orange-500" />
|
||||
<span className="text-xs text-gray-600">橙色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-red-500" />
|
||||
<span className="text-xs text-gray-600">红色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-purple-500" />
|
||||
<span className="text-xs text-gray-600">紫色</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-gray-500" />
|
||||
<span className="text-xs text-gray-600">灰色</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Model Features Context
|
||||
export const ModelFeaturesContext: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">在模型功能标识中的使用</h3>
|
||||
|
||||
<div className="grid gap-4">
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<h4 className="font-medium">GPT-4 Turbo</h4>
|
||||
<ToolsCallingIcon />
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">支持函数调用的先进模型,可以调用外部工具和API</p>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<span className="rounded bg-green-100 px-2 py-1 text-xs text-green-800">函数调用</span>
|
||||
<span className="rounded bg-blue-100 px-2 py-1 text-xs text-blue-800">多模态</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<h4 className="font-medium">Claude 3.5 Sonnet</h4>
|
||||
<ToolsCallingIcon />
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">Anthropic的高性能模型,具备强大的工具使用能力</p>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<span className="rounded bg-green-100 px-2 py-1 text-xs text-green-800">函数调用</span>
|
||||
<span className="rounded bg-orange-100 px-2 py-1 text-xs text-orange-800">推理</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<h4 className="font-medium">Llama 3.1 8B</h4>
|
||||
{/* 不支持函数调用 */}
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">Meta的开源模型,适用于基础对话任务</p>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<span className="rounded bg-gray-100 px-2 py-1 text-xs text-gray-800">文本生成</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Chat Message Context
|
||||
export const ChatMessageContext: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">在聊天消息中的使用</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="rounded-lg bg-blue-50 p-3">
|
||||
<div className="mb-1 flex items-center gap-2 text-sm text-blue-800">
|
||||
<ToolsCallingIcon iconClassName="w-3.5 h-3.5 mr-1 text-[#00b96b]" />
|
||||
<span className="font-medium">调用工具: weather_api</span>
|
||||
</div>
|
||||
<p className="text-sm text-blue-700">正在获取北京的天气信息...</p>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg bg-green-50 p-3">
|
||||
<div className="mb-1 flex items-center gap-2 text-sm text-green-800">
|
||||
<ToolsCallingIcon iconClassName="w-3.5 h-3.5 mr-1 text-[#00b96b]" />
|
||||
<span className="font-medium">调用工具: search_web</span>
|
||||
</div>
|
||||
<p className="text-sm text-green-700">正在搜索最新的AI新闻...</p>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg bg-orange-50 p-3">
|
||||
<div className="mb-1 flex items-center gap-2 text-sm text-orange-800">
|
||||
<ToolsCallingIcon iconClassName="w-3.5 h-3.5 mr-1 text-[#00b96b]" />
|
||||
<span className="font-medium">调用工具: code_interpreter</span>
|
||||
</div>
|
||||
<p className="text-sm text-orange-700">正在执行Python代码计算结果...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Tool Availability Indicator
|
||||
export const ToolAvailabilityIndicator: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">工具可用性指示器</h3>
|
||||
|
||||
<div className="rounded-lg border border-gray-200">
|
||||
<div className="border-b border-gray-200 p-3">
|
||||
<h4 className="font-medium text-gray-900">可用工具</h4>
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-gray-200">
|
||||
<div className="flex items-center justify-between p-3 hover:bg-gray-50">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-[#00b96b]" />
|
||||
<span className="font-medium">天气查询</span>
|
||||
</div>
|
||||
<span className="rounded-full bg-green-100 px-2 py-1 text-xs text-green-800">可用</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 hover:bg-gray-50">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-[#00b96b]" />
|
||||
<span className="font-medium">网络搜索</span>
|
||||
</div>
|
||||
<span className="rounded-full bg-green-100 px-2 py-1 text-xs text-green-800">可用</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 hover:bg-gray-50 opacity-60">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-gray-400" />
|
||||
<span className="font-medium">代码执行</span>
|
||||
</div>
|
||||
<span className="rounded-full bg-gray-100 px-2 py-1 text-xs text-gray-800">不可用</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 hover:bg-gray-50">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-yellow-600" />
|
||||
<span className="font-medium">图像生成</span>
|
||||
</div>
|
||||
<span className="rounded-full bg-yellow-100 px-2 py-1 text-xs text-yellow-800">限制使用</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Interactive Tool Selection
|
||||
export const InteractiveToolSelection: Story = {
|
||||
render: () => {
|
||||
const tools = [
|
||||
{ name: '天气查询', description: '获取实时天气信息', available: true },
|
||||
{ name: '网络搜索', description: '搜索最新信息', available: true },
|
||||
{ name: '代码执行', description: '运行Python代码', available: false },
|
||||
{ name: '图像分析', description: '分析和描述图像', available: true },
|
||||
{ name: '数据可视化', description: '创建图表和图形', available: false }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">交互式工具选择器</h3>
|
||||
|
||||
<div className="grid grid-cols-1 gap-3">
|
||||
{tools.map((tool, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
className={`flex items-center gap-3 rounded-lg border p-3 text-left transition-all hover:shadow-md focus:outline-none focus:ring-2 focus:ring-blue-500/20 ${
|
||||
tool.available
|
||||
? 'border-gray-200 hover:border-blue-500'
|
||||
: 'border-gray-200 opacity-60 cursor-not-allowed'
|
||||
}`}
|
||||
disabled={!tool.available}>
|
||||
<ToolsCallingIcon
|
||||
iconClassName={`w-4 h-4 mr-1.5 ${tool.available ? 'text-[#00b96b]' : 'text-gray-400'}`}
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="font-medium">{tool.name}</div>
|
||||
<div className="text-sm text-gray-600">{tool.description}</div>
|
||||
</div>
|
||||
<div className="text-xs">
|
||||
{tool.available ? (
|
||||
<span className="rounded bg-green-100 px-2 py-1 text-green-800">可用</span>
|
||||
) : (
|
||||
<span className="rounded bg-gray-100 px-2 py-1 text-gray-800">不可用</span>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Loading Tool Calls
|
||||
export const LoadingToolCalls: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">工具调用加载状态</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="rounded-lg border border-gray-200 p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon />
|
||||
<span className="font-medium">正在调用工具...</span>
|
||||
<div className="h-2 w-2 animate-pulse rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-gray-600">weather_api(city="北京")</p>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-green-200 bg-green-50 p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-green-600" />
|
||||
<span className="font-medium text-green-800">工具调用完成</span>
|
||||
<span className="text-green-600">✓</span>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-green-700">已获取北京天气信息:晴天,温度 22°C</p>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-red-200 bg-red-50 p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<ToolsCallingIcon iconClassName="w-4 h-4 mr-1.5 text-red-600" />
|
||||
<span className="font-medium text-red-800">工具调用失败</span>
|
||||
<span className="text-red-600">✗</span>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-red-700">API密钥无效,请检查配置</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Settings Panel
|
||||
export const SettingsPanel: Story = {
|
||||
render: () => (
|
||||
<div className="space-y-4">
|
||||
<h3 className="mb-3 font-semibold">设置面板中的使用</h3>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<ToolsCallingIcon />
|
||||
<h4 className="font-medium">函数调用设置</h4>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium">启用函数调用</div>
|
||||
<div className="text-sm text-gray-600">允许AI模型调用外部工具</div>
|
||||
</div>
|
||||
<input type="checkbox" className="rounded" defaultChecked />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium">自动确认调用</div>
|
||||
<div className="text-sm text-gray-600">自动执行安全的工具调用</div>
|
||||
</div>
|
||||
<input type="checkbox" className="rounded" />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium">显示调用详情</div>
|
||||
<div className="text-sm text-gray-600">在聊天中显示工具调用过程</div>
|
||||
</div>
|
||||
<input type="checkbox" className="rounded" defaultChecked />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user