Browse Source

feat: added ActionButton component (#6631)

Yi Xiao 8 months ago
parent
commit
c112188207

+ 49 - 0
web/app/components/base/action-button/index.css

@@ -0,0 +1,49 @@
+@tailwind components;
+
+@layer components {
+    .action-btn {
+        @apply inline-flex justify-center items-center cursor-pointer text-text-tertiary
+        hover:text-text-secondary 
+        hover:bg-state-base-hover 
+    }
+
+    .action-btn-disabled {
+        @apply cursor-not-allowed
+    }
+
+    .action-btn-xl {
+        @apply p-2 w-9 h-9 rounded-lg
+    }
+
+    .action-btn-l {
+        @apply p-1.5 w-[34px] h-[34px] rounded-lg
+    }
+
+    /* m is for the regular button */
+    .action-btn-m {
+        @apply p-0.5 w-6 h-6 rounded-lg
+    }
+
+    .action-btn-xs {
+        @apply p-0 w-5 h-5 rounded
+    }
+
+    .action-btn.action-btn-active {
+        @apply 
+        text-text-accent 
+        bg-state-accent-active
+        hover:bg-state-accent-active-alt
+    }
+
+    .action-btn.action-btn-disabled {
+        @apply
+        text-text-disabled
+    }
+
+    .action-btn.action-btn-destructive {
+        @apply
+        text-text-destructive
+        bg-state-destructive-hover
+    }
+
+}

+ 70 - 0
web/app/components/base/action-button/index.tsx

@@ -0,0 +1,70 @@
+import type { CSSProperties } from 'react'
+import React from 'react'
+import { type VariantProps, cva } from 'class-variance-authority'
+import classNames from '@/utils/classnames'
+
+enum ActionButtonState {
+  Destructive = 'destructive',
+  Active = 'active',
+  Disabled = 'disabled',
+  Default = '',
+}
+
+const actionButtonVariants = cva(
+  'action-btn',
+  {
+    variants: {
+      size: {
+        xs: 'action-btn-xs',
+        m: 'action-btn-m',
+        l: 'action-btn-l',
+        xl: 'action-btn-xl',
+      },
+    },
+    defaultVariants: {
+      size: 'm',
+    },
+  },
+)
+
+export type ActionButtonProps = {
+  size?: 'xs' | 'm' | 'l' | 'xl'
+  state?: ActionButtonState
+  styleCss?: CSSProperties
+} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof actionButtonVariants>
+
+function getActionButtonState(state: ActionButtonState) {
+  switch (state) {
+    case ActionButtonState.Destructive:
+      return 'action-btn-destructive'
+    case ActionButtonState.Active:
+      return 'action-btn-active'
+    case ActionButtonState.Disabled:
+      return 'action-btn-disabled'
+    default:
+      return ''
+  }
+}
+
+const ActionButton = React.forwardRef<HTMLButtonElement, ActionButtonProps>(
+  ({ className, size, state = ActionButtonState.Default, styleCss, children, ...props }, ref) => {
+    return (
+      <button
+        type='button'
+        className={classNames(
+          actionButtonVariants({ className, size }),
+          getActionButtonState(state),
+        )}
+        ref={ref}
+        style={styleCss}
+        {...props}
+      >
+        {children}
+      </button>
+    )
+  },
+)
+ActionButton.displayName = 'ActionButton'
+
+export default ActionButton
+export { ActionButton, ActionButtonState, actionButtonVariants }

+ 3 - 0
web/app/components/base/tooltip-plus/index.tsx

@@ -13,6 +13,7 @@ export type TooltipProps = {
   hideArrow?: boolean
   popupClassName?: string
   offset?: OffsetOptions
+  asChild?: boolean
 }
 
 const arrow = (
@@ -27,6 +28,7 @@ const Tooltip: FC<TooltipProps> = ({
   hideArrow,
   popupClassName,
   offset,
+  asChild,
 }) => {
   const [open, setOpen] = useState(false)
   const [isHoverPopup, {
@@ -79,6 +81,7 @@ const Tooltip: FC<TooltipProps> = ({
           }
         }}
         onMouseLeave={() => triggerMethod === 'hover' && handleLeave(true)}
+        asChild={asChild}
       >
         {children}
       </PortalToFollowElemTrigger>

+ 1 - 1
web/app/components/header/account-about/index.tsx

@@ -45,7 +45,7 @@ export default function AccountAbout({
                 IS_CE_EDITION
                   ? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank' rel='noopener noreferrer'>Open Source License</Link>
                   : <>
-                    <Link href='https://dify.ai/privacy' target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,
+                    <Link href='https://dify.ai/privacy' target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,<span> </span>
                     <Link href='https://dify.ai/terms' target='_blank' rel='noopener noreferrer'>Terms of Service</Link>
                   </>
               }

+ 16 - 6
web/app/components/workflow/nodes/_base/components/prompt/editor.tsx

@@ -30,6 +30,7 @@ import s from '@/app/components/app/configuration/config-prompt/style.module.css
 import { useEventEmitterContextContext } from '@/context/event-emitter'
 import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-editor/plugins/update-block'
 import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
+import ActionButton from '@/app/components/base/action-button'
 import TooltipPlus from '@/app/components/base/tooltip-plus'
 import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars'
 import Switch from '@/app/components/base/switch'
@@ -128,7 +129,7 @@ const Editor: FC<Props> = ({
     <Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}>
       <div ref={ref} className={cn(isFocus ? s.gradientBorder : 'bg-gray-100', isExpand && 'h-full', '!rounded-[9px] p-0.5')}>
         <div className={cn(isFocus ? 'bg-gray-50' : 'bg-gray-100', isExpand && 'h-full flex flex-col', 'rounded-lg')}>
-          <div className={cn(headerClassName, 'pt-1 pl-3 pr-2 flex justify-between h-6 items-center')}>
+          <div className={cn(headerClassName, 'pt-1 pl-3 pr-2 flex justify-between items-center')}>
             <div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div>
             <div className='flex items-center'>
               <div className='leading-[18px] text-xs font-medium text-gray-500'>{value?.length || 0}</div>
@@ -138,7 +139,7 @@ const Editor: FC<Props> = ({
 
               <div className='w-px h-3 ml-2 mr-2 bg-gray-200'></div>
               {/* Operations */}
-              <div className='flex items-center space-x-2'>
+              <div className='flex items-center space-x-[2px]'>
                 {isSupportJinja && (
                   <TooltipPlus
                     popupContent={
@@ -165,19 +166,28 @@ const Editor: FC<Props> = ({
                 {!readOnly && (
                   <TooltipPlus
                     popupContent={`${t('workflow.common.insertVarTip')}`}
+                    asChild
                   >
-                    <Variable02 className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={handleInsertVariable} />
+                    <ActionButton onClick={handleInsertVariable}>
+                      <Variable02 className='w-4 h-4' />
+                    </ActionButton>
                   </TooltipPlus>
                 )}
                 {showRemove && (
-                  <RiDeleteBinLine className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={onRemove} />
+                  <ActionButton onClick={onRemove}>
+                    <RiDeleteBinLine className='w-4 h-4' />
+                  </ActionButton>
                 )}
                 {!isCopied
                   ? (
-                    <Clipboard className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={handleCopy} />
+                    <ActionButton onClick={handleCopy}>
+                      <Clipboard className='w-4 h-4' />
+                    </ActionButton>
                   )
                   : (
-                    <ClipboardCheck className='mx-1 w-3.5 h-3.5 text-gray-500' />
+                    <ActionButton>
+                      <ClipboardCheck className='w-4 h-4' />
+                    </ActionButton>
                   )
                 }
                 <ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />

+ 1 - 1
web/app/components/workflow/nodes/_base/components/selector.tsx

@@ -63,7 +63,7 @@ const TypeSelector: FC<Props> = ({
           <div
             onClick={toggleShow}
             className={cn(showOption && 'bg-black/5', 'flex items-center h-5 pl-1 pr-0.5 rounded-md text-xs font-semibold text-gray-700 cursor-pointer hover:bg-black/5')}>
-            <div className={cn(triggerClassName, 'text-sm font-semibold', uppercase && 'uppercase', noValue && 'text-gray-400')}>{!noValue ? item?.label : placeholder}</div>
+            <div className={cn(triggerClassName, 'text-xs font-semibold', uppercase && 'uppercase', noValue && 'text-gray-400')}>{!noValue ? item?.label : placeholder}</div>
             {!readonly && <DropDownIcon className='w-3 h-3 ' />}
           </div>
         )}

+ 4 - 1
web/app/components/workflow/nodes/_base/components/toggle-expand-btn.tsx

@@ -5,6 +5,7 @@ import {
   RiCollapseDiagonalLine,
   RiExpandDiagonalLine,
 } from '@remixicon/react'
+import ActionButton from '@/app/components/base/action-button'
 
 type Props = {
   isExpand: boolean
@@ -21,7 +22,9 @@ const ExpandBtn: FC<Props> = ({
 
   const Icon = isExpand ? RiCollapseDiagonalLine : RiExpandDiagonalLine
   return (
-    <Icon className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={handleToggle} />
+    <ActionButton onClick={handleToggle}>
+      <Icon className='w-4 h-4' />
+    </ActionButton>
   )
 }
 export default React.memo(ExpandBtn)

+ 6 - 3
web/app/components/workflow/nodes/llm/components/prompt-generator-btn.tsx

@@ -4,6 +4,7 @@ import React, { useCallback } from 'react'
 import { useBoolean } from 'ahooks'
 import cn from 'classnames'
 import { Generator } from '@/app/components/base/icons/src/vender/other'
+import { ActionButton } from '@/app/components/base/action-button'
 import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
 import { AppType } from '@/types/app'
 import type { AutomaticRes } from '@/service/debug'
@@ -28,9 +29,11 @@ const PromptGeneratorBtn: FC<Props> = ({
   }, [onGenerated, showAutomaticFalse])
   return (
     <div className={cn(className)}>
-      <div className='p-[5px] rounded-md hover:bg-[#155EEF]/8 cursor-pointer' onClick={showAutomaticTrue}>
-        <Generator className='w-3.5 h-3.5 text-primary-600' />
-      </div>
+      <ActionButton
+        className='hover:bg-[#155EFF]/8'
+        onClick={showAutomaticTrue}>
+        <Generator className='w-4 h-4 text-primary-600' />
+      </ActionButton>
       {showAutomatic && (
         <GetAutomaticResModal
           mode={AppType.chat}

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

@@ -660,6 +660,7 @@ button:focus-within {
 }
 
 @import '../components/base/button/index.css';
+@import '../components/base/action-button/index.css';
 @import '../components/base/modal/index.css';
 
 @tailwind utilities;