Files
dify/web/app/components/workflow/skill/file-tree/tree-node-icon.tsx
yyh 919d7ef5cd refactor(skill): replace React icon components with CSS Icons
Migrate all icon usage in the skill directory from @remixicon/react
and custom SVG components to Tailwind CSS icon classes (i-ri-*, i-custom-*).
Update MenuItem API to accept string class names instead of React.ElementType.
2026-01-29 21:57:17 +08:00

60 lines
1.7 KiB
TypeScript

'use client'
// Icon rendering for tree nodes (folder/file icons with dirty indicator)
import type { FileAppearanceType } from '@/app/components/base/file-uploader/types'
import { useTranslation } from 'react-i18next'
import FileTypeIcon from '@/app/components/base/file-uploader/file-type-icon'
import { cn } from '@/utils/classnames'
import { getFileIconType } from '../utils/file-utils'
type TreeNodeIconProps = {
isFolder: boolean
isOpen: boolean
fileName: string
extension?: string
isDirty: boolean
onToggle?: (e: React.MouseEvent) => void
}
export const TreeNodeIcon = ({
isFolder,
isOpen,
fileName,
extension,
isDirty,
onToggle,
}: TreeNodeIconProps) => {
const { t } = useTranslation('workflow')
if (isFolder) {
return (
<button
type="button"
tabIndex={-1}
onClick={onToggle}
aria-label={t('skillSidebar.toggleFolder')}
className={cn(
'flex size-full items-center justify-center rounded',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-components-input-border-active',
)}
>
{isOpen
? <span className="i-ri-folder-open-line size-4 text-text-accent" aria-hidden="true" />
: <span className="i-ri-folder-line size-4 text-text-secondary" aria-hidden="true" />}
</button>
)
}
const fileIconType = getFileIconType(fileName, extension)
return (
<div className="relative flex size-full items-center justify-center">
<FileTypeIcon type={fileIconType as FileAppearanceType} size="sm" />
{isDirty && (
<span className="absolute -bottom-px -right-px size-[7px] rounded-full border border-white bg-text-warning-secondary" />
)}
</div>
)
}