Unify media preview loading background

This commit is contained in:
wangbo 2026-05-14 23:42:12 +08:00
parent c0cfae475d
commit a4f731af88
2 changed files with 38 additions and 3 deletions

View File

@ -521,6 +521,7 @@ function MediaTaskCard(props: {
const references = mediaReferenceItems(props.run);
const promptParts = promptDisplayParts(props.run.prompt, references);
const taskMeta = mediaTaskMetaText(props.run);
const previewState = items.length > 0 ? 'filled' : isPending ? 'loading' : 'empty';
return (
<article className="mediaTaskItem" data-status={props.run.status}>
@ -552,9 +553,9 @@ function MediaTaskCard(props: {
</div>
)}
<div className="mediaPreviewStage" data-count={expectedCount}>
<div className="mediaPreviewStage" data-count={expectedCount} data-preview-state={previewState}>
{backdropItem && <img aria-hidden="true" className="mediaPreviewBackdrop" src={backdropItem.src} alt="" />}
<div className="mediaGrid" data-count={expectedCount} style={style}>
<div className="mediaGrid" data-count={expectedCount} data-preview-state={previewState} style={style}>
{Array.from({ length: expectedCount }).map((_, index) => (
<MediaTile
expectedCount={expectedCount}
@ -660,7 +661,7 @@ function MediaTile(props: {
const isLoading = props.status === 'submitting' || props.status === 'queued' || props.status === 'running';
const isFailed = props.status === 'failed' || props.status === 'cancelled';
return (
<div className="mediaTile" data-count={props.expectedCount} data-empty={!props.item && !isLoading} data-kind={props.mode}>
<div className="mediaTile" data-count={props.expectedCount} data-empty={!props.item && !isLoading} data-kind={props.mode} data-placeholder={!props.item}>
{props.item?.type === 'video' && (
<video controls muted playsInline poster={props.item.poster}>
<source src={props.item.src} />

View File

@ -2115,6 +2115,15 @@
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.86);
}
.mediaPreviewStage[data-count="1"][data-preview-state="loading"] {
background:
linear-gradient(110deg, rgba(237, 240, 242, 0.92) 0%, rgba(247, 248, 249, 0.94) 42%, rgba(230, 234, 238, 0.88) 78%),
repeating-linear-gradient(90deg, rgba(15, 23, 42, 0.035) 0 1px, transparent 1px 28px),
repeating-linear-gradient(0deg, rgba(15, 23, 42, 0.03) 0 1px, transparent 1px 28px);
background-size: 220% 100%, auto, auto;
animation: mediaLoadingShimmer 1.35s ease-in-out infinite;
}
.mediaPreviewStage[data-count="1"]::after {
position: absolute;
inset: 0;
@ -2148,6 +2157,14 @@
overflow: visible;
}
.mediaPreviewStage[data-count="1"][data-preview-state="loading"] .mediaGrid,
.mediaPreviewStage[data-count="1"][data-preview-state="empty"] .mediaGrid {
width: 100%;
max-width: none;
height: 100%;
align-self: stretch;
}
.mediaTile {
position: relative;
display: grid;
@ -2166,6 +2183,14 @@
box-shadow: 0 18px 44px rgba(15, 23, 42, 0.14);
}
.mediaPreviewStage[data-count="1"] .mediaTile[data-placeholder="true"] {
width: 100%;
min-height: min(62vh, 600px);
border-radius: inherit;
background: transparent;
box-shadow: none;
}
.mediaTile[data-count="2"] {
min-height: min(48vh, 520px);
}
@ -2205,6 +2230,15 @@
background: #eef0f2;
}
.mediaPreviewStage[data-count="1"] .mediaTile[data-placeholder="true"] .mediaLoading,
.mediaPreviewStage[data-count="1"] .mediaTile[data-placeholder="true"] .mediaEmptyTile {
background: transparent;
}
.mediaPreviewStage[data-count="1"] .mediaTile[data-placeholder="true"] .mediaLoading {
animation: none;
}
.mediaTaskError {
display: grid;
gap: 4px;