feat: added ActionButton component (#6631)

This commit is contained in:
Yi Xiao 2024-07-24 18:09:44 +08:00 committed by GitHub
parent 5af2df0cd5
commit c112188207
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 151 additions and 12 deletions

View File

@ -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
}
}

View File

@ -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 }

View File

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

View File

@ -45,7 +45,7 @@ export default function AccountAbout({
IS_CE_EDITION 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://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> <Link href='https://dify.ai/terms' target='_blank' rel='noopener noreferrer'>Terms of Service</Link>
</> </>
} }

View File

@ -30,6 +30,7 @@ import s from '@/app/components/app/configuration/config-prompt/style.module.css
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-editor/plugins/update-block' 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 { 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 TooltipPlus from '@/app/components/base/tooltip-plus'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars'
import Switch from '@/app/components/base/switch' 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}> <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 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(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='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div>
<div className='flex items-center'> <div className='flex items-center'>
<div className='leading-[18px] text-xs font-medium text-gray-500'>{value?.length || 0}</div> <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> <div className='w-px h-3 ml-2 mr-2 bg-gray-200'></div>
{/* Operations */} {/* Operations */}
<div className='flex items-center space-x-2'> <div className='flex items-center space-x-[2px]'>
{isSupportJinja && ( {isSupportJinja && (
<TooltipPlus <TooltipPlus
popupContent={ popupContent={
@ -165,19 +166,28 @@ const Editor: FC<Props> = ({
{!readOnly && ( {!readOnly && (
<TooltipPlus <TooltipPlus
popupContent={`${t('workflow.common.insertVarTip')}`} 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> </TooltipPlus>
)} )}
{showRemove && ( {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 {!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} /> <ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />

View File

@ -63,7 +63,7 @@ const TypeSelector: FC<Props> = ({
<div <div
onClick={toggleShow} 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')}> 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 ' />} {!readonly && <DropDownIcon className='w-3 h-3 ' />}
</div> </div>
)} )}

View File

@ -5,6 +5,7 @@ import {
RiCollapseDiagonalLine, RiCollapseDiagonalLine,
RiExpandDiagonalLine, RiExpandDiagonalLine,
} from '@remixicon/react' } from '@remixicon/react'
import ActionButton from '@/app/components/base/action-button'
type Props = { type Props = {
isExpand: boolean isExpand: boolean
@ -21,7 +22,9 @@ const ExpandBtn: FC<Props> = ({
const Icon = isExpand ? RiCollapseDiagonalLine : RiExpandDiagonalLine const Icon = isExpand ? RiCollapseDiagonalLine : RiExpandDiagonalLine
return ( 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) export default React.memo(ExpandBtn)

View File

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

View File

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