refactor: refactor the button component using forwardRef (#4379)

Co-authored-by: KVOJJJin <jzongcode@gmail.com>
This commit is contained in:
TinsFox
2024-06-19 14:13:16 +08:00
committed by GitHub
parent bb33ffc332
commit a3bd5eba02
100 changed files with 218 additions and 224 deletions

View File

@@ -1,50 +1,44 @@
import type { FC, MouseEventHandler, PropsWithChildren } from 'react'
import React, { memo } from 'react'
import React from 'react'
import { type VariantProps, cva } from 'class-variance-authority'
import classNames from 'classnames'
import Spinner from '../spinner'
export type IButtonProps = PropsWithChildren<{
type?: string
className?: string
disabled?: boolean
const buttonVariants = cva(
'btn disabled:pointer-events-none',
{
variants: {
variant: {
primary: 'btn-primary disabled:btn-primary-disabled',
warning:
'btn-warning disabled:btn-warning-disabled',
default: 'btn-default disabled:btn-default-disabled',
},
},
defaultVariants: {
variant: 'default',
},
},
)
export type ButtonProps = {
loading?: boolean
tabIndex?: number
onClick?: MouseEventHandler<HTMLDivElement>
}>
} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>
const Button: FC<IButtonProps> = ({
type,
disabled,
children,
className,
onClick,
loading = false,
tabIndex,
}) => {
let typeClassNames = 'cursor-pointer'
switch (type) {
case 'primary':
typeClassNames = (disabled || loading) ? 'btn-primary-disabled' : 'btn-primary'
break
case 'warning':
typeClassNames = (disabled || loading) ? 'btn-warning-disabled' : 'btn-warning'
break
default:
typeClassNames = disabled ? 'btn-default-disabled' : 'btn-default'
break
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, loading, children, ...props }, ref) => {
return (
<button
className={classNames(buttonVariants({ variant, className }))}
ref={ref}
{...props}
>
{children}
<Spinner loading={loading} className='!text-white !h-3 !w-3 !border-2 !ml-1' />
</button>
)
},
)
Button.displayName = 'Button'
return (
<div
className={classNames('btn', typeClassNames, className)}
tabIndex={tabIndex}
onClick={disabled ? undefined : onClick}
>
{children}
{/* Spinner is hidden when loading is false */}
<Spinner loading={loading} className='!text-white !h-3 !w-3 !border-2 !ml-1' />
</div>
)
}
export default memo(Button)
export default Button
export { Button, buttonVariants }

View File

