统一图标生成中占位动画

限制图标生成器装饰样式只作用于非生成中占位框

恢复图标生成中占位框的共享扫描动画和缩放样式

补充图标生成中动画级联回归测试
This commit is contained in:
2026-06-27 17:30:37 +08:00
parent 8324911bbb
commit 1c5310a0bc
4 changed files with 74 additions and 7 deletions
@@ -757,6 +757,29 @@ describe('ImageCanvasWorldView', () => {
).toBe('');
});
it('uses the shared generating icon scale for icon placeholders', () => {
const dialog = createGenerationDialog({
id: 'dialog-icon-generating-scale',
mode: 'icon',
status: 'generating',
});
renderWorldView({
viewport: { x: 0, y: 0, scale: 0.25 },
canvasGenerationDialogs: [dialog],
generateDialog: dialog,
});
const frame = screen.getByRole('button', { name: '图标素材生成占位图' });
const iconTile = frame.querySelector(
'.image-canvas-editor__generation-frame-icon',
) as HTMLElement;
expect(
iconTile.style.getPropertyValue('--image-canvas-editor-inverse-scale'),
).toBe('4');
});
it('uses a plain information icon for metadata corner actions', () => {
const layer = createLayer();
const { props } = renderWorldView({ layers: [layer] });
@@ -1290,7 +1290,11 @@ export function ImageCanvasWorldView({
) : null}
<span
className="image-canvas-editor__generation-frame-icon"
style={dialog.mode === 'icon' ? undefined : inverseScaleStyle}
style={
dialog.mode === 'icon' && dialog.status !== 'generating'
? undefined
: inverseScaleStyle
}
>
{placeholderMeta.icon}
</span>
+18 -6
View File
@@ -5801,7 +5801,9 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
}
}
.image-canvas-editor__generation-frame--icon {
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
) {
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.72),
@@ -5814,8 +5816,12 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
border-color: #10b981;
}
.image-canvas-editor__generation-frame--icon::before,
.image-canvas-editor__generation-frame--icon::after {
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
)::before,
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
)::after {
content: '';
position: absolute;
width: 42%;
@@ -5826,15 +5832,21 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
box-shadow: 0 12px 24px rgba(15, 118, 110, 0.12);
}
.image-canvas-editor__generation-frame--icon::before {
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
)::before {
transform: translate(-20%, -8%) rotate(-8deg);
}
.image-canvas-editor__generation-frame--icon::after {
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
)::after {
transform: translate(18%, 10%) rotate(7deg);
}
.image-canvas-editor__generation-frame--icon
.image-canvas-editor__generation-frame--icon:not(
.image-canvas-editor__generation-frame--generating
)
.image-canvas-editor__generation-frame-icon {
position: relative;
z-index: 1;
+28
View File
@@ -31,6 +31,34 @@ function getCssBlock(source: string, selector: string) {
}
describe('index stylesheet unread dots', () => {
it('keeps icon generator decoration from overriding the shared generating animation', () => {
const css = readIndexCss();
const generatingBlock = getCssBlock(
css,
'.image-canvas-editor__generation-frame--generating',
);
const generatingScanBlock = getCssBlock(
css,
'.image-canvas-editor__generation-frame--generating::before',
);
const iconBlock = getCssBlock(
css,
'.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )',
);
const iconDecorationBlock = getCssBlock(
css,
'.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )::before,\n.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )::after',
);
expect(generatingBlock).toContain('cursor: progress;');
expect(generatingScanBlock).toContain('animation: image-canvas-generation-scan');
expect(iconBlock).toContain('background: linear-gradient(');
expect(iconDecorationBlock).toContain('width: 42%;');
expect(css).not.toContain(
'.image-canvas-editor__generation-frame--icon::before,\n.image-canvas-editor__generation-frame--icon::after',
);
});
it('keeps image canvas loading shimmer clipped inside media frames', () => {
const css = readIndexCss();
const loadingBlock = getCssBlock(