WEBLEB
Inicio
Editora de código
Iniciar sesión
Pro
Español
English
Français
Español
Forma de idea
2,431
Andev.web
Abrir en el editor
Publica tu código
1
Recomendado
24 November 2025
GTA
22 August 2025
Comentario de marcador de posición de código HTML
22 November 2025
Formulario de inicio de sesión de Liquid Glass HTML CSS
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 = {}));