Add inline previews for prompt attachments

This commit is contained in:
Shantur Rathore
2025-11-19 18:49:50 +00:00
parent 45dca7a7f0
commit d3ee15dcd7
2 changed files with 53 additions and 3 deletions

View File

@@ -720,8 +720,24 @@ export default function PromptInput(props: PromptInputProps) {
const filename = file.name
const mime = file.type || "text/plain"
const attachment = createFileAttachment(path, filename, mime, undefined, props.instanceFolder)
addAttachment(props.instanceId, props.sessionId, attachment)
const createAndStoreAttachment = (previewUrl?: string) => {
const attachment = createFileAttachment(path, filename, mime, undefined, props.instanceFolder)
if (previewUrl && mime.startsWith("image/")) {
attachment.url = previewUrl
}
addAttachment(props.instanceId, props.sessionId, attachment)
}
if (mime.startsWith("image/") && typeof FileReader !== "undefined") {
const reader = new FileReader()
reader.onload = () => {
const result = typeof reader.result === "string" ? reader.result : undefined
createAndStoreAttachment(result)
}
reader.readAsDataURL(file)
} else {
createAndStoreAttachment()
}
}
textareaRef?.focus()
@@ -772,7 +788,7 @@ export default function PromptInput(props: PromptInputProps) {
{(attachment) => {
const isImage = attachment.mediaType.startsWith("image/")
return (
<div class="attachment-chip">
<div class={`attachment-chip ${isImage ? "attachment-chip-image" : ""}`}>
<Show
when={isImage}
fallback={
@@ -831,6 +847,11 @@ export default function PromptInput(props: PromptInputProps) {
/>
</svg>
</button>
<Show when={isImage}>
<div class="attachment-chip-preview">
<img src={attachment.url} alt={attachment.filename} />
</div>
</Show>
</div>
)
}}

View File

@@ -103,6 +103,35 @@
ring-color: var(--attachment-chip-ring);
}
.attachment-chip-image {
position: relative;
}
.attachment-chip-preview {
display: none;
position: absolute;
bottom: calc(100% + 6px);
left: 0;
padding: 8px;
background-color: var(--surface-base);
border: 1px solid var(--border-base);
border-radius: 10px;
box-shadow: 0 16px 40px rgba(15, 23, 42, 0.25);
z-index: 20;
}
.attachment-chip-preview img {
display: block;
max-width: 320px;
max-height: 320px;
border-radius: 8px;
object-fit: contain;
}
.attachment-chip-image:hover .attachment-chip-preview {
display: block;
}
.attachment-remove {
@apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors;
}