@@ -93,7 +93,7 @@ const ConfigPanel = () => {
<Form />
<div className={`pl-[136px] flex items-center ${isMobile && '!pl-0'}`}>
<Button
type='primary'
variant='primary'
className='mr-2 text-sm font-medium'
onClick={() => {
setCollapsed(true)
@@ -118,7 +118,7 @@ const ConfigPanel = () => {
<Form />
<Button
className={`px-4 py-0 h-9 ${inputsForms.length && !isMobile && 'ml-[136px]'}`}
type='primary'
variant='primary'
onClick={handleStartChat}
>
<MessageDotsCircle className='mr-2 w-4 h-4 text-white' />

View File

@@ -42,7 +42,7 @@ const ConfirmUI: FC<IConfirmUIProps> = ({
</div>
<div className='flex gap-3 mt-4 ml-12'>
<Button type='primary' onClick={onConfirm} className='flex items-center justify-center min-w-20 text-center text-white rounded-lg cursor-pointer h-9 '>{confirmText || t('common.operation.confirm')}</Button>
<Button variant='primary' onClick={onConfirm} className='flex items-center justify-center min-w-20 text-center text-white rounded-lg cursor-pointer h-9 '>{confirmText || t('common.operation.confirm')}</Button>
<Button onClick={onCancel} className='flex items-center justify-center min-w-20 text-center text-gray-500 border rounded-lg cursor-pointer h-9 border-color-gray-200'>{cancelText || t('common.operation.cancel')}</Button>
</div>
</div>

View File

@@ -51,7 +51,7 @@ const ConfirmCommon: FC<ConfirmCommonProps> = ({
}
return (
<Modal isShow={isShow} onClose={() => {}} className='!w-[480px] !max-w-[480px] !p-0 !rounded-2xl' wrapperClassName={confirmWrapperClassName}>
<Modal isShow={isShow} onClose={() => { }} className='!w-[480px] !max-w-[480px] !p-0 !rounded-2xl' wrapperClassName={confirmWrapperClassName}>
<div className={cn(s[`wrapper-${type}`], 'relative p-8')}>
<div className='flex items-center justify-center absolute top-4 right-4 w-8 h-8 cursor-pointer' onClick={onCancel}>
<XClose className='w-4 h-4 text-gray-500' />
@@ -77,7 +77,7 @@ const ConfirmCommon: FC<ConfirmCommonProps> = ({
)
}
<Button
type='primary'
variant='primary'
className={confirmBtnClassName || ''}
onClick={onConfirm}
disabled={confirmDisabled}

View File

@@ -189,14 +189,14 @@ const EmojiPicker: FC<IEmojiPickerProps> = ({
</div>
<Divider className='m-0' />
<div className='w-full flex items-center justify-center p-3 gap-2'>
<Button type="default" className='w-full' onClick={() => {
<Button variant="default" className='w-full' onClick={() => {
onClose && onClose()
}}>
{t('app.emoji.cancel')}
</Button>
<Button
disabled={selectedEmoji === ''}
type="primary"
variant="primary"
className='w-full'
onClick={() => {
onSelect && onSelect(selectedEmoji, selectedBackground)

View File

@@ -262,7 +262,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
onClick={() => handleDataTypeChange(provider.key)}
>
<div className={`
mr-2 w-4 h-4 rounded-full border
mr-2 w-4 h-4 rounded-full border
${localeData.type === provider.key ? 'border-[5px] border-primary-600' : 'border border-gray-300'}`} />
{provider.name}
</div>
@@ -362,7 +362,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
{t('common.operation.cancel')}
</Button>
<Button
type='primary'
variant='primary'
className='text-sm font-medium'
onClick={handleSave}
disabled={localeData.type === 'openai_moderation' && !openaiProviderConfiged}

View File

@@ -169,7 +169,7 @@ const OpeningStatement: FC<OpeningStatementProps> = ({
isFocus ? (
<div className='flex items-center space-x-1'>
<div className='px-3 leading-[18px] text-xs font-medium text-gray-700 cursor-pointer' onClick={handleCancel}>{t('common.operation.cancel')}</div>
<Button className='!h-8 !px-3 text-xs' onClick={handleConfirm} type="primary">{t('common.operation.save')}</Button>
<Button className='!h-8 !px-3 text-xs' onClick={handleConfirm} variant="primary">{t('common.operation.save')}</Button>
</div>
) : (
<OperationBtn type='edit' actionName={hasValue ? '' : t('appDebug.openingStatement.writeOpener') as string} onClick={handleEdit} />

View File

@@ -42,7 +42,7 @@ const ImageLinkInput: FC<ImageLinkInputProps> = ({
placeholder={t('common.imageUploader.pasteImageLinkInputPlaceholder') || ''}
/>
<Button
type='primary'
variant='primary'
className='!h-6 text-xs font-medium'
disabled={!imageLink || disabled}
onClick={handleClick}

View File

@@ -50,7 +50,7 @@ const DeleteConfirmModal: FC<Props> = ({
<div className='flex gap-2 justify-end'>
<Button onClick={onHide}>{t('common.operation.cancel')}</Button>
<Button
type='warning'
variant='warning'
onClick={onRemove}
className='border-red-700 border-[0.5px]'
>

View File

@@ -23,7 +23,7 @@ const TagRemoveModal = ({ show, tag, onConfirm, onClose }: TagRemoveModalProps)
<Modal
className={cn('p-8 max-w-[480px] w-[480px]', s.bg)}
isShow={show}
onClose={() => {}}
onClose={() => { }}
>
<div className='absolute right-4 top-4 p-2 cursor-pointer' onClick={onClose}>
<XClose className='w-4 h-4 text-gray-500' />
@@ -40,7 +40,7 @@ const TagRemoveModal = ({ show, tag, onConfirm, onClose }: TagRemoveModalProps)
</div>
<div className='pt-6 flex items-center justify-end'>
<Button className='mr-2 text-gray-700 text-sm font-medium' onClick={onClose}>{t('common.operation.cancel')}</Button>
<Button className='text-sm font-medium border-red-700 border-[0.5px]' type="warning" onClick={onConfirm}>{t('common.operation.delete')}</Button>
<Button className='text-sm font-medium border-red-700 border-[0.5px]' variant="warning" onClick={onConfirm}>{t('common.operation.delete')}</Button>
</div>
</Modal>
)