Sfoglia il codice sorgente

Dark Mode: Workflow darkmode style (#11695)

NFish 4 mesi fa
parent
commit
a399502ecd

+ 2 - 2
web/app/components/tools/add-tool-modal/empty.tsx

@@ -6,8 +6,8 @@ const Empty = () => {
   return (
     <div className='flex flex-col items-center'>
       <div className="shrink-0 w-[163px] h-[149px] bg-cover bg-no-repeat bg-[url('~@/app/components/tools/add-tool-modal/empty.png')]"></div>
-      <div className='mb-1 text-[13px] font-medium text-gray-700 leading-[18px]'>{t('tools.addToolModal.emptyTitle')}</div>
-      <div className='text-[13px] text-gray-500 leading-[18px]'>{t('tools.addToolModal.emptyTip')}</div>
+      <div className='mb-1 text-[13px] font-medium text-text-primary leading-[18px]'>{t('tools.addToolModal.emptyTitle')}</div>
+      <div className='text-[13px] text-text-tertiary leading-[18px]'>{t('tools.addToolModal.emptyTip')}</div>
     </div>
   )
 }

+ 8 - 8
web/app/components/workflow/block-selector/all-tools.tsx

@@ -43,23 +43,23 @@ const AllTools = ({
 
     return mergedTools.filter((toolWithProvider) => {
       return isMatchingKeywords(toolWithProvider.name, searchText)
-      || toolWithProvider.tools.some((tool) => {
-        return Object.values(tool.label).some((label) => {
-          return isMatchingKeywords(label, searchText)
+        || toolWithProvider.tools.some((tool) => {
+          return Object.values(tool.label).some((label) => {
+            return isMatchingKeywords(label, searchText)
+          })
         })
-      })
     })
   }, [activeTab, buildInTools, customTools, workflowTools, searchText])
   return (
     <div>
-      <div className='flex items-center px-3 h-8 space-x-1 bg-gray-25 border-b-[0.5px] border-black/[0.08] shadow-xs'>
+      <div className='flex items-center px-3 h-8 space-x-1 bg-background-default-hover border-b-[0.5px] border-divider-subtle shadow-xs'>
         {
           tabs.map(tab => (
             <div
               className={cn(
-                'flex items-center px-2 h-6 rounded-md hover:bg-gray-100 cursor-pointer',
-                'text-xs font-medium text-gray-700',
-                activeTab === tab.key && 'bg-gray-200',
+                'flex items-center px-2 h-6 rounded-md hover:bg-state-base-hover-alt cursor-pointer',
+                'system-xs-medium text-text-tertiary',
+                activeTab === tab.key && 'system-xs-semibold bg-state-base-hover-alt text-text-primary',
               )}
               key={tab.key}
               onClick={() => setActiveTab(tab.key)}

+ 7 - 7
web/app/components/workflow/block-selector/blocks.tsx

@@ -58,7 +58,7 @@ const Blocks = ({
       >
         {
           classification !== '-' && !!list.length && (
-            <div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'>
+            <div className='flex items-start px-3 h-[22px] text-xs font-medium text-text-tertiary'>
               {t(`workflow.tabs.${classification}`)}
             </div>
           )
@@ -68,7 +68,7 @@ const Blocks = ({
             <Tooltip
               key={block.type}
               position='right'
-              popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
+              popupClassName='w-[200px]'
               popupContent={(
                 <div>
                   <BlockIcon
@@ -76,21 +76,21 @@ const Blocks = ({
                     className='mb-2'
                     type={block.type}
                   />
-                  <div className='mb-1 text-sm leading-5 text-gray-900'>{block.title}</div>
-                  <div className='text-xs text-gray-700 leading-[18px]'>{nodesExtraData[block.type].about}</div>
+                  <div className='mb-1 system-md-medium text-text-primary'>{block.title}</div>
+                  <div className='text-text-tertiary system-xs-regular'>{nodesExtraData[block.type].about}</div>
                 </div>
               )}
             >
               <div
                 key={block.type}
-                className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
+                className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-state-base-hover cursor-pointer'
                 onClick={() => onSelect(block.type)}
               >
                 <BlockIcon
                   className='mr-2 shrink-0'
                   type={block.type}
                 />
-                <div className='text-sm text-gray-900'>{block.title}</div>
+                <div className='text-sm text-text-secondary'>{block.title}</div>
               </div>
             </Tooltip>
           ))
@@ -103,7 +103,7 @@ const Blocks = ({
     <div className='p-1'>
       {
         isEmpty && (
-          <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>{t('workflow.tabs.noResult')}</div>
+          <div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>{t('workflow.tabs.noResult')}</div>
         )
       }
       {

+ 2 - 2
web/app/components/workflow/block-selector/index-bar.tsx

@@ -47,9 +47,9 @@ const IndexBar: FC<IndexBarProps> = ({ letters, itemRefs }) => {
       element.scrollIntoView({ behavior: 'smooth' })
   }
   return (
-    <div className="index-bar fixed right-4 top-36 flex flex-col items-center text-xs font-medium text-gray-500">
+    <div className="index-bar fixed right-4 top-36 flex flex-col items-center text-xs font-medium text-text-quaternary">
       {letters.map(letter => (
-        <div className="hover:text-gray-900 cursor-pointer" key={letter} onClick={() => handleIndexClick(letter)}>
+        <div className="hover:text-text-secondary cursor-pointer" key={letter} onClick={() => handleIndexClick(letter)}>
           {letter}
         </div>
       ))}

+ 7 - 4
web/app/components/workflow/block-selector/index.tsx

@@ -25,6 +25,7 @@ import Input from '@/app/components/base/input'
 import {
   Plus02,
 } from '@/app/components/base/icons/src/vender/line/general'
+import classNames from '@/utils/classnames'
 
 type NodeSelectorProps = {
   open?: boolean
@@ -114,19 +115,21 @@ const NodeSelector: FC<NodeSelectorProps> = ({
               <div
                 className={`
                   flex items-center justify-center 
-                  w-4 h-4 rounded-full bg-primary-600 cursor-pointer z-10
+                  w-4 h-4 rounded-full bg-components-button-primary-bg text-text-primary-on-surface hover:bg-components-button-primary-bg-hover cursor-pointer z-10
                   ${triggerClassName?.(open)}
                 `}
                 style={triggerStyle}
               >
-                <Plus02 className='w-2.5 h-2.5 text-white' />
+                <Plus02 className='w-2.5 h-2.5' />
               </div>
             )
         }
       </PortalToFollowElemTrigger>
       <PortalToFollowElemContent className='z-[1000]'>
-        <div className={`rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${popupClassName}`}>
-          <div className='px-2 pt-2' onClick={e => e.stopPropagation()}>
+        <div className={
+          classNames(`rounded-lg border-[0.5px] backdrop-blur-[5px]
+          border-components-panel-border bg-components-panel-bg-blur shadow-lg`, popupClassName)}>
+          <div className='p-2 pb-1' onClick={e => e.stopPropagation()}>
             <Input
               showLeftIcon
               showClearIcon

+ 4 - 4
web/app/components/workflow/block-selector/tabs.tsx

@@ -30,16 +30,16 @@ const Tabs: FC<TabsProps> = ({
     <div onClick={e => e.stopPropagation()}>
       {
         !noBlocks && (
-          <div className='flex items-center px-3 border-b-[0.5px] border-b-black/5'>
+          <div className='flex items-center px-3 border-b-[0.5px] border-divider-subtle'>
             {
               tabs.map(tab => (
                 <div
                   key={tab.key}
                   className={cn(
-                    'relative mr-4 h-[34px] text-[13px] leading-[34px] font-medium cursor-pointer',
+                    'relative mr-4 pt-1 pb-2 system-sm-medium cursor-pointer',
                     activeTab === tab.key
-                      ? 'text-gray-700 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-primary-600'
-                      : 'text-gray-500',
+                      ? 'text-text-primary after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-util-colors-blue-brand-blue-brand-600'
+                      : 'text-text-tertiary',
                   )}
                   onClick={() => onActiveTabChange(tab.key)}
                 >

+ 6 - 6
web/app/components/workflow/block-selector/tools.tsx

@@ -45,7 +45,7 @@ const Blocks = ({
             <Tooltip
               key={tool.name}
               position='right'
-              popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
+              popupClassName='w-[200px]'
               popupContent={(
                 <div>
                   <BlockIcon
@@ -54,13 +54,13 @@ const Blocks = ({
                     type={BlockEnum.Tool}
                     toolIcon={toolWithProvider.icon}
                   />
-                  <div className='mb-1 text-sm leading-5 text-gray-900'>{tool.label[language]}</div>
-                  <div className='text-xs text-gray-700 leading-[18px]'>{tool.description[language]}</div>
+                  <div className='mb-1 system-md-medium text-text-primary'>{tool.label[language]}</div>
+                  <div className='system-xs-regular text-text-tertiary'>{tool.description[language]}</div>
                 </div>
               )}
             >
               <div
-                className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
+                className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-state-base-hover cursor-pointer'
                 onClick={() => onSelect(BlockEnum.Tool, {
                   provider_id: toolWithProvider.id,
                   provider_type: toolWithProvider.type,
@@ -75,7 +75,7 @@ const Blocks = ({
                   type={BlockEnum.Tool}
                   toolIcon={toolWithProvider.icon}
                 />
-                <div className='text-sm text-gray-900 flex-1 min-w-0 truncate'>{tool.label[language]}</div>
+                <div className='text-sm text-text-secondary flex-1 min-w-0 truncate'>{tool.label[language]}</div>
               </div>
             </Tooltip>
           ))
@@ -100,7 +100,7 @@ const Blocks = ({
     <div className='p-1 max-w-[320px] max-h-[464px] overflow-y-auto'>
       {
         !tools.length && !showWorkflowEmpty && (
-          <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>{t('workflow.tabs.noResult')}</div>
+          <div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>{t('workflow.tabs.noResult')}</div>
         )
       }
       {!tools.length && showWorkflowEmpty && (

+ 1 - 1
web/app/components/workflow/header/editing-title.tsx

@@ -13,7 +13,7 @@ const EditingTitle = () => {
   const isSyncingWorkflowDraft = useStore(s => s.isSyncingWorkflowDraft)
 
   return (
-    <div className='flex items-center h-[18px] text-xs text-gray-500'>
+    <div className='flex items-center h-[18px] system-xs-regular text-text-tertiary'>
       {
         !!draftUpdatedAt && (
           <>

+ 8 - 12
web/app/components/workflow/header/index.tsx

@@ -27,6 +27,7 @@ import {
 } from '../hooks'
 import AppPublisher from '../../app/app-publisher'
 import { ToastContext } from '../../base/toast'
+import Divider from '../../base/divider'
 import RunAndHistory from './run-and-history'
 import EditingTitle from './editing-title'
 import RunningTitle from './running-title'
@@ -144,15 +145,12 @@ const Header: FC = () => {
 
   return (
     <div
-      className='absolute top-0 left-0 z-10 flex items-center justify-between w-full px-3 h-14'
-      style={{
-        background: 'linear-gradient(180deg, #F9FAFB 0%, rgba(249, 250, 251, 0.00) 100%)',
-      }}
+      className='absolute top-0 left-0 z-10 flex items-center justify-between w-full px-3 h-14 bg-mask-top2bottom-gray-50-to-transparent'
     >
       <div>
         {
           appSidebarExpand === 'collapse' && (
-            <div className='text-xs font-medium text-gray-700'>{appDetail?.name}</div>
+            <div className='system-xs-regular text-text-tertiary'>{appDetail?.name}</div>
           )
         }
         {
@@ -171,7 +169,7 @@ const Header: FC = () => {
             {/* <GlobalVariableButton disabled={nodesReadOnly} /> */}
             {isChatMode && <ChatVariableButton disabled={nodesReadOnly} />}
             <EnvButton disabled={nodesReadOnly} />
-            <div className='w-[1px] h-3.5 bg-gray-200'></div>
+            <Divider type='vertical' className='h-3.5 mx-auto' />
             <RunAndHistory />
             <Button className='text-components-button-secondary-text' onClick={handleShowFeatures}>
               <RiApps2AddLine className='w-4 h-4 mr-1 text-components-button-secondary-text' />
@@ -196,12 +194,11 @@ const Header: FC = () => {
       }
       {
         viewHistory && (
-          <div className='flex items-center'>
+          <div className='flex items-center space-x-2'>
             <ViewHistory withText />
-            <div className='mx-2 w-[1px] h-3.5 bg-gray-200'></div>
+            <Divider type='vertical' className='h-3.5 mx-auto' />
             <Button
               variant='primary'
-              className='mr-2'
               onClick={handleGoBackToEdit}
             >
               <ArrowNarrowLeft className='w-4 h-4 mr-1' />
@@ -212,14 +209,13 @@ const Header: FC = () => {
       }
       {
         restoring && (
-          <div className='flex items-center'>
+          <div className='flex items-center space-x-2'>
             <Button className='text-components-button-secondary-text' onClick={handleShowFeatures}>
               <RiApps2AddLine className='w-4 h-4 mr-1 text-components-button-secondary-text' />
               {t('workflow.common.features')}
             </Button>
-            <div className='mx-2 w-[1px] h-3.5 bg-gray-200'></div>
+            <Divider type='vertical' className='h-3.5 mx-auto' />
             <Button
-              className='mr-2'
               onClick={handleCancelRestore}
             >
               {t('common.operation.cancel')}

+ 15 - 14
web/app/components/workflow/header/undo-redo.tsx

@@ -7,8 +7,10 @@ import {
 } from '@remixicon/react'
 import TipPopup from '../operator/tip-popup'
 import { useWorkflowHistoryStore } from '../workflow-history-store'
+import Divider from '../../base/divider'
 import { useNodesReadOnly } from '@/app/components/workflow/hooks'
 import ViewWorkflowHistory from '@/app/components/workflow/header/view-workflow-history'
+import classNames from '@/utils/classnames'
 
 export type UndoRedoProps = { handleUndo: () => void; handleRedo: () => void }
 const UndoRedo: FC<UndoRedoProps> = ({ handleUndo, handleRedo }) => {
@@ -29,36 +31,35 @@ const UndoRedo: FC<UndoRedoProps> = ({ handleUndo, handleRedo }) => {
   const { nodesReadOnly } = useNodesReadOnly()
 
   return (
-    <div className='flex items-center p-0.5 rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500'>
+    <div className='flex items-center space-x-0.5 p-0.5 backdrop-blur-[5px] rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg shadow-lg'>
       <TipPopup title={t('workflow.common.undo')!} shortcuts={['ctrl', 'z']}>
         <div
           data-tooltip-id='workflow.undo'
-          className={`
-        flex items-center px-1.5 w-8 h-8 rounded-md text-[13px] font-medium 
-        hover:bg-black/5 hover:text-gray-700 cursor-pointer select-none
-        ${(nodesReadOnly || buttonsDisabled.undo) && 'hover:bg-transparent opacity-50 !cursor-not-allowed'}
-      `}
+          className={
+            classNames('flex items-center px-1.5 w-8 h-8 rounded-md system-sm-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer select-none',
+              (nodesReadOnly || buttonsDisabled.undo)
+              && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed')}
           onClick={() => !nodesReadOnly && !buttonsDisabled.undo && handleUndo()}
         >
           <RiArrowGoBackLine className='h-4 w-4' />
         </div>
-      </TipPopup>
+      </TipPopup >
       <TipPopup title={t('workflow.common.redo')!} shortcuts={['ctrl', 'y']}>
         <div
           data-tooltip-id='workflow.redo'
-          className={`
-        flex items-center px-1.5 w-8 h-8 rounded-md text-[13px] font-medium 
-        hover:bg-black/5 hover:text-gray-700 cursor-pointer select-none
-        ${(nodesReadOnly || buttonsDisabled.redo) && 'hover:bg-transparent opacity-50 !cursor-not-allowed'}
-      `}
+          className={
+            classNames('flex items-center px-1.5 w-8 h-8 rounded-md system-sm-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer select-none',
+              (nodesReadOnly || buttonsDisabled.redo)
+              && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed',
+            )}
           onClick={() => !nodesReadOnly && !buttonsDisabled.redo && handleRedo()}
         >
           <RiArrowGoForwardFill className='h-4 w-4' />
         </div>
       </TipPopup>
-      <div className="mx-[3px] w-[1px] h-3.5 bg-gray-200"></div>
+      <Divider type='vertical' className="h-3.5 mx-0.5" />
       <ViewWorkflowHistory />
-    </div>
+    </div >
   )
 }
 

+ 31 - 31
web/app/components/workflow/header/view-workflow-history.tsx

@@ -17,6 +17,7 @@ import {
 } from '../hooks'
 import TipPopup from '../operator/tip-popup'
 import type { WorkflowHistoryState } from '../workflow-history-store'
+import Divider from '../../base/divider'
 import cn from '@/utils/classnames'
 import {
   PortalToFollowElem,
@@ -24,6 +25,7 @@ import {
   PortalToFollowElemTrigger,
 } from '@/app/components/base/portal-to-follow-elem'
 import { useStore as useAppStore } from '@/app/components/app/store'
+import classNames from '@/utils/classnames'
 
 type ChangeHistoryEntry = {
   label: string
@@ -47,7 +49,7 @@ const ViewWorkflowHistory = () => {
     setCurrentLogItem: state.setCurrentLogItem,
     setShowMessageLogModal: state.setShowMessageLogModal,
   })))
-  const reactflowStore = useStoreApi()
+  const reactFlowStore = useStoreApi()
   const { store, getHistoryLabel } = useWorkflowHistory()
 
   const { pastStates, futureStates, undo, redo, clear } = store.temporal.getState()
@@ -59,7 +61,7 @@ const ViewWorkflowHistory = () => {
   }, [clear])
 
   const handleSetState = useCallback(({ index }: ChangeHistoryEntry) => {
-    const { setEdges, setNodes } = reactflowStore.getState()
+    const { setEdges, setNodes } = reactFlowStore.getState()
     const diff = currentHistoryStateIndex + index
     if (diff === 0)
       return
@@ -75,7 +77,7 @@ const ViewWorkflowHistory = () => {
 
     setEdges(edges)
     setNodes(nodes)
-  }, [currentHistoryStateIndex, reactflowStore, redo, store, undo])
+  }, [currentHistoryStateIndex, reactFlowStore, redo, store, undo])
 
   const calculateStepLabel = useCallback((index: number) => {
     if (!index)
@@ -83,8 +85,7 @@ const ViewWorkflowHistory = () => {
 
     const count = index < 0 ? index * -1 : index
     return `${index > 0 ? t('workflow.changeHistory.stepForward', { count }) : t('workflow.changeHistory.stepBackward', { count })}`
-  }
-  , [t])
+  }, [t])
 
   const calculateChangeList: ChangeHistoryList = useMemo(() => {
     const filterList = (list: any, startIndex = 0, reverse = false) => list.map((state: Partial<WorkflowHistoryState>, index: number) => {
@@ -125,10 +126,11 @@ const ViewWorkflowHistory = () => {
             title={t('workflow.changeHistory.title')}
           >
             <div
-              className={`
-                flex items-center justify-center w-8 h-8 rounded-md hover:bg-black/5 cursor-pointer
-                ${open && 'bg-primary-50'} ${nodesReadOnly && 'bg-primary-50 opacity-50 !cursor-not-allowed'}
-              `}
+              className={
+                classNames('flex items-center justify-center w-8 h-8 rounded-md text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer',
+                  open && 'bg-state-accent-active text-text-accent',
+                  nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled',
+                )}
               onClick={() => {
                 if (nodesReadOnly)
                   return
@@ -136,16 +138,16 @@ const ViewWorkflowHistory = () => {
                 setShowMessageLogModal(false)
               }}
             >
-              <RiHistoryLine className={`w-4 h-4 hover:bg-black/5 hover:text-gray-700 ${open ? 'text-primary-600' : 'text-gray-500'}`} />
+              <RiHistoryLine className='w-4 h-4' />
             </div>
           </TipPopup>
         </PortalToFollowElemTrigger>
         <PortalToFollowElemContent className='z-[12]'>
           <div
-            className='flex flex-col ml-2 min-w-[240px] max-w-[360px] bg-white border-[0.5px] border-gray-200 shadow-xl rounded-xl overflow-y-auto'
+            className='flex flex-col ml-2 min-w-[240px] max-w-[360px] bg-components-panel-bg-blur backdrop-blur-[5px] border-[0.5px] border-components-panel-border shadow-xl rounded-xl overflow-y-auto'
           >
-            <div className='sticky top-0 bg-white flex items-center justify-between px-4 pt-3 text-base font-semibold text-gray-900'>
-              <div className='grow'>{t('workflow.changeHistory.title')}</div>
+            <div className='sticky top-0 flex items-center justify-between px-4 pt-3'>
+              <div className='grow text-text-secondary system-mg-regular'>{t('workflow.changeHistory.title')}</div>
               <div
                 className='shrink-0 flex items-center justify-center w-6 h-6 cursor-pointer'
                 onClick={() => {
@@ -154,7 +156,7 @@ const ViewWorkflowHistory = () => {
                   setOpen(false)
                 }}
               >
-                <RiCloseLine className='w-4 h-4 text-gray-500' />
+                <RiCloseLine className='w-4 h-4 text-text-secondary' />
               </div>
             </div>
             {
@@ -168,8 +170,8 @@ const ViewWorkflowHistory = () => {
                   {
                     !calculateChangeList.statesCount && (
                       <div className='py-12'>
-                        <RiHistoryLine className='mx-auto mb-2 w-8 h-8 text-gray-300' />
-                        <div className='text-center text-[13px] text-gray-400'>
+                        <RiHistoryLine className='mx-auto mb-2 w-8 h-8 text-text-tertiary' />
+                        <div className='text-center text-[13px] text-text-tertiary'>
                           {t('workflow.changeHistory.placeholder')}
                         </div>
                       </div>
@@ -181,8 +183,8 @@ const ViewWorkflowHistory = () => {
                         <div
                           key={item?.index}
                           className={cn(
-                            'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-primary-50 cursor-pointer',
-                            item?.index === currentHistoryStateIndex && 'bg-primary-50',
+                            'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-state-base-hover text-text-secondary cursor-pointer',
+                            item?.index === currentHistoryStateIndex && 'bg-state-base-hover',
                           )}
                           onClick={() => {
                             handleSetState(item)
@@ -192,8 +194,7 @@ const ViewWorkflowHistory = () => {
                           <div>
                             <div
                               className={cn(
-                                'flex items-center text-[13px] font-medium leading-[18px]',
-                                item?.index === currentHistoryStateIndex && 'text-primary-600',
+                                'flex items-center text-[13px] font-medium leading-[18px] text-text-secondary',
                               )}
                             >
                               {item?.label || t('workflow.changeHistory.sessionStart')} ({calculateStepLabel(item?.index)}{item?.index === currentHistoryStateIndex && t('workflow.changeHistory.currentState')})
@@ -207,8 +208,8 @@ const ViewWorkflowHistory = () => {
                         <div
                           key={item?.index}
                           className={cn(
-                            'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-primary-50 cursor-pointer',
-                            item?.index === calculateChangeList.statesCount - 1 && 'bg-primary-50',
+                            'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-state-base-hover cursor-pointer',
+                            item?.index === calculateChangeList.statesCount - 1 && 'bg-state-base-hover',
                           )}
                           onClick={() => {
                             handleSetState(item)
@@ -218,8 +219,7 @@ const ViewWorkflowHistory = () => {
                           <div>
                             <div
                               className={cn(
-                                'flex items-center text-[13px] font-medium leading-[18px]',
-                                item?.index === calculateChangeList.statesCount - 1 && 'text-primary-600',
+                                'flex items-center text-[13px] font-medium leading-[18px] text-text-secondary',
                               )}
                             >
                               {item?.label || t('workflow.changeHistory.sessionStart')} ({calculateStepLabel(item?.index)})
@@ -234,12 +234,12 @@ const ViewWorkflowHistory = () => {
             }
             {
               !!calculateChangeList.statesCount && (
-                <>
-                  <div className="h-[1px] bg-gray-100" />
+                <div className='px-0.5'>
+                  <Divider className='m-0' />
                   <div
                     className={cn(
-                      'flex my-0.5 px-2 py-[7px] rounded-lg cursor-pointer',
-                      'hover:bg-red-50 hover:text-red-600',
+                      'flex my-0.5 px-2 py-[7px] rounded-lg text-text-secondary cursor-pointer',
+                      'hover:bg-state-base-hover',
                     )}
                     onClick={() => {
                       handleClearHistory()
@@ -256,12 +256,12 @@ const ViewWorkflowHistory = () => {
                       </div>
                     </div>
                   </div>
-                </>
+                </div>
               )
             }
-            <div className="px-3 w-[240px] py-2 text-xs text-gray-500" >
+            <div className="px-3 w-[240px] py-2 text-xs text-text-tertiary" >
               <div className="flex items-center mb-1 h-[22px] font-medium uppercase">{t('workflow.changeHistory.hint')}</div>
-              <div className="mb-1 text-gray-700 leading-[18px]">{t('workflow.changeHistory.hintText')}</div>
+              <div className="mb-1 text-text-tertiary leading-[18px]">{t('workflow.changeHistory.hintText')}</div>
             </div>
           </div>
         </PortalToFollowElemContent>

+ 5 - 4
web/app/components/workflow/index.tsx

@@ -179,7 +179,7 @@ const Workflow: FC<WorkflowProps> = memo(({
     return () => {
       handleSyncWorkflowDraft(true, true)
     }
-  // eslint-disable-next-line react-hooks/exhaustive-deps
+    // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [])
 
   const { handleRefreshWorkflowDraft } = useWorkflowUpdate()
@@ -280,7 +280,7 @@ const Workflow: FC<WorkflowProps> = memo(({
     <div
       id='workflow-container'
       className={`
-        relative w-full min-w-[960px] h-full bg-[#F0F2F7]
+        relative w-full min-w-[960px] h-full 
         ${workflowReadOnly && 'workflow-panel-animation'}
         ${nodeAnimation && 'workflow-node-animation'}
       `}
@@ -371,7 +371,8 @@ const Workflow: FC<WorkflowProps> = memo(({
         <Background
           gap={[14, 14]}
           size={2}
-          color='#E4E5E7'
+          className="bg-workflow-canvas-workflow-bg"
+          color='var(--color-workflow-canvas-workflow-dot-color)'
         />
       </ReactFlow>
     </div>
@@ -401,7 +402,7 @@ const WorkflowWrap = memo(() => {
 
   if (!data || isLoading) {
     return (
-      <div className='flex justify-center items-center relative w-full h-full bg-[#F0F2F7]'>
+      <div className='flex justify-center items-center relative w-full h-full'>
         <Loading />
       </div>
     )

+ 3 - 3
web/app/components/workflow/operator/add-block.tsx

@@ -78,9 +78,9 @@ const AddBlock = ({
         title={t('workflow.common.addBlock')}
       >
         <div className={cn(
-          'flex items-center justify-center w-8 h-8 rounded-lg hover:bg-black/5 hover:text-gray-700 cursor-pointer',
-          `${nodesReadOnly && '!cursor-not-allowed opacity-50'}`,
-          open && '!bg-black/5',
+          'flex items-center justify-center w-8 h-8 rounded-lg text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer',
+          `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
+          open && 'bg-state-accent-active text-text-accent',
         )}>
           <RiAddCircleFill className='w-4 h-4' />
         </div>

+ 12 - 11
web/app/components/workflow/operator/control.tsx

@@ -18,6 +18,7 @@ import {
   ControlMode,
 } from '../types'
 import { useStore } from '../store'
+import Divider from '../../base/divider'
 import AddBlock from './add-block'
 import TipPopup from './tip-popup'
 import { useOperator } from './hooks'
@@ -43,26 +44,26 @@ const Control = () => {
   }
 
   return (
-    <div className='flex items-center p-0.5 rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500'>
+    <div className='flex items-center p-0.5 rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg shadow-lg text-text-tertiary'>
       <AddBlock />
       <TipPopup title={t('workflow.nodes.note.addNote')}>
         <div
           className={cn(
-            'flex items-center justify-center ml-[1px] w-8 h-8 rounded-lg hover:bg-black/5 hover:text-gray-700 cursor-pointer',
-            `${nodesReadOnly && '!cursor-not-allowed opacity-50'}`,
+            'flex items-center justify-center ml-[1px] w-8 h-8 rounded-lg hover:bg-state-base-hover hover:text-text-secondary cursor-pointer',
+            `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
           )}
           onClick={addNote}
         >
           <RiStickyNoteAddLine className='w-4 h-4' />
         </div>
       </TipPopup>
-      <div className='mx-[3px] w-[1px] h-3.5 bg-gray-200'></div>
+      <Divider type='vertical' className='h-3.5 mx-0.5' />
       <TipPopup title={t('workflow.common.pointerMode')} shortcuts={['v']}>
         <div
           className={cn(
             'flex items-center justify-center mr-[1px] w-8 h-8 rounded-lg cursor-pointer',
-            controlMode === ControlMode.Pointer ? 'bg-primary-50 text-primary-600' : 'hover:bg-black/5 hover:text-gray-700',
-            `${nodesReadOnly && '!cursor-not-allowed opacity-50'}`,
+            controlMode === ControlMode.Pointer ? 'bg-state-accent-active text-text-accent' : 'hover:bg-state-base-hover hover:text-text-secondary',
+            `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
           )}
           onClick={handleModePointer}
         >
@@ -73,20 +74,20 @@ const Control = () => {
         <div
           className={cn(
             'flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer',
-            controlMode === ControlMode.Hand ? 'bg-primary-50 text-primary-600' : 'hover:bg-black/5 hover:text-gray-700',
-            `${nodesReadOnly && '!cursor-not-allowed opacity-50'}`,
+            controlMode === ControlMode.Hand ? 'bg-state-accent-active text-text-accent' : 'hover:bg-state-base-hover hover:text-text-secondary',
+            `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
           )}
           onClick={handleModeHand}
         >
           <RiHand className='w-4 h-4' />
         </div>
       </TipPopup>
-      <div className='mx-[3px] w-[1px] h-3.5 bg-gray-200'></div>
+      <Divider type='vertical' className='h-3.5 mx-0.5' />
       <TipPopup title={t('workflow.panel.organizeBlocks')} shortcuts={['ctrl', 'o']}>
         <div
           className={cn(
-            'flex items-center justify-center w-8 h-8 rounded-lg hover:bg-black/5 hover:text-gray-700 cursor-pointer',
-            `${nodesReadOnly && '!cursor-not-allowed opacity-50'}`,
+            'flex items-center justify-center w-8 h-8 rounded-lg hover:bg-state-base-hover hover:text-text-secondary cursor-pointer',
+            `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
           )}
           onClick={handleLayout}
         >

+ 3 - 1
web/app/components/workflow/operator/index.tsx

@@ -17,7 +17,9 @@ const Operator = ({ handleUndo, handleRedo }: OperatorProps) => {
           width: 102,
           height: 72,
         }}
-        className='!absolute !left-4 !bottom-14 z-[9] !m-0 !w-[102px] !h-[72px] !border-[0.5px] !border-black/8 !rounded-lg !shadow-lg'
+        maskColor='var(--color-shadow-shadow-5)'
+        className='!absolute !left-4 !bottom-14 z-[9] !m-0 !w-[102px] !h-[72px] !border-[0.5px] !border-divider-subtle
+        !rounded-lg !shadow-md !shadow-shadow-shadow-5 !bg-workflow-minimap-bg'
       />
       <div className='flex items-center mt-1 gap-2 absolute left-4 bottom-4 z-[9]'>
         <ZoomInOut />

+ 4 - 4
web/app/components/workflow/operator/tip-popup.tsx

@@ -15,12 +15,12 @@ const TipPopup = ({
   return (
     <Tooltip
       offset={4}
-      popupClassName='!p-0 !bg-gray-25'
+      popupClassName='p-0 bg-transparent'
       popupContent={
-        <div className='flex items-center gap-1 px-2 h-6 text-xs font-medium text-gray-700 rounded-lg border-[0.5px] border-black/5'>
-          {title}
+        <div className='flex items-center gap-1 p-1.5 backdrop-blur-[5px] shadow-lg rounded-lg border-[0.5px] border-components-panel-border bg-components-tooltip-bg'>
+          <span className='system-xs-medium text-text-secondary'>{title}</span>
           {
-            shortcuts && <ShortcutsName keys={shortcuts} className='!text-[11px]' />
+            shortcuts && <ShortcutsName keys={shortcuts} />
           }
         </div>
       }

+ 32 - 30
web/app/components/workflow/operator/zoom-in-out.tsx

@@ -18,10 +18,9 @@ import {
   useNodesSyncDraft,
   useWorkflowReadOnly,
 } from '../hooks'
-import {
-  getKeyboardKeyNameBySystem,
-} from '../utils'
+
 import ShortcutsName from '../shortcuts-name'
+import Divider from '../../base/divider'
 import TipPopup from './tip-popup'
 import cn from '@/utils/classnames'
 import {
@@ -132,53 +131,54 @@ const ZoomInOut: FC = () => {
     >
       <PortalToFollowElemTrigger asChild onClick={handleTrigger}>
         <div className={`
-          p-0.5 h-9 cursor-pointer text-[13px] text-gray-500 font-medium rounded-lg bg-white shadow-lg border-[0.5px] border-gray-100
+          p-0.5 h-9 cursor-pointer text-[13px] backdrop-blur-[5px] rounded-lg
+          bg-components-actionbar-bg shadow-lg border-[0.5px] border-components-actionbar-border 
+          hover:bg-state-base-hover
           ${workflowReadOnly && '!cursor-not-allowed opacity-50'}
         `}>
           <div className={cn(
-            'flex items-center justify-between w-[98px] h-8 hover:bg-gray-50 rounded-lg',
-            open && 'bg-gray-50',
+            'flex items-center justify-between w-[98px] h-8 rounded-lg',
           )}>
             <TipPopup
               title={t('workflow.operator.zoomOut')}
               shortcuts={['ctrl', '-']}
             >
               <div
-                className='flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer hover:bg-black/5'
+                className='flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer'
                 onClick={(e) => {
                   e.stopPropagation()
                   zoomOut()
                 }}
               >
-                <RiZoomOutLine className='w-4 h-4' />
+                <RiZoomOutLine className='w-4 h-4 text-text-tertiary hover:text-text-secondary' />
               </div>
             </TipPopup>
-            <div className='w-[34px]'>{parseFloat(`${zoom * 100}`).toFixed(0)}%</div>
+            <div className={cn('w-[34px] system-sm-medium text-text-tertiary hover:text-text-secondary')}>{parseFloat(`${zoom * 100}`).toFixed(0)}%</div>
             <TipPopup
               title={t('workflow.operator.zoomIn')}
               shortcuts={['ctrl', '+']}
             >
               <div
-                className='flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer hover:bg-black/5'
+                className='flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer'
                 onClick={(e) => {
                   e.stopPropagation()
                   zoomIn()
                 }}
               >
-                <RiZoomInLine className='w-4 h-4' />
+                <RiZoomInLine className='w-4 h-4 text-text-tertiary hover:text-text-secondary' />
               </div>
             </TipPopup>
           </div>
         </div>
       </PortalToFollowElemTrigger>
       <PortalToFollowElemContent className='z-10'>
-        <div className='w-[145px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg'>
+        <div className='w-[145px] backdrop-blur-[5px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
           {
             ZOOM_IN_OUT_OPTIONS.map((options, i) => (
               <Fragment key={i}>
                 {
                   i !== 0 && (
-                    <div className='h-[1px] bg-gray-100' />
+                    <Divider className='m-0' />
                   )
                 }
                 <div className='p-1'>
@@ -186,25 +186,27 @@ const ZoomInOut: FC = () => {
                     options.map(option => (
                       <div
                         key={option.key}
-                        className='flex items-center justify-between px-3 h-8 rounded-lg hover:bg-gray-50 cursor-pointer text-sm text-gray-700'
+                        className='flex items-center justify-between space-x-1 py-1.5 pl-3 pr-2 h-8 rounded-lg hover:bg-state-base-hover cursor-pointer system-md-regular text-text-secondary'
                         onClick={() => handleZoom(option.key)}
                       >
-                        {option.text}
-                        {
-                          option.key === ZoomType.zoomToFit && (
-                            <ShortcutsName keys={[`${getKeyboardKeyNameBySystem('ctrl')}`, '1']} />
-                          )
-                        }
-                        {
-                          option.key === ZoomType.zoomTo50 && (
-                            <ShortcutsName keys={['shift', '5']} />
-                          )
-                        }
-                        {
-                          option.key === ZoomType.zoomTo100 && (
-                            <ShortcutsName keys={['shift', '1']} />
-                          )
-                        }
+                        <span>{option.text}</span>
+                        <div className='flex items-center space-x-0.5'>
+                          {
+                            option.key === ZoomType.zoomToFit && (
+                              <ShortcutsName keys={['ctrl', '1']} />
+                            )
+                          }
+                          {
+                            option.key === ZoomType.zoomTo50 && (
+                              <ShortcutsName keys={['shift', '5']} />
+                            )
+                          }
+                          {
+                            option.key === ZoomType.zoomTo100 && (
+                              <ShortcutsName keys={['shift', '1']} />
+                            )
+                          }
+                        </div>
                       </div>
                     ))
                   }

+ 11 - 10
web/app/components/workflow/panel-contextmenu.tsx

@@ -5,6 +5,7 @@ import {
 } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useClickAway } from 'ahooks'
+import Divider from '../base/divider'
 import ShortcutsName from './shortcuts-name'
 import { useStore } from './store'
 import {
@@ -41,7 +42,7 @@ const PanelContextmenu = () => {
   const renderTrigger = () => {
     return (
       <div
-        className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
+        className='flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-state-base-hover'
       >
         {t('workflow.common.addBlock')}
       </div>
@@ -53,7 +54,7 @@ const PanelContextmenu = () => {
 
   return (
     <div
-      className='absolute w-[200px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xl z-[9]'
+      className='absolute w-[200px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg z-[9]'
       style={{
         left: panelMenu.left,
         top: panelMenu.top,
@@ -69,7 +70,7 @@ const PanelContextmenu = () => {
           }}
         />
         <div
-          className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
+          className='flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-state-base-hover'
           onClick={(e) => {
             e.stopPropagation()
             handleAddNote()
@@ -79,7 +80,7 @@ const PanelContextmenu = () => {
           {t('workflow.nodes.note.addNote')}
         </div>
         <div
-          className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
+          className='flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-state-base-hover'
           onClick={() => {
             handleStartWorkflowRun()
             handlePaneContextmenuCancel()
@@ -89,12 +90,12 @@ const PanelContextmenu = () => {
           <ShortcutsName keys={['alt', 'r']} />
         </div>
       </div>
-      <div className='h-[1px] bg-gray-100'></div>
+      <Divider className='m-0' />
       <div className='p-1'>
         <div
           className={cn(
-            'flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer',
-            !clipboardElements.length ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50',
+            'flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer',
+            !clipboardElements.length ? 'opacity-50 cursor-not-allowed' : 'hover:bg-state-base-hover',
           )}
           onClick={() => {
             if (clipboardElements.length) {
@@ -107,16 +108,16 @@ const PanelContextmenu = () => {
           <ShortcutsName keys={['ctrl', 'v']} />
         </div>
       </div>
-      <div className='h-[1px] bg-gray-100'></div>
+      <Divider className='m-0' />
       <div className='p-1'>
         <div
-          className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
+          className='flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-state-base-hover'
           onClick={() => exportCheck()}
         >
           {t('app.export')}
         </div>
         <div
-          className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50'
+          className='flex items-center justify-between px-3 h-8 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-state-base-hover'
           onClick={() => setShowImportDSLModal(true)}
         >
           {t('workflow.common.importDSL')}

+ 2 - 2
web/app/components/workflow/shortcuts-name.tsx

@@ -12,14 +12,14 @@ const ShortcutsName = ({
 }: ShortcutsNameProps) => {
   return (
     <div className={cn(
-      'flex items-center gap-0.5 h-4 text-xs text-gray-400',
+      'flex items-center gap-0.5',
       className,
     )}>
       {
         keys.map(key => (
           <div
             key={key}
-            className='capitalize'
+            className='w-4 h-4 flex items-center justify-center bg-components-kbd-bg-gray rounded-[4px] system-kbd capitalize'
           >
             {getKeyboardKeyNameBySystem(key)}
           </div>

+ 3 - 1
web/app/components/workflow/style.css

@@ -19,4 +19,6 @@
 
 #workflow-container .react-flow__node-custom-note {
   z-index: -1000 !important;
-}
+}
+
+#workflow-container .react-flow {}

+ 1 - 0
web/app/components/workflow/utils.ts

@@ -549,6 +549,7 @@ export const isMac = () => {
 const specialKeysNameMap: Record<string, string | undefined> = {
   ctrl: '⌘',
   alt: '⌥',
+  shift: '⇧',
 }
 
 export const getKeyboardKeyNameBySystem = (key: string) => {

+ 1 - 1
web/app/layout.tsx

@@ -34,7 +34,7 @@ const LocaleLayout = ({
         <meta name="apple-mobile-web-app-status-bar-style" content="default" />
       </head>
       <body
-        className="h-full select-auto"
+        className="h-full select-auto color-scheme"
         data-api-prefix={process.env.NEXT_PUBLIC_API_PREFIX}
         data-pubic-api-prefix={process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX}
         data-public-edition={process.env.NEXT_PUBLIC_EDITION}

+ 8 - 0
web/app/styles/globals.css

@@ -7,6 +7,14 @@
 @import "../../themes/manual-light.css";
 @import "../../themes/manual-dark.css";
 
+html {
+  color-scheme: light;
+}
+
+html[data-theme='dark'] {
+  color-scheme: dark;
+}
+
 html[data-changing-theme] * {
   transition: none !important;
 }

+ 1 - 0
web/tailwind.config.js

@@ -93,6 +93,7 @@ module.exports = {
         'chatbot-bg': 'var(--color-chatbot-bg)',
         'chat-bubble-bg': 'var(--color-chat-bubble-bg)',
         'workflow-process-bg': 'var(--color-workflow-process-bg)',
+        'mask-top2bottom-gray-50-to-transparent': 'var(--mask-top2bottom-gray-50-to-transparent)',
       },
     },
   },

+ 1 - 0
web/themes/manual-dark.css

@@ -2,4 +2,5 @@ html[data-theme="dark"] {
   --color-chatbot-bg: linear-gradient(180deg, rgba(34, 34, 37, 0.90) 0%, rgba(29, 29, 32, 0.90) 90.48%);
   --color-chat-bubble-bg: linear-gradient(180deg, rgba(200, 206, 218, 0.08) 0%, rgba(200, 206, 218, 0.02) 100%);
   --color-workflow-process-bg: linear-gradient(90deg, rgba(24, 24, 27, 0.25) 0%, rgba(24, 24, 27, 0.04) 100%);
+  --mask-top2bottom-gray-50-to-transparent:linear-gradient(180deg, rgba(24, 24, 27, 0.08) 0%, rgba(0, 0, 0, 0.00) 100%);
 }

+ 1 - 0
web/themes/manual-light.css

@@ -2,4 +2,5 @@ html[data-theme="light"] {
   --color-chatbot-bg: linear-gradient(180deg, rgba(249, 250, 251, 0.90) 0%, rgba(242, 244, 247, 0.90) 90.48%);
   --color-chat-bubble-bg: linear-gradient(180deg, #FFF 0%, rgba(255, 255, 255, 0.60) 100%);
   --color-workflow-process-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.20) 0%, rgba(200, 206, 218, 0.04) 100%);
+  --mask-top2bottom-gray-50-to-transparent: linear-gradient(180deg, rgba(200, 206, 218, 0.20) 0%, rgba(255, 255, 255, 0.00) 100%);
 }