fix(canvas): adapt composer controls to panel width and remove reference placeholder

This commit is contained in:
134 2026-10-21 08:54:58 +08:00
parent 98f5812b90
commit 281174d787
3 changed files with 35 additions and 50 deletions

View File

@ -630,6 +630,32 @@
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-composer-mode="image"] .lovart-composer-footer > div:last-child { flex: 1 1 0; min-width: 0; gap: 0; }
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-composer-mode="image"] .lovart-composer-send { min-width: 32px; width: auto; height: 32px; padding: 0 8px; gap: 2px; font-size: 13px; font-weight: 400; }
/* Adapt to the resizable chat panel, independently of the browser width. */
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] { container: canvas-composer / inline-size; }
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-composer-footer { gap: 4px; }
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-composer-footer > div:first-child { flex: 0 0 auto; overflow: visible; padding-right: 0; }
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-composer-footer > div:last-child { flex: 0 1 auto; min-width: 0; }
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-composer-mode-selector { width: auto; max-width: none; }
.lovart-image-params-icon { display: none; }
@container canvas-composer (max-width: 480px) {
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-composer-mode-selector { width: 32px; min-width: 32px; padding: 0; }
.lovart-composer-mode-selector .lovart-composer-mode-label,
.lovart-composer-mode-selector [data-reference-icon="chevron-down"] { display: none; }
.lovart-composer-mode-selector > span > :first-child { margin-right: 0; }
}
@container canvas-composer (max-width: 360px) {
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-model-selector { flex: 0 0 32px; width: 32px; padding: 0; justify-content: center; }
.lovart-model-selector > span:not([data-reference-icon]),
.lovart-model-selector > [data-reference-icon="chevron-down"] { display: none; }
.lovart-canvas-surface [data-lovart-chat="true"] .lovart-model-selector > [data-reference-icon]:first-child { margin-right: 0; }
}
@container canvas-composer (max-width: 280px) {
.lovart-canvas-surface [data-lovart-chat="true"] [data-canvas-responsive-composer="true"] .lovart-image-params { width: 32px; min-width: 32px; padding: 0; justify-content: center; }
.lovart-image-params .lovart-image-params-icon { display: block; }
.lovart-image-params .lovart-image-params-label,
.lovart-image-params > [data-reference-icon="chevron-down"] { display: none; }
}
/* The existing image toolbar is scaled to 80%; these dimensions render at
the reference's 44px bar, 32px buttons, and 20px icons. */
.lovart-image-action-bar {

View File

@ -14824,10 +14824,6 @@ export function CanvasChatPanel({
const isComposerUploading = Boolean(composerUploadProgress);
const isSubmitting =
isActiveChatPending || isDetailGenerating || isClawdSubmitting || isComposerUploading;
const composerReferenceUploadProgress =
composerUploadProgress?.target === "composer-reference"
? composerUploadProgress
: null;
const hasInputOrAttachments = Boolean(
input.trim() || attachments.length > 0 || (!isDetailGenerationMode && selectedSkillTag)
);
@ -17222,6 +17218,7 @@ export function CanvasChatPanel({
)}
data-canvas-chat-input-anchor="true"
data-canvas-composer-mode={activeComposerMode}
data-canvas-responsive-composer={!isWorkspacePresentation && !isVideoWorkspace && !isDetailGenerationMode ? "true" : undefined}
>
{isWorkspacePresentation && !isDetailGenerationMode ? (
<div className="border-b px-5 py-3">
@ -18310,49 +18307,7 @@ export function CanvasChatPanel({
) : null}
</div>
) : null}
{!isWorkspacePresentation && !isDetailGenerationMode && !isVideoWorkspace && (activeComposerMode === "image" || isImageAgentComposer) ? (
<div className="lovart-reference-upload mx-[8px] mt-[8px] flex items-center">
<button
type="button"
className="lovart-reference-tile relative flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full border border-dashed border-[#d9dde4] bg-[#f3f3f4] text-[#8f97a3] transition-colors hover:border-[#c6ccd6] hover:bg-[#ececee] hover:text-[#20242a] disabled:cursor-not-allowed disabled:opacity-60 dark:border-white/12 dark:bg-white/8 dark:text-zinc-400 dark:hover:border-white/20 dark:hover:bg-white/12 dark:hover:text-white"
onClick={() => fileInputRef.current?.click()}
disabled={isSubmitting}
title={supportsAtlasVideoReference ? "添加图片或参考视频" : "添加图片"}
aria-label={supportsAtlasVideoReference ? "添加图片或参考视频" : "添加图片"}
>
<ReferenceIcon name="reference-image" size={16} />
<span>参考图</span>
{composerReferenceUploadProgress ? (
<div className="absolute inset-0 flex items-center justify-center bg-black/70 text-white backdrop-blur-[1px]">
<span className="text-[10px] font-semibold leading-none tabular-nums">
{Math.max(
1,
Math.min(
100,
Math.round(composerReferenceUploadProgress.percent || 1)
)
)}
%
</span>
<span className="absolute inset-x-1 bottom-1 h-0.5 overflow-hidden rounded-full bg-white/20">
<span
className="block h-full rounded-full bg-[#e0ff3a] transition-all duration-300"
style={{
width: `${Math.max(
1,
Math.min(
100,
Math.round(composerReferenceUploadProgress.percent || 1)
)
)}%`,
}}
/>
</span>
</div>
) : null}
</button>
</div>
) : null}
{isClawdMode && clawdTableFiles.length > 0 ? (
<div className="mx-4 mt-3 flex flex-wrap gap-2">
{clawdTableFiles.map((file, index) => (
@ -18685,7 +18640,7 @@ export function CanvasChatPanel({
}}
/>
))}
{!isWorkspacePresentation && !isDetailGenerationMode && activeComposerMode !== "image" && (isClawdMode || !isVideoModel || showVideoAttachmentButton) && (
{!isWorkspacePresentation && !isDetailGenerationMode && (isClawdMode || !isVideoModel || showVideoAttachmentButton) && (
isClawdMode ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
@ -18763,6 +18718,8 @@ export function CanvasChatPanel({
? "bg-[#242529] text-zinc-100 hover:bg-[#2c2d33]"
: "bg-[#eeeeef] text-[#20242a] hover:bg-[#e7e7e8] dark:bg-white/10 dark:text-zinc-100 dark:hover:bg-white/14"
)}
title={activeModeLabel}
aria-label={`切换模式,当前为 ${activeModeLabel}`}
>
<span className="flex min-w-0 items-center">
{activeComposerMode === "clawd" ? (
@ -18794,7 +18751,7 @@ export function CanvasChatPanel({
item={null}
/>
)}
<span className="min-w-0 truncate">{activeModeLabel}</span>
<span className="lovart-composer-mode-label min-w-0 truncate">{activeModeLabel}</span>
{!isWorkspacePresentation && !isVideoWorkspace ? (
<ReferenceIcon name="chevron-down" size={18} className={cn("ml-1.5", isComposerModeMenuOpen && "rotate-180")} />
) : isComposerModeMenuOpen ? (

View File

@ -498,8 +498,10 @@ export function ImageParamsBar({
variant="ghost"
className={cn("h-8 shrink-0 rounded-full bg-[#f1f1f2] px-2.5 text-[13px] font-normal text-[#20242a] hover:bg-[#e9eaec] focus-visible:ring-0 focus-visible:ring-offset-0 dark:bg-[#242529] dark:text-zinc-100 dark:hover:bg-[#2c2d33]", referencePresentation && "lovart-image-params")}
title="生成参数"
aria-label="生成参数"
>
<span className={referencePresentation ? "min-w-0 truncate text-[13px]" : undefined}>{qualityLabel} · {selectedAspectLabel} · {selectedImageCount} {referencePresentation ? "张" : "img"}</span>
{referencePresentation ? <SlidersHorizontal className="lovart-image-params-icon h-4 w-4 shrink-0" aria-hidden="true" /> : null}
<span className={referencePresentation ? "lovart-image-params-label min-w-0 truncate text-[13px]" : undefined}>{qualityLabel} · {selectedAspectLabel} · {selectedImageCount} {referencePresentation ? "张" : "img"}</span>
{referencePresentation ? <ReferenceIcon name="chevron-down" size={18} className={minimalParamsOpen ? "rotate-180" : undefined} /> : minimalParamsOpen ? (
<ChevronUp className="ml-1 h-3 w-3" />
) : (