WEBLEB
Home
Editor
Login
Pro
English
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Idea Form
1467
Andev.web
Open In Editor
Publish Your Code
Recommended
28 August 2024
Parallax scroll animation
14 October 2023
Card Dashboard
13 June 2025
egg toasting loading
HTML
Copy
Andev Web
I have an idea
Idea
Submit
CSS
Copy
* { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 53; --bg: hsl(var(--hue),10%,90%); --fg: hsl(var(--hue),10%,10%); --primary: hsl(var(--hue),90%,50%); --trans-dur: 0.3s; --trans-timing1: cubic-bezier(0.65,0,0.35,1); --trans-timing2: cubic-bezier(0.65,0,0.35,1.35); font-size: calc(14px + (30 - 14) * (100vw - 280px) / (3840 - 280)); } body, button, textarea { font: 1em/1.5 Montserrat, sans-serif; } body { background-color: var(--bg); color: var(--fg); display: flex; height: 100vh; transition: background-color var(--trans-dur), color var(--trans-dur); } .idea-form { background-color: black; color: white; margin: auto; overflow: hidden; position: relative; width: 16.5em; height: 4.5em; transition: background-color var(--trans-dur), color var(--trans-dur), height var(--trans-dur) var(--trans-timing2); } .idea-form, .idea-form__btn, .idea-form__content { border-radius: 1.5em; } .idea-form, .idea-form__btn { position: relative; } .idea-form__btn, .idea-form__textarea { outline: transparent; transition: background-color var(--trans-dur), box-shadow var(--trans-dur), opacity var(--trans-dur) var(--trans-timing1); -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; } .idea-form__btn:disabled, .idea-form__textarea:disabled { cursor: not-allowed; opacity: 0.3; } .idea-form__btn { background-color: black; box-shadow: 0 0 0 0.25em hsla(var(--hue), 90%, 30%, 0); color: white; cursor: pointer; display: flex; margin-inline-start: auto; padding: 0.5em 1em; z-index: 2; } .idea-form__btn--start { background-color: transparent; box-shadow: none; color: currentColor; display: flex; align-items: center; letter-spacing: 0.0625em; padding-inline-start: 5.25em; width: 100%; height: 4.5em; text-transform: uppercase; transition: opacity var(--trans-dur) var(--trans-timing1), visibility var(--trans-dur) steps(1, start); } .idea-form__btn:focus-visible { box-shadow: 0 0 0 0.25em hsla(var(--hue), 90%, 30%, 1); } .idea-form__content { opacity: 0; padding: 1.5em 1em 0.75em; padding-inline-start: 5.25em; position: absolute; top: 0; left: 0; visibility: hidden; transition: opacity var(--trans-dur) var(--trans-timing1), visibility var(--trans-dur) steps(1, end); } .idea-form__fill, .idea-form__icon, .idea-form__label { position: absolute; } .idea-form__fill { background-color: hsl(var(--hue), 90%, 50%); border-radius: 50%; top: 1.75em; left: 2em; width: 1em; height: 1em; transform: translateY(50%) scale(0); transition: transform var(--trans-dur) var(--trans-timing1); } [dir=rtl] .idea-form__fill { right: 2em; left: auto; } .idea-form__btn--start:focus-visible { box-shadow: none; } .idea-form__btn--start:focus-visible + .idea-form__fill, .idea-form__btn--start:hover + .idea-form__fill { transform: translateY(0) scale(1); } .idea-form__icon { color: currentColor; display: block; top: 0.75em; left: 1em; width: 3em; height: 3em; z-index: 1; } [dir=rtl] .idea-form__icon { right: 1em; left: auto; } .idea-form__label { overflow: hidden; width: 1px; height: 1px; } .idea-form__textarea { background-color: transparent; color: black; display: block; margin-bottom: 0.75em; resize: none; width: 100%; height: 3em; } .idea-form__textarea::placeholder { color: hsl(var(--hue), 10%, 50%); } .idea-form[data-expanded=true] { background-color: transparent; height: 8.5em; transition-timing-function: steps(1, end), ease, var(--trans-timing2); } .idea-form[data-expanded=true] .idea-form__btn--start { opacity: 0; pointer-events: none; transition-timing-function: var(--trans-timing1), steps(1, end); visibility: hidden; } .idea-form[data-expanded=true] .idea-form__content { opacity: 1; transition-timing-function: var(--trans-timing1), steps(1, start); visibility: visible; } .idea-form[data-expanded=true] .idea-form__fill { transform: translateY(0) scale(32); } /* Dark theme */ @media (prefers-color-scheme: dark) { :root { --bg: hsl(var(--hue),10%,10%); --fg: hsl(var(--hue),10%,90%); } .idea-form { background-color: white; color: black; } }
JS
Copy
"use strict"; window.addEventListener("DOMContentLoaded", () => { const ideaForm = new IdeaForm("#idea"); }); class IdeaForm { /** * @param el CSS selector of the form */ constructor(el) { var _a, _b, _c; /** Timeout function for submission */ this.timeout = 0; this._idea = ""; this._expanded = false; this._state = SubmitState.Default; this.form = document.querySelector(el); (_a = this.form) === null || _a === void 0 ? void 0 : _a.addEventListener("click", this.toggle.bind(this)); (_b = this.form) === null || _b === void 0 ? void 0 : _b.addEventListener("input", this.ideaUpdate.bind(this)); (_c = this.form) === null || _c === void 0 ? void 0 : _c.addEventListener("submit", this.ideaSubmit.bind(this)); document.addEventListener("click", this.outsideToCollapse.bind(this)); document.addEventListener("keydown", this.escToCollapse.bind(this)); } get idea() { return this._idea; } set idea(value) { var _a; this._idea = value; const submitBtn = (_a = this.form) === null || _a === void 0 ? void 0 : _a.querySelector("[type=submit]"); if (submitBtn) { submitBtn.disabled = value.length === 0; } } get expanded() { return this._expanded; } set expanded(value) { var _a; this._expanded = value; (_a = this.form) === null || _a === void 0 ? void 0 : _a.setAttribute("data-expanded", `${value}`); } get state() { return this._state; } set state(value) { var _a, _b; this._state = value; const textarea = (_a = this.form) === null || _a === void 0 ? void 0 : _a.querySelector("#my-idea"); const submitBtn = (_b = this.form) === null || _b === void 0 ? void 0 : _b.querySelector("[type=submit]"); if (textarea) { textarea.disabled = value !== SubmitState.Default; } if (submitBtn) { if (value === SubmitState.Sending) { submitBtn.textContent = Label.Sending; submitBtn.disabled = true; } else if (value === SubmitState.Done) { submitBtn.textContent = Label.Sent; } else { submitBtn.textContent = Label.Submit; } } } /** * Click outside the form to collapse. * @param e Click event * */ outsideToCollapse(e) { if (this.state !== SubmitState.Default) return; let parent = e.target; while (parent !== null) { if (parent === this.form) { return; } parent = parent.parentElement; } this.expanded = false; } /** * Hide the form by pressing Esc. * @param e Keyboard event * */ escToCollapse(e) { if (e.code === "Escape" && this.state === SubmitState.Default) { this.expanded = false; } } /** * Show or hide the form. * @param e Click event * */ toggle(e) { var _a; const button = e.target; if (button.hasAttribute("data-toggle")) { this.expanded = !this.expanded; if (this.expanded) { const textarea = (_a = this.form) === null || _a === void 0 ? void 0 : _a.querySelector("#my-idea"); textarea === null || textarea === void 0 ? void 0 : textarea.focus(); } } } /** * Submit the idea content. * @param e Submit event * */ async ideaSubmit(e) { e.preventDefault(); if (this.state !== SubmitState.Default) return; const delaySending = 1000; const delayDone = 600; const delayReset = 300; this.state = SubmitState.Sending; return await new Promise(resolve => { // send clearTimeout(this.timeout); this.timeout = setTimeout(() => { resolve(); }, delaySending); }).then(async () => { // submitted this.state = SubmitState.Done; return await new Promise(resolve => { clearTimeout(this.timeout); this.timeout = setTimeout(() => { resolve(); }, delayDone); }); }).then(() => { // collapse and reset this.expanded = false; clearTimeout(this.timeout); this.timeout = setTimeout(() => { var _a; (_a = this.form) === null || _a === void 0 ? void 0 : _a.reset(); this.idea = ""; this.state = SubmitState.Default; }, delayReset); }); } /** * Update the idea content internally. * @param e Input event * */ ideaUpdate(e) { const textarea = e.target; this.idea = textarea.value; } } var Label; (function (Label) { Label["Sending"] = "Sending\u2026"; Label["Sent"] = "Sent"; Label["Submit"] = "Submit"; })(Label || (Label = {})); var SubmitState; (function (SubmitState) { SubmitState[SubmitState["Default"] = 0] = "Default"; SubmitState[SubmitState["Sending"] = 1] = "Sending"; SubmitState[SubmitState["Done"] = 2] = "Done"; })(SubmitState || (SubmitState = {}));