From 4ccbb54cd8807b439bb180050d84dafd6cd7c2e6 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Thu, 23 Jul 2026 14:00:46 +0530 Subject: [PATCH] fix(settings): sync global search switch behavior and animation --- src/components/checkbox/index.js | 49 +++++++++++++++++-------------- src/components/searchbar/index.js | 22 ++++++++++++-- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/components/checkbox/index.js b/src/components/checkbox/index.js index 928d8c23b..17e3e44b1 100644 --- a/src/components/checkbox/index.js +++ b/src/components/checkbox/index.js @@ -2,6 +2,32 @@ import "./styles.scss"; import Ref from "html-tag-js/ref"; import { animate } from "motion"; +export function updateSwitchHandle($handle, checked, animateToggle = true) { + if (!$handle) return; + + const targetTransform = checked + ? "translate3d(1.12rem, 0, 0)" + : "translate3d(0, 0, 0)"; + + if (animateToggle && !document.body.classList.contains("no-animation")) { + animate( + $handle, + { + transform: targetTransform, + }, + { + type: "spring", + stiffness: 500, + damping: 28, + }, + ).then(() => { + $handle.style.transform = targetTransform; + }); + } else { + $handle.style.transform = targetTransform; + } +} + /** * @typedef {Object} Checkbox * @property {string} text @@ -58,28 +84,7 @@ function Checkbox(text, checked, name, id, type, ref, size, isSwitch) { ) !== null; if (isSwitch && $handle.el) { - const isChecked = !!$input.el.checked; - const targetTransform = isChecked - ? "translate3d(1.12rem, 0, 0)" - : "translate3d(0, 0, 0)"; - - if (animateToggle && !document.body.classList.contains("no-animation")) { - animate( - $handle.el, - { - transform: targetTransform, - }, - { - type: "spring", - stiffness: 500, - damping: 28, - }, - ).then(() => { - $handle.el.style.transform = targetTransform; - }); - } else { - $handle.el.style.transform = targetTransform; - } + updateSwitchHandle($handle.el, !!$input.el.checked, animateToggle); } } diff --git a/src/components/searchbar/index.js b/src/components/searchbar/index.js index 058980fba..5de43125c 100644 --- a/src/components/searchbar/index.js +++ b/src/components/searchbar/index.js @@ -1,4 +1,5 @@ import "./style.scss"; +import { updateSwitchHandle } from "components/checkbox"; import Ref from "html-tag-js/ref"; import actionStack from "lib/actionStack"; @@ -191,7 +192,12 @@ function searchBar( function cloneSearchItem($item) { const $clone = $item.cloneNode(true); syncCheckboxState($clone, $item); - $clone.addEventListener("click", () => { + $clone.addEventListener("click", (event) => { + // The clone is only a proxy for the backing settings item. In + // particular, do not let a cloned label activate its checkbox after + // this handler: that would emit a second click and toggle the backing + // setting twice. + event.preventDefault(); $item.addEventListener( "settings-item-interaction-end", (event) => { @@ -214,15 +220,16 @@ function searchBar( function syncSearchClone($clone, $item) { $clone.className = $item.className; $clone.innerHTML = $item.innerHTML; - syncCheckboxState($clone, $item); + syncCheckboxState($clone, $item, true); } /** * Sync the checked property of checkbox and radio elements, since cloneNode and innerHTML do not copy/preserve dynamic checked state. * @param {HTMLElement} $clone * @param {HTMLElement} $item + * @param {boolean} [animateToggle] */ - function syncCheckboxState($clone, $item) { + function syncCheckboxState($clone, $item, animateToggle = false) { const $itemCheckbox = $item.querySelector( 'input[type="checkbox"], input[type="radio"]', ); @@ -232,6 +239,15 @@ function searchBar( ); if ($cloneCheckbox) { $cloneCheckbox.checked = $itemCheckbox.checked; + + // Motion animations update the original switch asynchronously. + // A clone does not retain the Checkbox component's update + // handler, so apply the shared switch transition explicitly. + const $checkbox = $cloneCheckbox.closest(".input-checkbox"); + const $handle = $checkbox?.querySelector(".handle"); + if ($handle && $checkbox.classList.contains("switch")) { + updateSwitchHandle($handle, $cloneCheckbox.checked, animateToggle); + } } } }