Files
427e7578-d7bf-49c8-aee9-2dd…/src/components/AddOption.ts
2026-04-15 01:23:33 +02:00

67 lines
1.9 KiB
TypeScript

export function AddOption(
onSubmit: (label: string) => string | null,
): HTMLElement {
const wrapper = document.createElement("div");
wrapper.className = "add-option-wrapper";
const input = document.createElement("input");
input.type = "text";
input.className = "add-option-input";
input.placeholder = "Add an option\u2026";
input.maxLength = 100;
input.setAttribute("aria-label", "New poll option");
const btn = document.createElement("button");
btn.className = "add-option-btn";
btn.setAttribute("aria-label", "Add option");
btn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M8 2v12M2 8h12" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/>
</svg>
<span>Add</span>
`;
const feedback = document.createElement("div");
feedback.className = "add-option-feedback";
feedback.setAttribute("aria-live", "polite");
wrapper.append(input, btn, feedback);
function submit() {
const name = input.value.trim();
if (!name) {
input.focus();
input.classList.add("shake");
input.addEventListener("animationend", () => input.classList.remove("shake"), { once: true });
return;
}
const error = onSubmit(name);
if (error) {
feedback.textContent = error;
feedback.style.display = "";
setTimeout(() => {
feedback.textContent = "";
feedback.style.display = "none";
}, 3000);
return;
}
input.value = "";
feedback.textContent = "";
feedback.style.display = "none";
input.focus();
}
btn.addEventListener("click", submit);
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") submit();
});
input.addEventListener("input", () => {
feedback.textContent = "";
feedback.style.display = "none";
});
return wrapper;
}