feat: optimize playground media references

This commit is contained in:
2026-05-13 22:06:13 +08:00
parent 5868dd7e68
commit 0cd4e6fed1
6 changed files with 1522 additions and 39 deletions
+436
View File
@@ -139,6 +139,442 @@
line-height: var(--line-height-relaxed);
}
.composerBodyWithReferences {
grid-template-columns: 120px minmax(0, 1fr);
align-items: start;
}
.composerBodyWithReferences[data-frame-mode="true"] {
grid-template-columns: 250px minmax(0, 1fr);
}
.mediaReferenceStack {
position: relative;
width: 108px;
min-height: 106px;
overflow: visible;
}
.mediaReferenceStack[data-expanded="true"] {
z-index: 12;
}
.mediaReferenceTooltip {
position: absolute;
z-index: 14;
top: -42px;
left: 0;
max-width: min(640px, 54vw);
overflow: hidden;
padding: 10px 14px;
border-radius: 12px;
background: #20252b;
color: #fff;
font-size: var(--font-size-sm);
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
box-shadow: 0 12px 32px rgba(24, 24, 27, 0.22);
}
.mediaReferenceStackCards {
position: relative;
width: 108px;
min-height: 104px;
transition: width 160ms ease;
}
.mediaReferenceStack[data-expanded="true"] .mediaReferenceStackCards {
width: min(calc(var(--reference-count) * 52px + 18px), calc(100vw - 96px));
}
.mediaReferenceCard {
position: absolute;
display: grid;
width: 58px;
height: 76px;
place-items: center;
overflow: visible;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface-muted);
color: var(--text-soft);
box-shadow: 0 10px 24px rgba(24, 24, 27, 0.12);
}
.mediaReferenceCard {
left: calc(24px + var(--reference-x, 0px));
top: calc(7px + var(--reference-y, 0px));
transform: rotate(var(--reference-tilt, -6deg));
transition: left 160ms ease, top 160ms ease, transform 160ms ease, z-index 150ms ease, box-shadow 150ms ease;
}
.mediaReferenceStack[data-expanded="true"] .mediaReferenceCard {
left: calc(2px + var(--reference-index) * 52px);
top: 8px;
transform: rotate(var(--reference-tilt, -4deg));
}
.mediaReferenceCard[data-hovered="true"] {
z-index: 6;
transform: translateY(-8px) scale(1.04) rotate(0deg);
box-shadow: 0 16px 36px rgba(24, 24, 27, 0.18);
}
.mediaReferenceCard img,
.mediaReferenceCard video,
.frameSlotButton video,
.frameSlotButton img {
width: 100%;
height: 100%;
overflow: hidden;
border-radius: inherit;
object-fit: cover;
}
.mediaReferencePlaceholder {
display: grid;
width: 100%;
height: 100%;
place-items: center;
overflow: hidden;
border-radius: inherit;
background: var(--surface-muted);
color: var(--primary);
}
.mediaReferenceDuration {
position: absolute;
left: 6px;
bottom: 6px;
padding: 1px 5px;
border-radius: 999px;
background: rgba(24, 24, 27, 0.66);
color: #fff;
font-size: var(--font-size-xs);
line-height: 1.35;
}
.mediaReferenceRemove,
.frameSlotRemove {
position: absolute;
z-index: 7;
display: grid;
width: 24px;
height: 24px;
place-items: center;
border: 0;
border-radius: 999px;
background: #20252b;
color: #fff;
padding: 0;
box-shadow: 0 6px 16px rgba(24, 24, 27, 0.18);
}
.mediaReferenceRemove {
top: -13px;
right: -13px;
}
.mediaReferenceUploadCard {
border-style: dashed;
box-shadow: none;
}
.mediaReferenceUploadCard span {
position: absolute;
bottom: 10px;
color: inherit;
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
}
.mediaReferenceStack:not([data-expanded="true"]) .mediaReferenceUploadCard[data-has-uploads="true"] {
opacity: 0;
pointer-events: none;
}
.mediaReferenceStack[data-expanded="true"] .mediaReferenceUploadCard,
.mediaReferenceUploadCard[data-has-uploads="false"] {
opacity: 1;
pointer-events: auto;
}
.mediaReferenceUploadCard:not(:disabled):hover {
color: var(--text-normal);
background: var(--surface);
}
.mediaReferenceUploadCard:disabled {
cursor: not-allowed;
opacity: 0.64;
}
.mediaReferenceStack:not([data-expanded="true"]) .mediaReferenceUploadCard[data-has-uploads="true"]:disabled {
opacity: 0;
}
.mediaReferenceAdd {
position: absolute;
left: 74px;
top: 61px;
z-index: 12;
display: grid;
width: 32px;
height: 32px;
place-items: center;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--surface-muted);
color: var(--text-normal);
padding: 0;
box-shadow: 0 8px 20px rgba(24, 24, 27, 0.12);
}
.mediaReferenceStack[data-expanded="true"] .mediaReferenceAdd {
opacity: 0;
pointer-events: none;
transform: scale(0.86);
}
.mediaReferenceAdd:not(:disabled):hover {
background: var(--surface);
color: var(--primary);
}
.mediaReferenceAdd:disabled {
cursor: not-allowed;
opacity: 0.64;
}
.firstLastFramePicker {
display: grid;
grid-template-columns: 86px 34px 86px;
align-items: center;
gap: 10px;
min-height: 118px;
}
.frameSlot {
position: relative;
}
.frameSlotButton {
display: grid;
width: 78px;
height: 104px;
place-items: center;
overflow: hidden;
border: 1px dashed var(--border);
border-radius: 8px;
background: var(--surface-muted);
color: var(--text-soft);
transform: rotate(-7deg);
}
.frameSlot:nth-child(3) .frameSlotButton {
transform: rotate(6deg);
}
.frameSlotButton[data-filled="true"] {
border-style: solid;
}
.frameSlotButton span {
position: absolute;
bottom: 10px;
color: inherit;
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
}
.frameSlotButton[data-filled="true"] span {
padding: 1px 6px;
border-radius: 999px;
background: rgba(24, 24, 27, 0.62);
color: #fff;
}
.frameSlotRemove {
top: -8px;
right: 0;
}
.frameSwapButton {
display: grid;
width: 34px;
height: 34px;
place-items: center;
border: 0;
border-radius: 999px;
background: transparent;
color: var(--text-soft);
}
.frameSwapButton:not(:disabled):hover {
background: var(--surface-muted);
color: var(--text-normal);
}
.frameSwapButton:disabled {
opacity: 0.42;
}
.promptMentionInput {
position: relative;
min-width: 0;
}
.promptMentionEditable {
position: relative;
z-index: 1;
min-height: 88px;
max-height: 190px;
overflow-y: auto;
border: 0;
outline: 0;
background: transparent;
color: var(--text-normal);
font: inherit;
font-size: var(--font-size-sm);
line-height: var(--line-height-relaxed);
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.promptMentionPlaceholder {
position: absolute;
z-index: 0;
top: 0;
left: 0;
right: 0;
overflow: hidden;
color: var(--muted-foreground);
font: inherit;
font-size: var(--font-size-sm);
line-height: var(--line-height-relaxed);
pointer-events: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.playgroundComposer.compact .promptMentionEditable {
min-height: 104px;
}
.promptMentionChip {
display: inline-flex;
max-width: min(260px, 80%);
align-items: center;
gap: 5px;
margin: 0 4px 2px 0;
padding: 2px 6px 2px 2px;
border-radius: 7px;
background: var(--primary);
color: var(--primary-foreground);
font-size: var(--font-size-xs);
line-height: 1.55;
vertical-align: middle;
}
.promptMentionChipThumb {
display: inline-grid;
width: 22px;
height: 22px;
min-width: 22px;
place-items: center;
overflow: hidden;
border-radius: 5px;
object-fit: cover;
background: rgba(255, 255, 255, 0.18);
}
.promptMentionChipThumbPlaceholder {
font-weight: var(--font-weight-semibold);
}
.promptMentionDropdown {
position: absolute;
z-index: 20;
width: min(320px, calc(100vw - 24px));
max-height: 286px;
overflow-y: auto;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
box-shadow: 0 18px 42px rgba(24, 24, 27, 0.16);
}
.promptMentionItem {
display: grid;
grid-template-columns: 36px minmax(0, 1fr) auto;
width: 100%;
align-items: center;
gap: 10px;
min-height: 54px;
padding: 8px 10px;
border: 0;
background: transparent;
color: var(--text-normal);
text-align: left;
}
.promptMentionItem:hover,
.promptMentionItem[data-active="true"] {
background: var(--surface-muted);
}
.promptMentionThumb,
.promptMentionThumbIcon {
display: grid;
width: 36px;
height: 36px;
place-items: center;
border-radius: 8px;
background: var(--surface-muted);
color: var(--primary);
object-fit: cover;
}
.promptMentionItem span {
display: grid;
min-width: 0;
gap: 2px;
}
.promptMentionItem strong,
.promptMentionItem small {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.promptMentionItem strong {
color: var(--text-strong);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
}
.promptMentionItem small {
color: var(--muted-foreground);
font-size: var(--font-size-xs);
}
.promptMentionItem em {
padding: 2px 6px;
border-radius: 999px;
background: var(--surface-muted);
color: var(--text-soft);
font-size: var(--font-size-xs);
font-style: normal;
}
.promptMentionEmpty {
padding: 12px;
color: var(--muted-foreground);
font-size: var(--font-size-sm);
}
@keyframes composer-upload-spin {
to {
transform: rotate(360deg);