diff --git a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx
index ccd2dd53cc..d462ca6449 100644
--- a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx
+++ b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx
@@ -2,7 +2,7 @@
import type { Area } from 'react-easy-crop'
import type { OnImageInput } from '@/app/components/base/app-icon-picker/ImageInput'
-import type { AvatarProps } from '@/app/components/base/avatar'
+import type { AvatarProps } from '@/app/components/base/ui/avatar'
import type { ImageFile } from '@/types/app'
import { RiDeleteBin5Line, RiPencilLine } from '@remixicon/react'
import * as React from 'react'
@@ -10,10 +10,10 @@ import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import ImageInput from '@/app/components/base/app-icon-picker/ImageInput'
import getCroppedImg from '@/app/components/base/app-icon-picker/utils'
-import { Avatar } from '@/app/components/base/avatar'
import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import { useLocalFileUploader } from '@/app/components/base/image-uploader/hooks'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { Dialog, DialogContent } from '@/app/components/base/ui/dialog'
import { toast } from '@/app/components/base/ui/toast'
import { DISABLE_UPLOAD_IMAGE_AS_ICON } from '@/config'
diff --git a/web/app/account/(commonLayout)/avatar.tsx b/web/app/account/(commonLayout)/avatar.tsx
index 36a510cf63..b81c96df74 100644
--- a/web/app/account/(commonLayout)/avatar.tsx
+++ b/web/app/account/(commonLayout)/avatar.tsx
@@ -6,9 +6,9 @@ import {
import { Fragment } from 'react'
import { useTranslation } from 'react-i18next'
import { resetUser } from '@/app/components/base/amplitude/utils'
-import { Avatar } from '@/app/components/base/avatar'
import { LogOut01 } from '@/app/components/base/icons/src/vender/line/general'
import PremiumBadge from '@/app/components/base/premium-badge'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { useProviderContext } from '@/context/provider-context'
import { useRouter } from '@/next/navigation'
import { useLogout, useUserProfile } from '@/service/use-common'
diff --git a/web/app/account/oauth/authorize/page.tsx b/web/app/account/oauth/authorize/page.tsx
index 2c849fd542..b0b7f557a4 100644
--- a/web/app/account/oauth/authorize/page.tsx
+++ b/web/app/account/oauth/authorize/page.tsx
@@ -10,9 +10,9 @@ import {
import * as React from 'react'
import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
import Button from '@/app/components/base/button'
import Loading from '@/app/components/base/loading'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { toast } from '@/app/components/base/ui/toast'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { setPostLoginRedirect } from '@/app/signin/utils/post-login-redirect'
diff --git a/web/app/components/app/app-access-control/add-member-or-group-pop.tsx b/web/app/components/app/app-access-control/add-member-or-group-pop.tsx
index d7e48f2d1f..b25fb94191 100644
--- a/web/app/components/app/app-access-control/add-member-or-group-pop.tsx
+++ b/web/app/components/app/app-access-control/add-member-or-group-pop.tsx
@@ -5,12 +5,12 @@ import { RiAddCircleFill, RiArrowRightSLine, RiOrganizationChart } from '@remixi
import { useDebounce } from 'ahooks'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { useSelector } from '@/context/app-context'
import { SubjectType } from '@/models/access-control'
import { useSearchForWhiteListCandidates } from '@/service/access-control'
import { cn } from '@/utils/classnames'
import useAccessControlStore from '../../../../context/access-control-store'
-import { Avatar } from '../../base/avatar'
import Button from '../../base/button'
import Checkbox from '../../base/checkbox'
import Input from '../../base/input'
diff --git a/web/app/components/app/app-access-control/specific-groups-or-members.tsx b/web/app/components/app/app-access-control/specific-groups-or-members.tsx
index 2c0e4b2694..8f4e71c8d2 100644
--- a/web/app/components/app/app-access-control/specific-groups-or-members.tsx
+++ b/web/app/components/app/app-access-control/specific-groups-or-members.tsx
@@ -3,10 +3,10 @@ import type { AccessControlAccount, AccessControlGroup } from '@/models/access-c
import { RiAlertFill, RiCloseCircleFill, RiLockLine, RiOrganizationChart } from '@remixicon/react'
import { useCallback, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { AccessMode } from '@/models/access-control'
import { useAppWhiteListSubjects } from '@/service/access-control'
import useAccessControlStore from '../../../../context/access-control-store'
-import { Avatar } from '../../base/avatar'
import Loading from '../../base/loading'
import Tooltip from '../../base/tooltip'
import AddMemberOrGroupDialog from './add-member-or-group-pop'
diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/chat-item.spec.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/chat-item.spec.tsx
index 80bb26a052..61eb8f2ae8 100644
--- a/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/chat-item.spec.tsx
+++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/__tests__/chat-item.spec.tsx
@@ -90,7 +90,7 @@ vi.mock('@/app/components/base/chat/chat', () => ({
},
}))
-vi.mock('@/app/components/base/avatar', () => ({
+vi.mock('@/app/components/base/ui/avatar', () => ({
Avatar: ({ name }: { name: string }) =>
{name}
,
}))
diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx
index e957fc24c4..56345890ff 100644
--- a/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx
+++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx
@@ -7,11 +7,11 @@ import {
useCallback,
useMemo,
} from 'react'
-import { Avatar } from '@/app/components/base/avatar'
import Chat from '@/app/components/base/chat/chat'
import { useChat } from '@/app/components/base/chat/chat/hooks'
import { getLastAnswer } from '@/app/components/base/chat/utils'
import { useFeatures } from '@/app/components/base/features/hooks'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useAppContext } from '@/context/app-context'
import { useDebugConfigurationContext } from '@/context/debug-configuration'
diff --git a/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx b/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx
index 84ff8b5ede..a9f9f1116b 100644
--- a/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx
+++ b/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx
@@ -3,11 +3,11 @@ import type { ChatConfig, ChatItem, OnSend } from '@/app/components/base/chat/ty
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { memo, useCallback, useImperativeHandle, useMemo } from 'react'
import { useStore as useAppStore } from '@/app/components/app/store'
-import { Avatar } from '@/app/components/base/avatar'
import Chat from '@/app/components/base/chat/chat'
import { useChat } from '@/app/components/base/chat/chat/hooks'
import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/chat/utils'
import { useFeatures } from '@/app/components/base/features/hooks'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useAppContext } from '@/context/app-context'
import { useDebugConfigurationContext } from '@/context/debug-configuration'
diff --git a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
index 720355d09f..9c3a7cc8f7 100644
--- a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
+++ b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
@@ -11,6 +11,7 @@ import AppIcon from '@/app/components/base/app-icon'
import InputsForm from '@/app/components/base/chat/chat-with-history/inputs-form'
import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested-questions'
import { Markdown } from '@/app/components/base/markdown'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { InputVarType } from '@/app/components/workflow/types'
import {
AppSourceType,
@@ -23,7 +24,6 @@ import { submitHumanInputForm as submitHumanInputFormService } from '@/service/w
import { TransferMethod } from '@/types/app'
import { cn } from '@/utils/classnames'
import { formatBooleanInputs } from '@/utils/model-config'
-import { Avatar } from '../../avatar'
import Chat from '../chat'
import { useChat } from '../chat/hooks'
import { getLastAnswer, isValidGeneratedAnswer } from '../utils'
diff --git a/web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx b/web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx
index c518a9d078..451f566505 100644
--- a/web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx
+++ b/web/app/components/base/chat/embedded-chatbot/chat-wrapper.tsx
@@ -12,6 +12,7 @@ import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested
import InputsForm from '@/app/components/base/chat/embedded-chatbot/inputs-form'
import LogoAvatar from '@/app/components/base/logo/logo-embedded-chat-avatar'
import { Markdown } from '@/app/components/base/markdown'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { InputVarType } from '@/app/components/workflow/types'
import {
AppSourceType,
@@ -23,7 +24,6 @@ import {
import { submitHumanInputForm as submitHumanInputFormService } from '@/service/workflow'
import { TransferMethod } from '@/types/app'
import { cn } from '@/utils/classnames'
-import { Avatar } from '../../avatar'
import Chat from '../chat'
import { useChat } from '../chat/hooks'
import { getLastAnswer, isValidGeneratedAnswer } from '../utils'
diff --git a/web/app/components/base/avatar/__tests__/index.spec.tsx b/web/app/components/base/ui/avatar/__tests__/index.spec.tsx
similarity index 99%
rename from web/app/components/base/avatar/__tests__/index.spec.tsx
rename to web/app/components/base/ui/avatar/__tests__/index.spec.tsx
index 69c56ac993..8be3f8bf0f 100644
--- a/web/app/components/base/avatar/__tests__/index.spec.tsx
+++ b/web/app/components/base/ui/avatar/__tests__/index.spec.tsx
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react'
-import { Avatar } from '../index'
+import { Avatar } from '..'
describe('Avatar', () => {
describe('Rendering', () => {
diff --git a/web/app/components/base/avatar/index.stories.tsx b/web/app/components/base/ui/avatar/index.stories.tsx
similarity index 100%
rename from web/app/components/base/avatar/index.stories.tsx
rename to web/app/components/base/ui/avatar/index.stories.tsx
diff --git a/web/app/components/base/avatar/index.tsx b/web/app/components/base/ui/avatar/index.tsx
similarity index 92%
rename from web/app/components/base/avatar/index.tsx
rename to web/app/components/base/ui/avatar/index.tsx
index 885022dded..0842a1734d 100644
--- a/web/app/components/base/avatar/index.tsx
+++ b/web/app/components/base/ui/avatar/index.tsx
@@ -36,7 +36,7 @@ function AvatarRoot({
return (
)
diff --git a/web/app/components/datasets/settings/permission-selector/index.tsx b/web/app/components/datasets/settings/permission-selector/index.tsx
index a83beffbb4..cdf13e4b32 100644
--- a/web/app/components/datasets/settings/permission-selector/index.tsx
+++ b/web/app/components/datasets/settings/permission-selector/index.tsx
@@ -4,13 +4,13 @@ import { useDebounceFn } from 'ahooks'
import * as React from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
import Input from '@/app/components/base/input'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
import { DatasetPermission } from '@/models/datasets'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/header/account-dropdown/index.tsx b/web/app/components/header/account-dropdown/index.tsx
index f5b0352a40..442554615b 100644
--- a/web/app/components/header/account-dropdown/index.tsx
+++ b/web/app/components/header/account-dropdown/index.tsx
@@ -4,9 +4,9 @@ import type { MouseEventHandler, ReactNode } from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { resetUser } from '@/app/components/base/amplitude/utils'
-import { Avatar } from '@/app/components/base/avatar'
import PremiumBadge from '@/app/components/base/premium-badge'
import ThemeSwitcher from '@/app/components/base/theme-switcher'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLinkItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/app/components/base/ui/dropdown-menu'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { IS_CLOUD_EDITION } from '@/config'
diff --git a/web/app/components/header/account-setting/members-page/index.tsx b/web/app/components/header/account-setting/members-page/index.tsx
index 875ffba3e0..6ac9ee5d2d 100644
--- a/web/app/components/header/account-setting/members-page/index.tsx
+++ b/web/app/components/header/account-setting/members-page/index.tsx
@@ -2,7 +2,7 @@
import type { InvitationResult } from '@/models/common'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip'
import { NUM_INFINITE } from '@/app/components/billing/config'
import { Plan } from '@/app/components/billing/type'
diff --git a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/member-selector.tsx b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/member-selector.tsx
index a6617ac4d2..59e69b92e2 100644
--- a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/member-selector.tsx
+++ b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/member-selector.tsx
@@ -3,9 +3,9 @@ import type { FC } from 'react'
import * as React from 'react'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
import Input from '@/app/components/base/input'
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { useMembers } from '@/service/use-common'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx
index a655ccd6bb..465e2b7d40 100644
--- a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx
+++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx
@@ -3,7 +3,7 @@ import type { Member } from '@/models/common'
import { RiCloseCircleFill, RiErrorWarningFill } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { cn } from '@/utils/classnames'
type Props = {
diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/member-list.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/member-list.tsx
index 471f4f7c5c..2a7b9b0707 100644
--- a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/member-list.tsx
+++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/member-list.tsx
@@ -4,8 +4,8 @@ import type { Recipient } from '@/app/components/workflow/nodes/human-input/type
import type { Member } from '@/models/common'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
import Input from '@/app/components/base/input'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { cn } from '@/utils/classnames'
const i18nPrefix = 'nodes.humanInput'
diff --git a/web/app/education-apply/user-info.tsx b/web/app/education-apply/user-info.tsx
index 13f9b8521a..6e51d1adb8 100644
--- a/web/app/education-apply/user-info.tsx
+++ b/web/app/education-apply/user-info.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next'
-import { Avatar } from '@/app/components/base/avatar'
import Button from '@/app/components/base/button'
import { Triangle } from '@/app/components/base/icons/src/public/education'
+import { Avatar } from '@/app/components/base/ui/avatar'
import { useAppContext } from '@/context/app-context'
import { useRouter } from '@/next/navigation'
import { useLogout } from '@/service/use-common'
diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json
index 846e9f11ec..568f113499 100644
--- a/web/eslint-suppressions.json
+++ b/web/eslint-suppressions.json
@@ -1560,11 +1560,6 @@
"count": 1
}
},
- "app/components/base/avatar/index.tsx": {
- "tailwindcss/enforce-consistent-class-order": {
- "count": 2
- }
- },
"app/components/base/badge.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 2
diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs
index cbae7af77f..0fe2a56c03 100644
--- a/web/eslint.config.mjs
+++ b/web/eslint.config.mjs
@@ -171,7 +171,7 @@ export default antfu(
},
{
name: 'dify/base-ui-primitives',
- files: ['app/components/base/ui/**/*.tsx', 'app/components/base/avatar/**/*.tsx'],
+ files: ['app/components/base/ui/**/*.tsx'],
rules: {
'react-refresh/only-export-components': 'off',
},