diff --git a/app/static/css/app.css b/app/static/css/app.css index d7df05f..a69b235 100644 --- a/app/static/css/app.css +++ b/app/static/css/app.css @@ -2208,3 +2208,113 @@ html.sidebar-open { } .sidebar-tag-item .sidebar-icon { font-size: 14px; } + +/* ── Advanced Settings (collapsible, inside password modal) ─────────── */ + +.adv-section { + border: 1px solid var(--color-border); + border-radius: var(--radius); + overflow: hidden; + margin-top: 4px; + margin-bottom: 8px; + background: var(--color-surface); +} + +.adv-section-header { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + padding: 11px 14px; + background: none; + border: none; + cursor: pointer; + font-size: 14px; + font-weight: 500; + color: var(--color-text); + text-align: left; + transition: background var(--transition); + gap: 8px; +} + +.adv-section-header:hover { + background: var(--color-bg); +} + +.adv-section-title { + flex: 1; +} + +.adv-section-chevron { + font-size: 16px; + color: var(--color-text-muted); + line-height: 1; + transition: transform 0.18s ease; + user-select: none; +} + +/* Rotate chevron when expanded */ +.adv-section-header[aria-expanded="true"] .adv-section-chevron { + transform: rotate(180deg); +} + +.adv-section-body { + padding: 4px 14px 10px; + border-top: 1px solid var(--color-border); + display: flex; + flex-direction: column; + gap: 0; + animation: adv-body-in 0.15s ease; +} + +.adv-section-body.hidden { + display: none; +} + +@keyframes adv-body-in { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +.adv-checkbox-row { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 10px 0; + cursor: pointer; + border-bottom: 1px solid var(--color-border); +} + +.adv-checkbox-row:last-child { + border-bottom: none; +} + +.adv-checkbox-row input[type="checkbox"] { + margin-top: 2px; + width: 15px; + height: 15px; + flex-shrink: 0; + accent-color: var(--color-primary); + cursor: pointer; +} + +.adv-checkbox-text { + display: flex; + flex-direction: column; + gap: 2px; + flex: 1; + min-width: 0; +} + +.adv-checkbox-label { + font-size: 14px; + font-weight: 500; + color: var(--color-text); + line-height: 1.3; +} + +.adv-checkbox-desc { + font-size: 12px; + color: var(--color-text-muted); + line-height: 1.45; +} diff --git a/app/static/js/vault.js b/app/static/js/vault.js index 9e8ec27..5cfb590 100644 --- a/app/static/js/vault.js +++ b/app/static/js/vault.js @@ -2878,6 +2878,16 @@ const Vault = (() => { form.dataset.mode = mode; form.dataset.itemId = item ? item.id : ""; + // Always start Advanced Settings collapsed when the modal opens. + const advBody = document.getElementById("adv-settings-body"); + const advToggle = document.getElementById("adv-settings-toggle"); + if (advBody) advBody.classList.add("hidden"); + if (advToggle) { + advToggle.setAttribute("aria-expanded", "false"); + const chevron = advToggle.querySelector(".adv-section-chevron"); + if (chevron) chevron.textContent = "\u2964"; + } + const folderSel = document.getElementById("field-folder"); folderSel.innerHTML = ''; _folders.forEach((f) => { @@ -2912,6 +2922,13 @@ const Vault = (() => { setVal("field-totp-uri", p.totp_uri || ""); setVal("field-notes", p.notes); setVal("field-tags", (p.tags || []).join(", ")); + // Advanced Settings + document.getElementById("field-autofill").checked = + p.autofill !== false; // default true + document.getElementById("field-autologin").checked = + !!p.autologin; + document.getElementById("field-reprompt").checked = + !!p.reprompt; break; case "note": setVal("field-note-body", p.note_body); @@ -2988,6 +3005,9 @@ const Vault = (() => { totp_uri: getVal("field-totp-uri").trim(), notes: getVal("field-notes").trim(), tags: _parseTags(getVal("field-tags")), + autofill: document.getElementById("field-autofill")?.checked ?? true, + autologin: !!document.getElementById("field-autologin")?.checked, + reprompt: !!document.getElementById("field-reprompt")?.checked, }; case "note": return { note_body: getVal("field-note-body") }; @@ -3406,6 +3426,19 @@ const Vault = (() => { .join(""); }); + // Advanced Settings collapsible toggle + document + .getElementById("adv-settings-toggle") + ?.addEventListener("click", () => { + const body = document.getElementById("adv-settings-body"); + const btn = document.getElementById("adv-settings-toggle"); + const chevron = btn.querySelector(".adv-section-chevron"); + const isOpen = !body.classList.contains("hidden"); + body.classList.toggle("hidden", isOpen); + btn.setAttribute("aria-expanded", String(!isOpen)); + chevron.textContent = isOpen ? "\u2964" : "\u2963"; + }); + // Sidebar navigation document.getElementById("sidebar-all")?.addEventListener("click", () => { _activeFilter = null; diff --git a/app/templates/vault/index.html b/app/templates/vault/index.html index 131f5ee..a2fe1af 100644 --- a/app/templates/vault/index.html +++ b/app/templates/vault/index.html @@ -499,6 +499,64 @@ secret key. PassKeeper will generate your 2FA codes.

+ + +
+ + +