diff --git a/web/__tests__/billing/pricing-modal-flow.test.tsx b/web/__tests__/billing/pricing-modal-flow.test.tsx
index 6b8fb57f83..7326ee3559 100644
--- a/web/__tests__/billing/pricing-modal-flow.test.tsx
+++ b/web/__tests__/billing/pricing-modal-flow.test.tsx
@@ -295,24 +295,7 @@ describe('Pricing Modal Flow', () => {
})
})
- // ─── 6. Close Handling ───────────────────────────────────────────────────
- describe('Close handling', () => {
- it('should call onCancel when pressing ESC key', () => {
- render()
-
- // ahooks useKeyPress listens on document for keydown events
- document.dispatchEvent(new KeyboardEvent('keydown', {
- key: 'Escape',
- code: 'Escape',
- keyCode: 27,
- bubbles: true,
- }))
-
- expect(onCancel).toHaveBeenCalledTimes(1)
- })
- })
-
- // ─── 7. Pricing URL ─────────────────────────────────────────────────────
+ // ─── 6. Pricing URL ─────────────────────────────────────────────────────
describe('Pricing page URL', () => {
it('should render pricing link with correct URL', () => {
render()
diff --git a/web/app/components/billing/pricing/__tests__/footer.spec.tsx b/web/app/components/billing/pricing/__tests__/footer.spec.tsx
index 7ef78180de..762d0ad211 100644
--- a/web/app/components/billing/pricing/__tests__/footer.spec.tsx
+++ b/web/app/components/billing/pricing/__tests__/footer.spec.tsx
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react'
import * as React from 'react'
-import { CategoryEnum } from '..'
import Footer from '../footer'
+import { CategoryEnum } from '../types'
vi.mock('next/link', () => ({
default: ({ children, href, className, target }: { children: React.ReactNode, href: string, className?: string, target?: string }) => (
diff --git a/web/app/components/billing/pricing/__tests__/index.spec.tsx b/web/app/components/billing/pricing/__tests__/index.spec.tsx
index 54813ae0d7..1be2234cf9 100644
--- a/web/app/components/billing/pricing/__tests__/index.spec.tsx
+++ b/web/app/components/billing/pricing/__tests__/index.spec.tsx
@@ -74,15 +74,11 @@ describe('Pricing', () => {
})
describe('Props', () => {
- it('should allow switching categories and handle esc key', () => {
- const handleCancel = vi.fn()
- render()
+ it('should allow switching categories', () => {
+ render()
fireEvent.click(screen.getByText('billing.plansCommon.self'))
expect(screen.queryByRole('switch')).not.toBeInTheDocument()
-
- fireEvent.keyDown(window, { key: 'Escape', keyCode: 27 })
- expect(handleCancel).toHaveBeenCalled()
})
})
diff --git a/web/app/components/billing/pricing/footer.tsx b/web/app/components/billing/pricing/footer.tsx
index 7569ccaa76..6a213eca00 100644
--- a/web/app/components/billing/pricing/footer.tsx
+++ b/web/app/components/billing/pricing/footer.tsx
@@ -1,10 +1,9 @@
-import type { Category } from '.'
-import { RiArrowRightUpLine } from '@remixicon/react'
+import type { Category } from './types'
import Link from 'next/link'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
-import { CategoryEnum } from '.'
+import { CategoryEnum } from './types'
type FooterProps = {
pricingPageURL: string
@@ -34,7 +33,7 @@ const Footer = ({
>
{t('plansCommon.comparePlanAndFeatures', { ns: 'billing' })}
-
+
diff --git a/web/app/components/billing/pricing/header.tsx b/web/app/components/billing/pricing/header.tsx
index b130f23981..e5107e5677 100644
--- a/web/app/components/billing/pricing/header.tsx
+++ b/web/app/components/billing/pricing/header.tsx
@@ -1,6 +1,6 @@
-import { RiCloseLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
+import { DialogDescription, DialogTitle } from '@/app/components/base/ui/dialog'
import Button from '../../base/button'
import DifyLogo from '../../base/logo/dify-logo'
@@ -20,19 +20,19 @@ const Header = ({
-
+
{t('plansCommon.title.plans', { ns: 'billing' })}
-
+
-
+
{t('plansCommon.title.description', { ns: 'billing' })}
-
+
diff --git a/web/app/components/billing/pricing/index.tsx b/web/app/components/billing/pricing/index.tsx
index 2b58158146..21ca7d0a6f 100644
--- a/web/app/components/billing/pricing/index.tsx
+++ b/web/app/components/billing/pricing/index.tsx
@@ -1,9 +1,9 @@
'use client'
import type { FC } from 'react'
-import { useKeyPress } from 'ahooks'
+import type { Category } from './types'
import * as React from 'react'
import { useState } from 'react'
-import { createPortal } from 'react-dom'
+import { Dialog, DialogContent } from '@/app/components/base/ui/dialog'
import { useAppContext } from '@/context/app-context'
import { useGetPricingPageLanguage } from '@/context/i18n'
import { useProviderContext } from '@/context/provider-context'
@@ -13,13 +13,7 @@ import Header from './header'
import PlanSwitcher from './plan-switcher'
import { PlanRange } from './plan-switcher/plan-range-switcher'
import Plans from './plans'
-
-export enum CategoryEnum {
- CLOUD = 'cloud',
- SELF = 'self',
-}
-
-export type Category = CategoryEnum.CLOUD | CategoryEnum.SELF
+import { CategoryEnum } from './types'
type PricingProps = {
onCancel: () => void
@@ -33,42 +27,47 @@ const Pricing: FC = ({
const [planRange, setPlanRange] = React.useState(PlanRange.monthly)
const [currentCategory, setCurrentCategory] = useState(CategoryEnum.CLOUD)
const canPay = isCurrentWorkspaceManager
- useKeyPress(['esc'], onCancel)
const pricingPageLanguage = useGetPricingPageLanguage()
const pricingPageURL = pricingPageLanguage
? `https://dify.ai/${pricingPageLanguage}/pricing#plans-and-features`
: 'https://dify.ai/pricing#plans-and-features'
- return createPortal(
- e.stopPropagation()}
+ return (
+
)
}
export default React.memo(Pricing)
diff --git a/web/app/components/billing/pricing/plan-switcher/__tests__/index.spec.tsx b/web/app/components/billing/pricing/plan-switcher/__tests__/index.spec.tsx
index 51e074e305..e6b8d8430f 100644
--- a/web/app/components/billing/pricing/plan-switcher/__tests__/index.spec.tsx
+++ b/web/app/components/billing/pricing/plan-switcher/__tests__/index.spec.tsx
@@ -1,6 +1,6 @@
import { fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
-import { CategoryEnum } from '../../index'
+import { CategoryEnum } from '../../types'
import PlanSwitcher from '../index'
import { PlanRange } from '../plan-range-switcher'
diff --git a/web/app/components/billing/pricing/plan-switcher/index.tsx b/web/app/components/billing/pricing/plan-switcher/index.tsx
index 60e0bdf8de..be0bd3e2b1 100644
--- a/web/app/components/billing/pricing/plan-switcher/index.tsx
+++ b/web/app/components/billing/pricing/plan-switcher/index.tsx
@@ -1,5 +1,5 @@
import type { FC } from 'react'
-import type { Category } from '../index'
+import type { Category } from '../types'
import type { PlanRange } from './plan-range-switcher'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
diff --git a/web/app/components/billing/pricing/types.ts b/web/app/components/billing/pricing/types.ts
new file mode 100644
index 0000000000..843d98e6f5
--- /dev/null
+++ b/web/app/components/billing/pricing/types.ts
@@ -0,0 +1,6 @@
+export enum CategoryEnum {
+ CLOUD = 'cloud',
+ SELF = 'self',
+}
+
+export type Category = CategoryEnum.CLOUD | CategoryEnum.SELF
diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json
index aa60a9c8ea..5f15dc8ba9 100644
--- a/web/eslint-suppressions.json
+++ b/web/eslint-suppressions.json
@@ -2964,16 +2964,6 @@
"count": 2
}
},
- "app/components/billing/pricing/header.tsx": {
- "tailwindcss/enforce-consistent-class-order": {
- "count": 1
- }
- },
- "app/components/billing/pricing/index.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
"app/components/billing/pricing/plan-switcher/plan-range-switcher.tsx": {
"react-refresh/only-export-components": {
"count": 1