WEBLEB
Accueil
Éditeur
Connexion
Pro
Français
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Formulaire d'idée
1066
Andev.web
Ouvrir dans l'éditeur
Publiez votre code
Recommandé
16 November 2024
Comment créer une barre latérale de grille en CSS
21 October 2024
Erreur 403
29 October 2024
Le système solaire
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 = {}));