From 3e5bbdb30bbe9764de80dff90380a46a97ff75fa Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Wed, 20 May 2026 09:04:02 +0800 Subject: [PATCH] tweaks --- .../deployments/create-guide/index.tsx | 841 ++++++++++-------- 1 file changed, 451 insertions(+), 390 deletions(-) diff --git a/web/features/deployments/create-guide/index.tsx b/web/features/deployments/create-guide/index.tsx index 4a8e575e93..7dd7a87dbf 100644 --- a/web/features/deployments/create-guide/index.tsx +++ b/web/features/deployments/create-guide/index.tsx @@ -6,7 +6,7 @@ import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { toast } from '@langgenius/dify-ui/toast' import { keepPreviousData, useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query' -import { useLayoutEffect, useRef, useState } from 'react' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import AppIcon from '@/app/components/base/app-icon' import Input from '@/app/components/base/input' @@ -19,7 +19,7 @@ import { SOURCE_APPS_PAGE_SIZE } from '../data' import { environmentMode, environmentName } from '../environment' type GuideMethod = 'bindApp' | 'importDsl' -type GuideStep = 'method' | 'source' | 'release' | 'target' | 'review' | 'done' +type GuideStep = 'method' | 'source' | 'release' | 'target' | 'done' type EnvironmentOption = AppDeployEnvironment & { id: string } type BindingSelections = Record @@ -28,13 +28,9 @@ type BindingSelectOption = { label: string } -const guideSteps: GuideStep[] = ['method', 'source', 'release', 'target', 'review'] const sourceAppSkeletonKeys = ['first-source-app', 'second-source-app', 'third-source-app'] const targetEnvironmentSkeletonKeys = ['first-target-environment', 'second-target-environment'] const targetBindingSkeletonKeys = ['first-target-binding', 'second-target-binding'] -const maxGuideCardHeight = 640 -const minGuideCardHeight = 320 -const guideCardVerticalMargin = 144 const dslPreviewDeployTargetEnvironments: EnvironmentOption[] = [ { @@ -152,9 +148,9 @@ function StepShell({ title, description, children }: { children: React.ReactNode }) { return ( -
-
-

{title}

+
+
+

{title}

{description}

{children} @@ -162,41 +158,6 @@ function StepShell({ title, description, children }: { ) } -function StepList({ activeStep }: { - activeStep: GuideStep -}) { - const { t } = useTranslation('deployments') - const activeIndex = activeStep === 'done' ? guideSteps.length : guideSteps.indexOf(activeStep) - - return ( -
    - {guideSteps.map((step, index) => { - const isActive = step === activeStep - const isDone = activeIndex > index || activeStep === 'done' - return ( -
  1. -
  2. - ) - })} -
- ) -} - function MethodCard({ icon, title, description, badge, selected, onClick }: { icon: string title: string @@ -210,33 +171,29 @@ function MethodCard({ icon, title, description, badge, selected, onClick }: { type="button" onClick={onClick} className={cn( - 'group flex min-h-16 min-w-0 items-center gap-3 rounded-lg border p-3 text-left transition-colors', - selected - ? 'border-primary-600 bg-primary-50' - : 'border-divider-subtle bg-background-default hover:border-divider-regular hover:bg-background-default-hover', + `relative box-content h-[84px] w-full cursor-pointer rounded-xl border-[0.5px] + border-components-option-card-option-border bg-components-panel-on-panel-item-bg p-3 + text-left shadow-xs hover:shadow-md sm:w-[191px]`, + selected && 'shadow-md outline-[1.5px] outline-components-option-card-option-selected-border outline-solid', )} > - + - - - {title} - {badge && ( - - {badge} - - )} - - {description} - - + {title} + {badge && ( + + {badge} + )} - aria-hidden="true" - /> + + + + {description} + + ) } @@ -245,145 +202,107 @@ function GuideCard({ children, actions }: { children: React.ReactNode actions: React.ReactNode }) { - const cardRef = useRef(null) - const scrollerRef = useRef(null) - const contentRef = useRef(null) - const actionsRef = useRef(null) - - useLayoutEffect(() => { - let animationFrame = 0 - let restoreScrollTimeout = 0 - - function restoreScroll() { - if (scrollerRef.current) - scrollerRef.current.style.overflowY = '' - } - - function hideScroll() { - if (scrollerRef.current) - scrollerRef.current.style.overflowY = 'hidden' - } - - function updateHeight() { - const cardElement = cardRef.current - const contentElement = contentRef.current - if (!cardElement || !contentElement) - return - - const actionsElement = actionsRef.current - const measuredHeight = Math.ceil( - contentElement.getBoundingClientRect().height - + (actionsElement?.getBoundingClientRect().height ?? 0) - + 2, - ) - const availableHeight = Math.max( - minGuideCardHeight, - Math.min(maxGuideCardHeight, window.innerHeight - guideCardVerticalMargin), - ) - const nextHeight = Math.min(measuredHeight, availableHeight) - const currentHeight = Math.ceil(cardElement.getBoundingClientRect().height) - if (currentHeight !== nextHeight && scrollerRef.current) { - hideScroll() - window.clearTimeout(restoreScrollTimeout) - restoreScrollTimeout = window.setTimeout(restoreScroll, 240) - } - cardElement.style.height = `${nextHeight}px` - } - - function scheduleHeightUpdate() { - cancelAnimationFrame(animationFrame) - animationFrame = requestAnimationFrame(updateHeight) - } - - function handleTransitionStart(event: TransitionEvent) { - if (event.target === cardRef.current && event.propertyName === 'height') { - hideScroll() - window.clearTimeout(restoreScrollTimeout) - } - } - - function handleTransitionEnd(event: TransitionEvent) { - if (event.target === cardRef.current && event.propertyName === 'height') - restoreScroll() - } - - scheduleHeightUpdate() - - const resizeObserver = new ResizeObserver(scheduleHeightUpdate) - const transitionElement = cardRef.current - if (contentRef.current) - resizeObserver.observe(contentRef.current) - if (actionsRef.current) - resizeObserver.observe(actionsRef.current) - if (transitionElement) - transitionElement.addEventListener('transitionend', handleTransitionEnd) - if (transitionElement) - transitionElement.addEventListener('transitionstart', handleTransitionStart) - if (transitionElement) - transitionElement.addEventListener('transitioncancel', handleTransitionEnd) - window.addEventListener('resize', scheduleHeightUpdate) - - return () => { - cancelAnimationFrame(animationFrame) - window.clearTimeout(restoreScrollTimeout) - resizeObserver.disconnect() - if (transitionElement) { - transitionElement.removeEventListener('transitionend', handleTransitionEnd) - transitionElement.removeEventListener('transitionstart', handleTransitionStart) - transitionElement.removeEventListener('transitioncancel', handleTransitionEnd) - } - window.removeEventListener('resize', scheduleHeightUpdate) - } - }, []) - return ( -
-
-
- {children} -
-
-
- {actions} +
+
+ {children}
+ {actions}
) } -function GuideFrame({ activeStep, children }: { +function GuideFrame({ activeStep, preview, children }: { activeStep: GuideStep + preview: React.ReactNode children: React.ReactNode }) { const { t } = useTranslation('deployments') return ( -
-
-
-
- -