From 183c58384142b3da09f8fb6273adefa095794da7 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 21 Jun 2026 21:43:44 +0200 Subject: [PATCH] gh-14320: fix workspace change icon picker state when opening (gh-14321) The picker reset its page with a smooth scrollIntoView while the popup was hiding, and positioned the page before the popup was laid out, so it could animate/jump on open. Reset instantly on popupshown (after layout) instead, and drop the on-hide scroll so there's no visible animation. --- src/zen/common/emojis/ZenEmojiPicker.mjs | 87 ++++++++++++++---------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/src/zen/common/emojis/ZenEmojiPicker.mjs b/src/zen/common/emojis/ZenEmojiPicker.mjs index cf651e23c..97b2c1cce 100644 --- a/src/zen/common/emojis/ZenEmojiPicker.mjs +++ b/src/zen/common/emojis/ZenEmojiPicker.mjs @@ -6,29 +6,29 @@ import { nsZenDOMOperatedFeature } from "chrome://browser/content/zen-components // prettier-ignore const SVG_ICONS = [ - "airplane.svg", "american-football.svg", "baseball.svg", "basket.svg", - "bed.svg", "bell.svg", "bookmark.svg", "book.svg", - "briefcase.svg", "brush.svg", "bug.svg", "build.svg", - "cafe.svg", "call.svg", "card.svg", "chat.svg", - "checkbox.svg", "circle.svg", "cloud.svg", "code.svg", - "coins.svg", "construct.svg", "cutlery.svg", "egg.svg", - "extension-puzzle.svg", "eye.svg", "fast-food.svg", "fish.svg", - "flag.svg", "flame.svg", "flask.svg", "folder.svg", - "game-controller.svg", "globe-1.svg", "globe.svg", "grid-2x2.svg", - "grid-3x3.svg", "heart.svg", "ice-cream.svg", "image.svg", - "inbox.svg", "key.svg", "layers.svg", "leaf.svg", - "lightning.svg", "location.svg", "lock-closed.svg", "logo-rss.svg", - "logo-usd.svg", "mail.svg", "map.svg", "megaphone.svg", - "moon.svg", "music.svg", "navigate.svg", "nuclear.svg", - "page.svg", "palette.svg", "paw.svg", "people.svg", - "pizza.svg", "planet.svg", "present.svg", "rocket.svg", - "school.svg", "shapes.svg", "shirt.svg", "skull.svg", - "squares.svg", "square.svg", "star-1.svg", "star.svg", - "stats-chart.svg", "sun.svg", "tada.svg", "terminal.svg", - "ticket.svg", "time.svg", "trash.svg", "triangle.svg", - "video.svg", "volume-high.svg", "wallet.svg", "warning.svg", - "water.svg", "weight.svg", - ]; + "airplane.svg", "american-football.svg", "baseball.svg", "basket.svg", + "bed.svg", "bell.svg", "bookmark.svg", "book.svg", + "briefcase.svg", "brush.svg", "bug.svg", "build.svg", + "cafe.svg", "call.svg", "card.svg", "chat.svg", + "checkbox.svg", "circle.svg", "cloud.svg", "code.svg", + "coins.svg", "construct.svg", "cutlery.svg", "egg.svg", + "extension-puzzle.svg", "eye.svg", "fast-food.svg", "fish.svg", + "flag.svg", "flame.svg", "flask.svg", "folder.svg", + "game-controller.svg", "globe-1.svg", "globe.svg", "grid-2x2.svg", + "grid-3x3.svg", "heart.svg", "ice-cream.svg", "image.svg", + "inbox.svg", "key.svg", "layers.svg", "leaf.svg", + "lightning.svg", "location.svg", "lock-closed.svg", "logo-rss.svg", + "logo-usd.svg", "mail.svg", "map.svg", "megaphone.svg", + "moon.svg", "music.svg", "navigate.svg", "nuclear.svg", + "page.svg", "palette.svg", "paw.svg", "people.svg", + "pizza.svg", "planet.svg", "present.svg", "rocket.svg", + "school.svg", "shapes.svg", "shirt.svg", "skull.svg", + "squares.svg", "square.svg", "star-1.svg", "star.svg", + "stats-chart.svg", "sun.svg", "tada.svg", "terminal.svg", + "ticket.svg", "time.svg", "trash.svg", "triangle.svg", + "video.svg", "volume-high.svg", "wallet.svg", "warning.svg", + "water.svg", "weight.svg", +]; class nsZenEmojiPicker extends nsZenDOMOperatedFeature { #panel; @@ -47,6 +47,7 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { init() { this.#panel = document.getElementById("PanelUI-zen-emojis-picker"); this.#panel.addEventListener("popupshowing", this); + this.#panel.addEventListener("popupshown", this); this.#panel.addEventListener("popuphidden", this); this.#panel.addEventListener("command", this); this.searchInput.addEventListener("input", this); @@ -57,6 +58,9 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { case "popupshowing": this.#onPopupShowing(event); break; + case "popupshown": + this.#onPopupShown(event); + break; case "popuphidden": this.#onPopupHidden(event); break; @@ -103,17 +107,20 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { return document.getElementById("PanelUI-zen-emojis-picker-search"); } - #changePage(toSvg = false) { + #changePage(toSvg = false, { animate = true } = {}) { + const pages = document.getElementById("PanelUI-zen-emojis-picker-pages"); const itemToScroll = toSvg ? this.svgList - : document - .getElementById("PanelUI-zen-emojis-picker-pages") - .querySelector('[emojis="true"]'); - itemToScroll.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "start", - }); + : pages.querySelector('[emojis="true"]'); + if (animate) { + itemToScroll.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "start", + }); + } else { + pages.scrollLeft = toSvg ? itemToScroll.offsetLeft : 0; + } const button = document.getElementById( `PanelUI-zen-emojis-picker-change-${toSvg ? "svg" : "emojis"}` ); @@ -180,9 +187,6 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { }); emojiList.appendChild(item); } - setTimeout(() => { - this.searchInput.focus(); - }, 500); } const svgList = this.svgList; for (const icon of SVG_ICONS) { @@ -199,14 +203,23 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { } } + #onPopupShown(event) { + if (event.target !== this.#panel) { + return; + } + const allowEmojis = !this.#panel.hasAttribute("only-svg-icons"); + if (allowEmojis) { + this.searchInput.focus({ preventScroll: true }); + } + this.#changePage(false, { animate: false }); + } + #onPopupHidden(event) { if (event.target !== this.#panel) { return; } this.#clearEmojis(); - this.#changePage(false); - const emojiList = this.emojiList; emojiList.innerHTML = "";