Streamline admin reply composer

This commit is contained in:
rajchales-monito
2026-07-24 10:59:56 +02:00
parent f63fb539d6
commit e1d213186c
3 changed files with 69 additions and 34 deletions
+33 -13
View File
@@ -487,24 +487,44 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
background: white; background: white;
border-top: 1px solid var(--line); border-top: 1px solid var(--line);
} }
.reply.dragging {
box-shadow: inset 0 0 0 2px var(--brand);
background: #edf8f3;
}
.reply-composer { .reply-composer {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) 44px 48px;
gap: 10px; gap: 8px;
align-items: stretch;
} }
.admin-dropzone { .reply-composer textarea { min-height: 72px; resize: vertical; }
min-height: 38px; .reply-icon-button {
border: 1px dashed var(--line); min-height: 72px;
border-radius: 8px; width: 100%;
padding: 8px 10px; display: grid;
display: flex; place-items: center;
align-items: center; border-radius: 6px;
color: var(--muted); padding: 0;
background: #f8fbf9;
cursor: pointer; cursor: pointer;
} }
.admin-dropzone.dragging { border-color: var(--brand); background: #edf8f3; color: var(--ink); } .reply-icon-button svg {
.admin-dropzone input { display: none; } width: 21px;
height: 21px;
fill: currentColor;
}
.attach-button {
border: 1px solid var(--line);
background: #f8fbf9;
color: var(--muted);
}
.attach-button:hover { background: #edf3ef; color: var(--ink); }
.attach-button input { display: none; }
.send-button {
border: 0;
background: var(--brand);
color: white;
}
.send-button svg { transform: translateX(1px); }
.reply-attachments { .reply-attachments {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
+10 -4
View File
@@ -58,12 +58,18 @@
<form id="replyForm" class="reply hidden"> <form id="replyForm" class="reply hidden">
<div class="reply-composer"> <div class="reply-composer">
<textarea name="message" rows="3" placeholder="Napsat odpoved..."></textarea> <textarea name="message" rows="3" placeholder="Napsat odpoved..."></textarea>
<button type="submit" title="Odeslat">Odeslat</button> <label class="reply-icon-button attach-button" title="Pridat fotku" aria-label="Pridat fotku">
</div>
<label class="admin-dropzone" tabindex="0">
<input name="attachments" type="file" accept=".jpg,.jpeg,.png,.webp,.gif,.avif,image/jpeg,image/png,image/webp,image/gif,image/avif" multiple> <input name="attachments" type="file" accept=".jpg,.jpeg,.png,.webp,.gif,.avif,image/jpeg,image/png,image/webp,image/gif,image/avif" multiple>
<span>Pridat fotky nebo pretahnout</span> <svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M7.5 18.5a5 5 0 0 1 0-7.1l7.7-7.7a3.5 3.5 0 0 1 5 5l-8.4 8.4a2.1 2.1 0 0 1-3-3l7.8-7.8 1.4 1.4-7.8 7.8a.1.1 0 0 0 .1.1l8.4-8.4a1.5 1.5 0 0 0-2.1-2.1l-7.7 7.7a3 3 0 0 0 4.2 4.2l7.5-7.5 1.4 1.4-7.5 7.5a5 5 0 0 1-7 0Z"></path>
</svg>
</label> </label>
<button class="reply-icon-button send-button" type="submit" title="Odeslat" aria-label="Odeslat">
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M3.7 20.3 21 12 3.7 3.7l2.5 7.1L14 12l-7.8 1.2-2.5 7.1Z"></path>
</svg>
</button>
</div>
<div id="replyAttachments" class="reply-attachments"></div> <div id="replyAttachments" class="reply-attachments"></div>
</form> </form>
</section> </section>
+25 -16
View File
@@ -119,35 +119,39 @@ $("#replyForm textarea").addEventListener("input", debounce(() => {
}, 600)); }, 600));
$("#replyForm input[name='attachments']").addEventListener("change", (event) => { $("#replyForm input[name='attachments']").addEventListener("change", (event) => {
state.replyFiles = mergeImageFiles(state.replyFiles, [...event.target.files]); addReplyFiles([...event.target.files]);
event.target.value = ""; event.target.value = "";
renderReplyAttachments();
});
$(".admin-dropzone").addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
$("#replyForm input[name='attachments']").click();
}
}); });
for (const eventName of ["dragenter", "dragover"]) { for (const eventName of ["dragenter", "dragover"]) {
$(".admin-dropzone").addEventListener(eventName, (event) => { $(".conversation").addEventListener(eventName, (event) => {
event.preventDefault(); event.preventDefault();
$(".admin-dropzone").classList.add("dragging"); if (!state.activeId) return;
$("#replyForm").classList.add("dragging");
}); });
} }
for (const eventName of ["dragleave", "drop"]) { for (const eventName of ["dragleave", "drop"]) {
$(".admin-dropzone").addEventListener(eventName, (event) => { $(".conversation").addEventListener(eventName, (event) => {
event.preventDefault(); event.preventDefault();
$(".admin-dropzone").classList.remove("dragging"); $("#replyForm").classList.remove("dragging");
}); });
} }
$(".admin-dropzone").addEventListener("drop", (event) => { $(".conversation").addEventListener("drop", (event) => {
state.replyFiles = mergeImageFiles(state.replyFiles, [...event.dataTransfer.files]); if (!state.activeId) return;
renderReplyAttachments(); addReplyFiles([...event.dataTransfer.files]);
});
$(".conversation").addEventListener("paste", (event) => {
if (!state.activeId) return;
const files = [...event.clipboardData?.items || []]
.filter((item) => item.kind === "file")
.map((item) => item.getAsFile())
.filter(Boolean);
if (!files.length) return;
event.preventDefault();
addReplyFiles(files);
}); });
$("#replyAttachments").addEventListener("click", (event) => { $("#replyAttachments").addEventListener("click", (event) => {
@@ -458,6 +462,11 @@ function renderReplyAttachments() {
`).join(""); `).join("");
} }
function addReplyFiles(files) {
state.replyFiles = mergeImageFiles(state.replyFiles, files);
renderReplyAttachments();
}
function clearReplyComposer(form = $("#replyForm")) { function clearReplyComposer(form = $("#replyForm")) {
const textarea = form?.querySelector("textarea[name='message']"); const textarea = form?.querySelector("textarea[name='message']");
if (!textarea) return; if (!textarea) return;