From ebf741114dcac38e16a712e79aae736d97763ae6 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:16:39 +0800 Subject: [PATCH] refactor(web): replace Button destructive boolean with tone semantic axis (#35176) --- .../account-page/AvatarWithEdit.tsx | 2 +- .../components/verify-email.tsx | 2 +- .../app/configuration/configuration-view.tsx | 4 +-- .../dsl-confirm-modal.tsx | 2 +- .../app/create-from-dsl-modal/index.tsx | 2 +- .../components/app/switch-app-modal/index.tsx | 2 +- web/app/components/base/confirm/index.tsx | 2 +- .../__tests__/index.spec.tsx | 6 ++-- .../base/inline-delete-confirm/index.tsx | 2 +- .../base/tag-management/tag-remove-modal.tsx | 2 +- .../ui/alert-dialog/__tests__/index.spec.tsx | 2 +- .../components/base/ui/alert-dialog/index.tsx | 4 +-- .../base/ui/button/__tests__/index.spec.tsx | 11 +++++-- web/app/components/base/ui/button/index.css | 32 +++++++++---------- .../base/ui/button/index.stories.tsx | 7 ++-- web/app/components/base/ui/button/index.tsx | 16 +++++++--- .../dsl-confirm-modal.tsx | 2 +- .../detail/completed/common/batch-action.tsx | 2 +- .../completed/common/regeneration-modal.tsx | 4 +-- .../transfer-ownership-modal/index.tsx | 2 +- .../model-provider-page/model-modal/index.tsx | 2 +- .../update-plugin/downgrade-warning.tsx | 2 +- .../__tests__/version-mismatch-modal.spec.tsx | 2 +- .../components/update-dsl-modal.tsx | 2 +- .../components/version-mismatch-modal.tsx | 2 +- .../edit-custom-collection-modal/index.tsx | 2 +- .../confirm-modal/__tests__/index.spec.tsx | 2 +- .../workflow-tool/confirm-modal/index.tsx | 2 +- .../components/tools/workflow-tool/index.tsx | 2 +- .../delete-confirm-modal.tsx | 2 +- .../components/workflow/update-dsl-modal.tsx | 4 +-- 31 files changed, 73 insertions(+), 59 deletions(-) diff --git a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx index da1da8448b..05048008b4 100644 --- a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx +++ b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx @@ -159,7 +159,7 @@ const AvatarWithEdit = ({ onSave, ...props }: AvatarWithEditProps) => { {t('operation.cancel', { ns: 'common' })} - diff --git a/web/app/account/(commonLayout)/delete-account/components/verify-email.tsx b/web/app/account/(commonLayout)/delete-account/components/verify-email.tsx index 7e14d889d9..01e19e51b1 100644 --- a/web/app/account/(commonLayout)/delete-account/components/verify-email.tsx +++ b/web/app/account/(commonLayout)/delete-account/components/verify-email.tsx @@ -53,7 +53,7 @@ export default function VerifyEmail(props: DeleteAccountProps) { }} />
- +
diff --git a/web/app/components/app/configuration/configuration-view.tsx b/web/app/components/app/configuration/configuration-view.tsx index aaee68cb71..049ccf4171 100644 --- a/web/app/components/app/configuration/configuration-view.tsx +++ b/web/app/components/app/configuration/configuration-view.tsx @@ -165,10 +165,10 @@ const ConfigurationView: FC = ({ - + {t('operation.cancel', { ns: 'common' })} - + {t('operation.confirm', { ns: 'common' })} diff --git a/web/app/components/app/create-from-dsl-modal/dsl-confirm-modal.tsx b/web/app/components/app/create-from-dsl-modal/dsl-confirm-modal.tsx index 71a6757bf2..59ba840a07 100644 --- a/web/app/components/app/create-from-dsl-modal/dsl-confirm-modal.tsx +++ b/web/app/components/app/create-from-dsl-modal/dsl-confirm-modal.tsx @@ -43,7 +43,7 @@ const DSLConfirmModal = ({
- +
) diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index bd6c91f323..1fd985c7f8 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -322,7 +322,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
- +
diff --git a/web/app/components/app/switch-app-modal/index.tsx b/web/app/components/app/switch-app-modal/index.tsx index 7ccbfccf30..16016b8096 100644 --- a/web/app/components/app/switch-app-modal/index.tsx +++ b/web/app/components/app/switch-app-modal/index.tsx @@ -152,7 +152,7 @@ const SwitchAppModal = ({ show, appDetail, inAppDetail = false, onSuccess, onClo
- +
diff --git a/web/app/components/base/confirm/index.tsx b/web/app/components/base/confirm/index.tsx index f958d32b99..f23df5cc42 100644 --- a/web/app/components/base/confirm/index.tsx +++ b/web/app/components/base/confirm/index.tsx @@ -152,7 +152,7 @@ function Confirm({
{showCancel && } - {showConfirm && } + {showConfirm && }
diff --git a/web/app/components/base/inline-delete-confirm/__tests__/index.spec.tsx b/web/app/components/base/inline-delete-confirm/__tests__/index.spec.tsx index 6d615554dc..521988d3e6 100644 --- a/web/app/components/base/inline-delete-confirm/__tests__/index.spec.tsx +++ b/web/app/components/base/inline-delete-confirm/__tests__/index.spec.tsx @@ -93,7 +93,7 @@ describe('InlineDeleteConfirm', () => { ) const confirmButton = getByText('Yes').closest('button') - expect(confirmButton?.className).toContain('btn-destructive') + expect(confirmButton?.className).toContain('btn-destructive-primary') }) it('should render without destructive class for warning variant', () => { @@ -108,7 +108,7 @@ describe('InlineDeleteConfirm', () => { ) const confirmButton = getByText('Yes').closest('button') - expect(confirmButton?.className).not.toContain('btn-destructive') + expect(confirmButton?.className).not.toContain('btn-destructive-primary') }) it('should render without destructive class for info variant', () => { @@ -123,7 +123,7 @@ describe('InlineDeleteConfirm', () => { ) const confirmButton = getByText('Yes').closest('button') - expect(confirmButton?.className).not.toContain('btn-destructive') + expect(confirmButton?.className).not.toContain('btn-destructive-primary') }) }) diff --git a/web/app/components/base/inline-delete-confirm/index.tsx b/web/app/components/base/inline-delete-confirm/index.tsx index b119f4bb83..b2f1242da8 100644 --- a/web/app/components/base/inline-delete-confirm/index.tsx +++ b/web/app/components/base/inline-delete-confirm/index.tsx @@ -62,7 +62,7 @@ const InlineDeleteConfirm: FC = ({ - + ) diff --git a/web/app/components/base/ui/alert-dialog/__tests__/index.spec.tsx b/web/app/components/base/ui/alert-dialog/__tests__/index.spec.tsx index adbcb621c9..3eec5f9f05 100644 --- a/web/app/components/base/ui/alert-dialog/__tests__/index.spec.tsx +++ b/web/app/components/base/ui/alert-dialog/__tests__/index.spec.tsx @@ -110,7 +110,7 @@ describe('AlertDialog wrapper', () => { expect(screen.getByTestId('actions')).toHaveClass('flex', 'items-start', 'justify-end', 'gap-2', 'self-stretch', 'p-6', 'custom-actions') const confirmButton = screen.getByRole('button', { name: 'Confirm' }) expect(confirmButton).toHaveClass('btn-primary') - expect(confirmButton).toHaveClass('btn-destructive') + expect(confirmButton).toHaveClass('btn-destructive-primary') }) it('should keep dialog open after confirm click and close via cancel helper', async () => { diff --git a/web/app/components/base/ui/alert-dialog/index.tsx b/web/app/components/base/ui/alert-dialog/index.tsx index 05d9ab3ad9..c8e68260c0 100644 --- a/web/app/components/base/ui/alert-dialog/index.tsx +++ b/web/app/components/base/ui/alert-dialog/index.tsx @@ -86,13 +86,13 @@ type AlertDialogConfirmButtonProps = ButtonProps export function AlertDialogConfirmButton({ variant = 'primary', - destructive = true, + tone = 'destructive', ...props }: AlertDialogConfirmButtonProps) { return ( ) - expect(screen.getByRole('button').className).toContain('btn-destructive') + it('applies destructive tone with default variant', () => { + render() + expect(screen.getByRole('button').className).toContain('btn-destructive-secondary') + }) + + it('applies destructive tone with primary variant', () => { + render() + expect(screen.getByRole('button').className).toContain('btn-destructive-primary') }) }) diff --git a/web/app/components/base/ui/button/index.css b/web/app/components/base/ui/button/index.css index 30140c212d..eee8b7944b 100644 --- a/web/app/components/base/ui/button/index.css +++ b/web/app/components/base/ui/button/index.css @@ -98,53 +98,51 @@ } } -@utility btn-destructive { - &.btn-primary { - @apply bg-components-button-destructive-primary-bg +@utility btn-destructive-primary { + @apply bg-components-button-destructive-primary-bg border-components-button-destructive-primary-border hover:bg-components-button-destructive-primary-bg-hover hover:border-components-button-destructive-primary-border-hover text-components-button-destructive-primary-text; - } - &.btn-primary:is(:disabled, [data-disabled]) { + &:is(:disabled, [data-disabled]) { @apply shadow-none bg-components-button-destructive-primary-bg-disabled border-components-button-destructive-primary-border-disabled text-components-button-destructive-primary-text-disabled; } +} - &.btn-secondary { - @apply bg-components-button-destructive-secondary-bg +@utility btn-destructive-secondary { + @apply bg-components-button-destructive-secondary-bg border-components-button-destructive-secondary-border hover:bg-components-button-destructive-secondary-bg-hover hover:border-components-button-destructive-secondary-border-hover text-components-button-destructive-secondary-text; - } - &.btn-secondary:is(:disabled, [data-disabled]) { + &:is(:disabled, [data-disabled]) { @apply bg-components-button-destructive-secondary-bg-disabled border-components-button-destructive-secondary-border-disabled text-components-button-destructive-secondary-text-disabled; } +} - &.btn-tertiary { - @apply bg-components-button-destructive-tertiary-bg +@utility btn-destructive-tertiary { + @apply bg-components-button-destructive-tertiary-bg hover:bg-components-button-destructive-tertiary-bg-hover text-components-button-destructive-tertiary-text; - } - &.btn-tertiary:is(:disabled, [data-disabled]) { + &:is(:disabled, [data-disabled]) { @apply bg-components-button-destructive-tertiary-bg-disabled text-components-button-destructive-tertiary-text-disabled; } +} - &.btn-ghost { - @apply hover:bg-components-button-destructive-ghost-bg-hover +@utility btn-destructive-ghost { + @apply hover:bg-components-button-destructive-ghost-bg-hover text-components-button-destructive-ghost-text; - } - &.btn-ghost:is(:disabled, [data-disabled]) { + &:is(:disabled, [data-disabled]) { @apply text-components-button-destructive-ghost-text-disabled; } } diff --git a/web/app/components/base/ui/button/index.stories.tsx b/web/app/components/base/ui/button/index.stories.tsx index 8921dc9b27..9552452a22 100644 --- a/web/app/components/base/ui/button/index.stories.tsx +++ b/web/app/components/base/ui/button/index.stories.tsx @@ -11,7 +11,10 @@ const meta = { tags: ['autodocs'], argTypes: { loading: { control: 'boolean' }, - destructive: { control: 'boolean' }, + tone: { + control: 'select', + options: ['default', 'destructive'], + }, disabled: { control: 'boolean' }, variant: { control: 'select', @@ -92,7 +95,7 @@ export const Loading: Story = { export const Destructive: Story = { args: { variant: 'primary', - destructive: true, + tone: 'destructive', children: 'Delete', }, } diff --git a/web/app/components/base/ui/button/index.tsx b/web/app/components/base/ui/button/index.tsx index 22dc6ce3c8..00bbe3c8b7 100644 --- a/web/app/components/base/ui/button/index.tsx +++ b/web/app/components/base/ui/button/index.tsx @@ -21,13 +21,21 @@ const buttonVariants = cva( medium: 'btn-medium', large: 'btn-large', }, - destructive: { - true: 'btn-destructive', + tone: { + default: '', + destructive: '', }, }, + compoundVariants: [ + { variant: 'primary', tone: 'destructive', class: 'btn-destructive-primary' }, + { variant: 'secondary', tone: 'destructive', class: 'btn-destructive-secondary' }, + { variant: 'tertiary', tone: 'destructive', class: 'btn-destructive-tertiary' }, + { variant: 'ghost', tone: 'destructive', class: 'btn-destructive-ghost' }, + ], defaultVariants: { variant: 'secondary', size: 'medium', + tone: 'default', }, }, ) @@ -43,7 +51,7 @@ export function Button({ className, variant, size, - destructive, + tone, loading, disabled, type = 'button', @@ -53,7 +61,7 @@ export function Button({ return (
- +
) diff --git a/web/app/components/datasets/documents/detail/completed/common/batch-action.tsx b/web/app/components/datasets/documents/detail/completed/common/batch-action.tsx index 9a2798698c..3e5f395dfe 100644 --- a/web/app/components/datasets/documents/detail/completed/common/batch-action.tsx +++ b/web/app/components/datasets/documents/detail/completed/common/batch-action.tsx @@ -130,7 +130,7 @@ const BatchAction: FC = ({ )} - @@ -50,7 +50,7 @@ const RegeneratingContent: FC = React.memo(() => {

{t('segment.regeneratingMessage', { ns: 'datasetDocuments' })}

- diff --git a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx index 4500509d00..8554db341f 100644 --- a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx +++ b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx @@ -173,7 +173,7 @@ const TransferOwnershipModal = ({ onClose, show }: Props) => {
-
- +
diff --git a/web/app/components/rag-pipeline/components/__tests__/version-mismatch-modal.spec.tsx b/web/app/components/rag-pipeline/components/__tests__/version-mismatch-modal.spec.tsx index 9ff1de49ad..038362c7ce 100644 --- a/web/app/components/rag-pipeline/components/__tests__/version-mismatch-modal.spec.tsx +++ b/web/app/components/rag-pipeline/components/__tests__/version-mismatch-modal.spec.tsx @@ -101,7 +101,7 @@ describe('VersionMismatchModal', () => { const confirmBtn = screen.getByRole('button', { name: /app\.newApp\.Confirm/ }) expect(confirmBtn).toHaveClass('btn-primary') - expect(confirmBtn).toHaveClass('btn-destructive') + expect(confirmBtn).toHaveClass('btn-destructive-primary') }) }) diff --git a/web/app/components/rag-pipeline/components/update-dsl-modal.tsx b/web/app/components/rag-pipeline/components/update-dsl-modal.tsx index a420f02b9e..cc5d8cd7dd 100644 --- a/web/app/components/rag-pipeline/components/update-dsl-modal.tsx +++ b/web/app/components/rag-pipeline/components/update-dsl-modal.tsx @@ -91,7 +91,7 @@ const UpdateDSLModal = ({ - + ) diff --git a/web/app/components/tools/edit-custom-collection-modal/index.tsx b/web/app/components/tools/edit-custom-collection-modal/index.tsx index 506eab1c8f..6a15010189 100644 --- a/web/app/components/tools/edit-custom-collection-modal/index.tsx +++ b/web/app/components/tools/edit-custom-collection-modal/index.tsx @@ -344,7 +344,7 @@ const EditCustomCollectionModal: FC = ({
{ isEdit && ( - + ) }
diff --git a/web/app/components/tools/workflow-tool/confirm-modal/__tests__/index.spec.tsx b/web/app/components/tools/workflow-tool/confirm-modal/__tests__/index.spec.tsx index e076ae67e2..2cbe98c7ab 100644 --- a/web/app/components/tools/workflow-tool/confirm-modal/__tests__/index.spec.tsx +++ b/web/app/components/tools/workflow-tool/confirm-modal/__tests__/index.spec.tsx @@ -165,7 +165,7 @@ describe('ConfirmModal', () => { // Assert const confirmButton = screen.getByText('common.operation.confirm') expect(confirmButton).toHaveClass('btn-primary') - expect(confirmButton).toHaveClass('btn-destructive') + expect(confirmButton).toHaveClass('btn-destructive-primary') }) }) diff --git a/web/app/components/tools/workflow-tool/confirm-modal/index.tsx b/web/app/components/tools/workflow-tool/confirm-modal/index.tsx index 1533b22f8e..ff78cc017d 100644 --- a/web/app/components/tools/workflow-tool/confirm-modal/index.tsx +++ b/web/app/components/tools/workflow-tool/confirm-modal/index.tsx @@ -36,7 +36,7 @@ const ConfirmModal = ({ show, onConfirm, onClose }: ConfirmModalProps) => {
- +
diff --git a/web/app/components/tools/workflow-tool/index.tsx b/web/app/components/tools/workflow-tool/index.tsx index d93a378ec2..aa99d2aa27 100644 --- a/web/app/components/tools/workflow-tool/index.tsx +++ b/web/app/components/tools/workflow-tool/index.tsx @@ -318,7 +318,7 @@ const WorkflowToolAsModal: FC = ({
{!isAdd && onRemove && ( - + )}
diff --git a/web/app/components/workflow/panel/version-history-panel/delete-confirm-modal.tsx b/web/app/components/workflow/panel/version-history-panel/delete-confirm-modal.tsx index daf485c5a5..4779be8984 100644 --- a/web/app/components/workflow/panel/version-history-panel/delete-confirm-modal.tsx +++ b/web/app/components/workflow/panel/version-history-panel/delete-confirm-modal.tsx @@ -34,7 +34,7 @@ const DeleteConfirmModal: FC = ({ -
diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx index 38607b97d5..98176033c9 100644 --- a/web/app/components/workflow/update-dsl-modal.tsx +++ b/web/app/components/workflow/update-dsl-modal.tsx @@ -247,7 +247,7 @@ const UpdateDSLModal = ({
- +