From d1f1cfdcca885eeffaa29a83593ec741499e90cf Mon Sep 17 00:00:00 2001 From: kdletters Date: Sun, 14 Jun 2026 15:04:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=BD=E5=8F=96=E5=86=85=E8=81=94=E9=80=89?= =?UTF-8?q?=E9=A1=B9=E6=8C=89=E9=92=AE=E5=8E=9F=E8=AF=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 PlatformInlineOptionButton,统一承接当前选项加下拉箭头的轻量按钮 chrome。 编辑器生成输入框的比例和模型按钮改为复用平台内联选项按钮。 补充原语测试和编辑器共享样式断言,并更新 TRACKING。 --- TRACKING.md | 1 + .../PlatformInlineOptionButton.test.tsx | 46 +++++++++++++++++++ .../common/PlatformInlineOptionButton.tsx | 39 ++++++++++++++++ .../ImageCanvasEditorView.test.tsx | 12 ++++- .../image-editor/ImageCanvasEditorView.tsx | 15 +++--- src/index.css | 2 - 6 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 src/components/common/PlatformInlineOptionButton.test.tsx create mode 100644 src/components/common/PlatformInlineOptionButton.tsx diff --git a/TRACKING.md b/TRACKING.md index f11e3191..34f12248 100644 --- a/TRACKING.md +++ b/TRACKING.md @@ -100,3 +100,4 @@ - 2026-06-14 组件复用修正:编辑器生成输入框的“参考图”按钮改为复用 `PlatformIconButton variant="surfaceFloating"`,用 children 承载短标签,仅保留生成器局部尺寸和浅灰覆盖;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformIconButton.test.tsx`、`npm run typecheck`。 - 2026-06-14 组件复用修正:编辑器生成图右上角元数据角标改为复用 `PlatformIconButton asChild="spanButton"`,保留嵌套在图层按钮内的合法 DOM 结构,同时把 Enter / Space 键盘触发和 `darkMini` chrome 收口到共享组件;验证命令:`npm run test -- src/components/common/PlatformIconButton.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 - 2026-06-14 组件复用修正:编辑器画布内生成输入框和“修改图片”弹窗提示词改为复用 `PlatformTextField variant="textarea"`,删除编辑器里按标签选择器手写 textarea 基础输入 chrome 的做法,仅保留生成器局部尺寸和 Lovart 式覆盖;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformTextField.test.tsx`、`npm run typecheck`。 +- 2026-06-14 组件复用修正:新增 `PlatformInlineOptionButton`,编辑器生成输入框里的比例和模型选择 pill 改为复用平台内联选项按钮原语,删除两个局部按钮重复维护基础 inline chrome 的做法;验证命令:`npm run test -- src/components/common/PlatformInlineOptionButton.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 diff --git a/src/components/common/PlatformInlineOptionButton.test.tsx b/src/components/common/PlatformInlineOptionButton.test.tsx new file mode 100644 index 00000000..ec136ac2 --- /dev/null +++ b/src/components/common/PlatformInlineOptionButton.test.tsx @@ -0,0 +1,46 @@ +/* @vitest-environment jsdom */ + +import { fireEvent, render, screen } from '@testing-library/react'; +import { ChevronDown } from 'lucide-react'; +import { expect, test, vi } from 'vitest'; + +import { PlatformInlineOptionButton } from './PlatformInlineOptionButton'; + +test('renders shared inline option button chrome', () => { + const onClick = vi.fn(); + render( + } + onClick={onClick} + > + 1:1 + , + ); + + const button = screen.getByRole('button', { name: '生成比例 1:1' }); + + expect(button.className).toContain('platform-inline-option-button'); + expect(button.className).toContain('bg-transparent'); + expect(button.className).toContain('local-option'); + expect(button.textContent).toContain('1:1'); + + fireEvent.click(button); + + expect(onClick).toHaveBeenCalledTimes(1); +}); + +test('keeps disabled state and default button type', () => { + render( + + GPT Image + , + ); + + const button = screen.getByRole('button', { name: '模型' }); + + expect(button.getAttribute('type')).toBe('button'); + expect(button).toHaveProperty('disabled', true); + expect(button.className).toContain('disabled:cursor-not-allowed'); +}); diff --git a/src/components/common/PlatformInlineOptionButton.tsx b/src/components/common/PlatformInlineOptionButton.tsx new file mode 100644 index 00000000..96f35ee7 --- /dev/null +++ b/src/components/common/PlatformInlineOptionButton.tsx @@ -0,0 +1,39 @@ +import type { ButtonHTMLAttributes, ReactNode } from 'react'; + +type PlatformInlineOptionButtonProps = Omit< + ButtonHTMLAttributes, + 'children' +> & { + children: ReactNode; + trailingIcon?: ReactNode; +}; + +/** + * 平台内联选项按钮。 + * 统一承接工具面板里“当前选项 + 下拉箭头”这类轻量 pill 动作。 + */ +export function PlatformInlineOptionButton({ + children, + trailingIcon, + className, + type = 'button', + ...buttonProps +}: PlatformInlineOptionButtonProps) { + const actionClassName = [ + 'platform-inline-option-button inline-flex items-center justify-center border-0 bg-transparent text-sm font-black text-slate-700 transition-colors hover:text-slate-950 disabled:cursor-not-allowed disabled:opacity-55', + className, + ] + .filter(Boolean) + .join(' '); + + return ( + + ); +} diff --git a/src/components/image-editor/ImageCanvasEditorView.test.tsx b/src/components/image-editor/ImageCanvasEditorView.test.tsx index 8fb6e515..6f866f78 100644 --- a/src/components/image-editor/ImageCanvasEditorView.test.tsx +++ b/src/components/image-editor/ImageCanvasEditorView.test.tsx @@ -742,8 +742,16 @@ describe('ImageCanvasEditorView', () => { expect(generatePrompt.className).toContain( 'image-canvas-editor__generation-prompt', ); - expect(within(generateDialog).getByRole('button', { name: '生成比例 1:1 2k 1张' })).toBeTruthy(); - expect(within(generateDialog).getByRole('button', { name: '生成模型 GPT Image' })).toBeTruthy(); + expect( + within(generateDialog).getByRole('button', { + name: '生成比例 1:1 2k 1张', + }).className, + ).toContain('platform-inline-option-button'); + expect( + within(generateDialog).getByRole('button', { + name: '生成模型 GPT Image', + }).className, + ).toContain('platform-inline-option-button'); expect(within(generateDialog).getByRole('button', { name: '生成' }).className).toContain( 'platform-button', ); diff --git a/src/components/image-editor/ImageCanvasEditorView.tsx b/src/components/image-editor/ImageCanvasEditorView.tsx index 829af070..1fa0b47e 100644 --- a/src/components/image-editor/ImageCanvasEditorView.tsx +++ b/src/components/image-editor/ImageCanvasEditorView.tsx @@ -70,6 +70,7 @@ import { PlatformFloatingMenuItem, } from '../common/PlatformFloatingMenu'; import { PlatformIconButton } from '../common/PlatformIconButton'; +import { PlatformInlineOptionButton } from '../common/PlatformInlineOptionButton'; import { PlatformStatusMessage } from '../common/PlatformStatusMessage'; import { PlatformTextField } from '../common/PlatformTextField'; import { UnifiedModal } from '../common/UnifiedModal'; @@ -2816,26 +2817,24 @@ export function ImageCanvasEditorView() { } />
- - +