Files
dify/web/app/components/workflow/skill/file-tree/tree/tree-node-icon.tsx
yyh 9e10b73b54 refactor(skill): replace @remixicon/react imports with CSS icon classes
Migrate all Remixicon component imports in workflow/skill to Tailwind CSS
icon utility classes (i-ri-*), reducing JS bundle size. Update MenuItem
to accept string icon classes alongside React components. Adjust test
selectors that relied on SVG element queries.
2026-02-09 19:51:05 +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>
)
}