{item.title}
+{item.meta}
+{description}
+A simple vertical panel with the default scrollbar skin and no business-specific overrides.
+{item.meta}
+The scrollbar is still the shared base/ui primitive, while the pane adds sticky structure and a viewport mask.
+This pane keeps the default track behavior and only changes the surface layout around it.
+{description}
+Current design delivery defines the horizontal scrollbar body, but not a horizontal edge hint.
+Both axes overflow here so the corner becomes visible as a deliberate seam between the two tracks.
++ Wide-and-tall content to force both scrollbars and show the corner treatment clearly. +
++ Web Apps +
+ + {webAppsRows.length} + ++ This pane is intentionally long so the default vertical scrollbar sits over a larger editorial surface. +
+{t('sidebar.webApps', { ns: 'explore' })}
} -{t('sidebar.webApps', { ns: 'explore' })}
} + {shouldUseExpandedScrollArea + ? ( +{t(`${i18nPrefix}.readyToInstall`, { ns: 'plugin' })}
+
{t('difyVersionNotCompatible', { ns: 'plugin', minimalDifyVersion: payload.meta.minimum_dify_version })}
)} diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx index 275d4ca47b..8a4e0bd82a 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -5,11 +5,11 @@ import { RiLoader2Line } from '@remixicon/react' import * as React from 'react' import { useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { gte } from 'semver' import Button from '@/app/components/base/button' import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' import { useAppContext } from '@/context/app-context' import { useInstallPackageFromMarketPlace, usePluginDeclarationFromMarketPlace, usePluginTaskList, useUpdatePackageFromMarketPlace } from '@/service/use-plugins' +import { isEqualOrLaterThanVersion } from '@/utils/semver' import Card from '../../../card' // import { RiInformation2Line } from '@remixicon/react' import { TaskStatus } from '../../../types' @@ -126,17 +126,17 @@ const Installed: FC{t(`${i18nPrefix}.readyToInstall`, { ns: 'plugin' })}
{!isDifyVersionCompatible && ( -+
{t('difyVersionNotCompatible', { ns: 'plugin', minimalDifyVersion: pluginDeclaration?.manifest.meta.minimum_dify_version })}
)} diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx index 5497786794..4dd604a03e 100644 --- a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx @@ -76,16 +76,16 @@ afterAll(() => { // Mock portal components for controlled positioning in tests // Use React context to properly scope open state per portal instance (for nested portals) -const _PortalOpenContext = React.createContext(false) - vi.mock('@/app/components/base/portal-to-follow-elem', () => { // Context reference shared across mock components let sharedContext: React.Context