From c4eacd201c0546d402a55ea98d6d8b645df0652a Mon Sep 17 00:00:00 2001
From: dragonwocky <thedragonring.bod@gmail.com>
Date: Tue, 30 Jan 2024 22:20:58 +1100
Subject: [PATCH] style: implement size- utility

---
 src/archive/corner-action.css       | 55 -----------------------------
 src/archive/corner-action.mjs       | 43 ----------------------
 src/common/markup.js                | 10 +++---
 src/common/system.js                |  6 ++--
 src/core/client.mjs                 |  2 +-
 src/core/islands/MenuButton.mjs     |  6 ++--
 src/core/islands/Panel.mjs          | 25 ++++++-------
 src/core/islands/TopbarButton.mjs   |  8 ++---
 src/core/menu/islands/Banner.mjs    |  2 +-
 src/core/menu/islands/Checkbox.mjs  |  8 ++---
 src/core/menu/islands/Input.mjs     |  4 +--
 src/core/menu/islands/Mod.mjs       |  2 +-
 src/core/menu/islands/Profiles.mjs  |  2 +-
 src/core/menu/islands/Select.mjs    |  6 ++--
 src/core/menu/islands/Sidebar.mjs   |  4 +--
 src/core/menu/islands/Toggle.mjs    |  6 ++--
 src/core/menu/islands/View.mjs      |  2 +-
 src/core/menu/menu.mjs              |  2 +-
 src/extensions/titlebar/buttons.mjs |  2 +-
 src/extensions/topbar/client.mjs    |  7 +++-
 src/extensions/tweaks/client.mjs    |  2 +-
 21 files changed, 55 insertions(+), 149 deletions(-)
 delete mode 100644 src/archive/corner-action.css
 delete mode 100644 src/archive/corner-action.mjs

diff --git a/src/archive/corner-action.css b/src/archive/corner-action.css
deleted file mode 100644
index fdff4ac..0000000
--- a/src/archive/corner-action.css
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * notion-enhancer: components
- * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
- * (c) 2021 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
- * (https://notion-enhancer.github.io/) under the MIT license
- */
-
-#enhancer--corner-actions {
-  position: absolute;
-  bottom: 26px;
-  right: 26px;
-  z-index: 101;
-  cursor: default;
-  pointer-events: none;
-  display: flex;
-  flex-direction: row-reverse;
-}
-
-#enhancer--corner-actions > div {
-  position: static !important;
-  width: 36px;
-  height: 36px;
-  margin-left: 12px;
-  pointer-events: auto;
-  border-radius: 100%;
-  font-size: 20px;
-
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  color: var(--theme--icon);
-  fill: var(--theme--icon);
-  background: var(--theme--ui_corner_action) !important;
-  box-shadow: var(--theme--ui_shadow, rgba(15, 15, 15, 0.15)) 0px 0px 0px 1px,
-    var(--theme--ui_shadow, rgba(15, 15, 15, 0.15)) 0px 2px 4px !important;
-
-  user-select: none;
-  cursor: pointer;
-}
-#enhancer--corner-actions > div:hover {
-  background: var(--theme--ui_corner_action-hover) !important;
-}
-#enhancer--corner-actions > div:active {
-  background: var(--theme--ui_corner_action-active) !important;
-}
-#enhancer--corner-actions > div.hidden {
-  display: none;
-}
-
-#enhancer--corner-actions > div > svg {
-  width: 22px;
-  height: 22px;
-  color: var(--theme--icon);
-  fill: var(--theme--icon);
-}
diff --git a/src/archive/corner-action.mjs b/src/archive/corner-action.mjs
deleted file mode 100644
index bf42f9b..0000000
--- a/src/archive/corner-action.mjs
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * notion-enhancer: components
- * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
- * (c) 2021 CloudHill <rl.cloudhill@gmail.com> (https://github.com/CloudHill)
- * (https://notion-enhancer.github.io/) under the MIT license
- */
-
-'use strict';
-
-/** shared notion-style elements */
-
-import { web } from '../index.mjs';
-
-let $stylesheet, $cornerButtonsContainer;
-
-/**
- * adds a button to notion's bottom right corner
- * @param {string} icon - an svg string
- * @param {function} listener - the function to call when the button is clicked
- * @returns {Element} the appended corner action element
- */
-export const addCornerAction = async (icon, listener) => {
-  if (!$stylesheet) {
-    $stylesheet = web.loadStylesheet('api/components/corner-action.css');
-    $cornerButtonsContainer = web.html`<div id="enhancer--corner-actions"></div>`;
-  }
-
-  await web.whenReady(['.notion-help-button']);
-  const $helpButton = document.querySelector('.notion-help-button'),
-    $onboardingButton = document.querySelector('.onboarding-checklist-button');
-  if ($onboardingButton) $cornerButtonsContainer.prepend($onboardingButton);
-  $cornerButtonsContainer.prepend($helpButton);
-  web.render(
-    document.querySelector('.notion-app-inner > .notion-cursor-listener'),
-    $cornerButtonsContainer
-  );
-
-  const $actionButton = web.html`<div class="enhancer--corner-action-button">${icon}</div>`;
-  $actionButton.addEventListener('click', listener);
-  web.render($cornerButtonsContainer, $actionButton);
-
-  return $actionButton;
-};
diff --git a/src/common/markup.js b/src/common/markup.js
index 5e91096..2b6d4d2 100644
--- a/src/common/markup.js
+++ b/src/common/markup.js
@@ -84,18 +84,18 @@ twind.install({
   rules: [
     ["text-(wrap|nowrap|balance|pretty)", "textWrap"],
     [/^i-((?:\w|-)+)(?:\?(mask|bg|auto))?$/, presetIcons],
+    [/^size-\[([^\]]+)\]$/, ({ 1: $1 }) => ({ height: $1, width: $1 })],
   ],
   variants: [
-    // https://github.com/tw-in-js/twind/blob/main/packages/preset-ext/src/variants.ts
-    [
-      "not-([a-z-]+|\\[.+\\])",
-      ({ 1: $1 }) => `&:not(${($1[0] == "[" ? "" : ":") + $1})`,
-    ],
     ["children", "&>*"],
     ["siblings", "&~*"],
     ["sibling", "&+*"],
     [/^&/, (match) => match.input],
     [/^has-\[([^\]]+)\]/, (match) => `&:has(${match[1]})`],
+    [
+      /^not-([a-z-]+|\[.+\])/,
+      ({ 1: $1 }) => `&:not(${($1[0] == "[" ? "" : ":") + $1})`,
+    ],
   ],
 });
 
diff --git a/src/common/system.js b/src/common/system.js
index e702efb..f8cbe1b 100644
--- a/src/common/system.js
+++ b/src/common/system.js
@@ -142,10 +142,8 @@ const initDatabase = (namespace, fallbacks = {}) => {
   },
   reloadApp = () => {
     if (IS_ELECTRON && !IS_RENDERER) {
-      const { app } = require("electron"),
-        args = process.argv.slice(1).filter((arg) => arg !== "--startup");
-      app.relaunch({ args });
-      app.exit();
+      const { app } = require("electron");
+      app.relaunch(), app.exit();
     } else sendMessage("notion-enhancer", "reload-app");
   };
 
diff --git a/src/core/client.mjs b/src/core/client.mjs
index 0409aae..e4d2be3 100644
--- a/src/core/client.mjs
+++ b/src/core/client.mjs
@@ -107,7 +107,7 @@ const insertMenu = async (api, db) => {
     event.stopPropagation();
     $modal.open();
   });
-  window.addEventListener("message", (event) => {
+  addEventListener("message", (event) => {
     // from embedded menu
     if (event.data?.channel !== "notion-enhancer") return;
     if (event.data?.action === "close-menu") $modal.close();
diff --git a/src/core/islands/MenuButton.mjs b/src/core/islands/MenuButton.mjs
index b98690c..856bf6b 100644
--- a/src/core/islands/MenuButton.mjs
+++ b/src/core/islands/MenuButton.mjs
@@ -20,7 +20,7 @@ function MenuButton(
     transition hover:bg-[color:var(--theme--bg-hover)]`,
   });
   return html`<div ...${props}>
-    <div class="flex items-center justify-center w-[22px] h-[22px] mr-[8px]">
+    <div class="flex items-center justify-center size-[22px] mr-[8px]">
       <i class="i-${icon}"></i>
     </div>
     <div>${children}</div>
@@ -29,9 +29,9 @@ function MenuButton(
       <!-- accents are squashed into one variable for theming:
       use rgb to match notion if overrides not loaded -->
       <div
-        class="flex justify-center w-[16px] h-[16px] font-semibold
+        class="flex justify-center size-[16px] font-semibold mb-[2px]
         text-([10px] [color:var(--theme--accent-secondary\\_contrast)])
-        bg-[color:var(--theme--accent-secondary)] rounded-[3px] mb-[2px]
+        bg-[color:var(--theme--accent-secondary)] rounded-[3px]
         dark:bg-[color:${themeOverridesLoaded
           ? "var(--theme--accent-secondary)"
           : "rgb(180,65,60)"}]"
diff --git a/src/core/islands/Panel.mjs b/src/core/islands/Panel.mjs
index e096db6..dfa6a0f 100644
--- a/src/core/islands/Panel.mjs
+++ b/src/core/islands/Panel.mjs
@@ -92,12 +92,12 @@ function Panel({
     { addMutationListener, removeMutationListener } = globalThis.__enhancerApi,
     $panelToggle = html`<button
       aria-label="Toggle side panel"
-      class="select-none h-[24px] w-[24px] duration-[20ms]
+      class="select-none size-[24px] duration-[20ms]
       transition inline-flex items-center justify-center mr-[10px]
       rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]"
     >
       <i
-        class="i-chevrons-left w-[20px] h-[20px]
+        class="i-chevrons-left size-[20px]
         text-[color:var(--theme--fg-secondary)] transition-transform
         group-&[data-pinned]/panel:rotate-180 duration-[${transitionDuration}ms]"
       />
@@ -301,21 +301,22 @@ function Panel({
   // moves help button out of the way of open panel.
   // normally would place outside of an island, but in
   // this case is necessary for syncing up animations
-  const notionHelp = ".notion-help-button",
-    repositionHelp = async (width) => {
-      const $notionHelp = document.querySelector(notionHelp);
-      if (!$notionHelp) return;
+  const floatingButtons =
+      ".notion-enhancer--floating-buttons, .notion-help-button",
+    repositionFloatingButtons = async (width) => {
+      const $floatingButtons = document.querySelector(floatingButtons);
+      if (!$floatingButtons) return;
       width ??= await getWidth();
       if (isNaN(width)) width = minWidth;
       if (!isPinned()) width = 0;
       const to = `${26 + width}px`,
-        from = $notionHelp.style.getPropertyValue("right");
+        from = $floatingButtons.style.getPropertyValue("right");
       if (from === to) return;
-      $notionHelp.style.setProperty("right", to);
-      animate($notionHelp, [({ right: from }, { right: to })]);
-      removeMutationListener(repositionHelp);
+      $floatingButtons.style.setProperty("right", to);
+      animate($floatingButtons, [({ right: from }, { right: to })]);
+      removeMutationListener(repositionFloatingButtons);
     };
-  addMutationListener(notionHelp, repositionHelp);
+  addMutationListener(floatingButtons, repositionFloatingButtons);
 
   $panel.pin = () => {
     if (isPinned() || !panelViews.length) return;
@@ -376,7 +377,7 @@ function Panel({
     const $parent = $panel.parentElement || $panel;
     $parent.style.setProperty("--panel--width", `${width}px`);
     if ($parent !== $panel) $panel.style.removeProperty("--panel--width");
-    repositionHelp(width);
+    repositionFloatingButtons(width);
   };
 
   useState(["panelViews"], async ([panelViews = []]) => {
diff --git a/src/core/islands/TopbarButton.mjs b/src/core/islands/TopbarButton.mjs
index 53a5ddc..67523b6 100644
--- a/src/core/islands/TopbarButton.mjs
+++ b/src/core/islands/TopbarButton.mjs
@@ -1,6 +1,6 @@
 /**
  * notion-enhancer
- * (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
+ * (c) 2024 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
  * (https://notion-enhancer.github.io/) under the MIT license
  */
 
@@ -10,20 +10,20 @@ function TopbarButton({ icon, ...props }, ...children) {
   const { html, extendProps } = globalThis.__enhancerApi;
   extendProps(props, {
     tabindex: 0,
-    role: "button",
     class: `notion-enhancer--topbar-button
     text-[color:var(--theme--fg-primary)] mr-[2px]
     select-none h-[28px] w-[33px] duration-[20ms]
     transition inline-flex items-center justify-center
     rounded-[3px] hover:bg-[color:var(--theme--bg-hover)]
     has-[span]:w-auto &>span:(text-[14px] leading-[1.2] px-[8px])
-    &[data-active]:bg-[color:var(--theme--bg-hover)]`,
+    &[data-active]:bg-[color:var(--theme--bg-hover)]
+    &>i:size-[20px]`,
   });
 
   return html`<button ...${props}>
     ${props.innerHTML || children.length
       ? children
-      : html`<i class="i-${icon} w-[20px] h-[20px]" />`}
+      : html`<i class="i-${icon}" />`}
   </button>`;
 }
 
diff --git a/src/core/menu/islands/Banner.mjs b/src/core/menu/islands/Banner.mjs
index ffcda2e..c2d664a 100644
--- a/src/core/menu/islands/Banner.mjs
+++ b/src/core/menu/islands/Banner.mjs
@@ -80,7 +80,7 @@ function Banner({ updateAvailable, isDevelopmentBuild }) {
     >
       <div
         class="notion-enhancer--menu-update-indicator
-        absolute h-[12px] w-[12px] right-[-6px] top-[-6px]
+        absolute size-[12px] right-[-6px] top-[-6px]
         ${updateAvailable ? "" : "hidden"}"
       >
         <span
diff --git a/src/core/menu/islands/Checkbox.mjs b/src/core/menu/islands/Checkbox.mjs
index 5784a5a..96c2889 100644
--- a/src/core/menu/islands/Checkbox.mjs
+++ b/src/core/menu/islands/Checkbox.mjs
@@ -11,9 +11,9 @@ function Checkbox({ _get, _set, _requireReload = true, ...props }) {
   const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
     $input = html`<input
       type="checkbox"
-      class="hidden checked:sibling:(px-px
+      class="hidden checked:&+div:(px-px
       bg-[color:var(--theme--accent-primary)])
-      not-checked:sibling:(children:text-transparent
+      not-checked:&+div:(&>div:text-transparent
         border-(& [color:var(--theme--fg-primary)])
         hover:bg-[color:var(--theme--bg-hover)])"
       ...${props}
@@ -39,9 +39,9 @@ function Checkbox({ _get, _set, _requireReload = true, ...props }) {
     }}
   >
     ${$input}
-    <div class="flex items-center h-[16px] transition duration-[200ms]">
+    <div class="flex items-center h-[16px] transition duration-200">
       <i
-        class="i-check w-[14px] h-[14px]
+        class="i-check size-[14px]
         text-[color:var(--theme--accent-primary\\_contrast)]"
       ></i>
     </div>
diff --git a/src/core/menu/islands/Input.mjs b/src/core/menu/islands/Input.mjs
index abf911e..cb5ad1e 100644
--- a/src/core/menu/islands/Input.mjs
+++ b/src/core/menu/islands/Input.mjs
@@ -96,7 +96,7 @@ function Input({
       hover:text-[color:var(--theme--fg-primary)]"
       onclick=${() => _set?.({ filename: "", content: "" })}
     >
-      <i class="i-x w-[14px] h-[14px]"></i>
+      <i class="i-x size-[14px]"></i>
     </button>`;
     props.accept = extensions
       ?.map((ext) => (ext.startsWith(".") ? ext : `.${ext}`))
@@ -119,7 +119,7 @@ function Input({
       class="${variant === "lg" ? "pr-[12px]" : "pr-[8px]"}
       absolute flex items-center h-full pointer-events-none
       text-[color:var(--theme--fg-secondary)] right-0 top-0"
-      ><i class="i-${icon} w-[16px] h-[16px]"></i>
+      ><i class="i-${icon} size-[16px]"></i>
     </span>`;
 
   let _initialValue;
diff --git a/src/core/menu/islands/Mod.mjs b/src/core/menu/islands/Mod.mjs
index 39c73a3..261540f 100644
--- a/src/core/menu/islands/Mod.mjs
+++ b/src/core/menu/islands/Mod.mjs
@@ -73,7 +73,7 @@ function Mod({
               setState({ transition: "slide-to-right", view: id });
             }}
           >
-            <i class="i-settings w-[18px] h-[18px]"></i>
+            <i class="i-settings size-[18px]"></i>
           </button>`
         : ""}
       <div class="my-auto scale-[1.15]">
diff --git a/src/core/menu/islands/Profiles.mjs b/src/core/menu/islands/Profiles.mjs
index 438ffa1..a7a4dc5 100644
--- a/src/core/menu/islands/Profiles.mjs
+++ b/src/core/menu/islands/Profiles.mjs
@@ -123,7 +123,7 @@ function Profile({ id }) {
       text-[color:var(--theme--fg-secondary)]
       hover:text-[color:var(--theme--fg-primary)]"
     >
-      <i class="i-x w-[14px] h-[14px]"></i>
+      <i class="i-x size-[14px]"></i>
     </button>`,
     $confirmName = $successName.cloneNode(true),
     $confirm = html`<${Popup}
diff --git a/src/core/menu/islands/Select.mjs b/src/core/menu/islands/Select.mjs
index ad758d3..a497416 100644
--- a/src/core/menu/islands/Select.mjs
+++ b/src/core/menu/islands/Select.mjs
@@ -10,7 +10,7 @@ import { Popup } from "./Popup.mjs";
 
 function Option({ $icon = "", value = "", _get, _set }) {
   const { html, useState } = globalThis.__enhancerApi,
-    $selected = html`<i class="ml-auto i-check w-[16px] h-[16px]"></i>`,
+    $selected = html`<i class="ml-auto i-check size-[16px]"></i>`,
     $option = html`<div
       tabindex="0"
       role="option"
@@ -65,7 +65,7 @@ function Select({
       if (["string", "number"].includes(typeof opt)) opt = { value: opt };
       if (!(opt?.$icon instanceof Element)) {
         if (typeof opt?.$icon === "string") {
-          opt.$icon = html`<i class="i-${opt.$icon} h-[16px] w-[16px]" />`;
+          opt.$icon = html`<i class="i-${opt.$icon} size-[16px]" />`;
         } else delete opt.$icon;
       }
       return {
@@ -135,7 +135,7 @@ function Select({
     <//>
     <i
       class="i-chevron-down pointer-events-none
-      absolute right-[6px] top-[6px] w-[16px] h-[16px]
+      absolute right-[6px] top-[6px] size-[16px]
       text-[color:var(--theme--fg-secondary)]"
     ></i>
   </div>`;
diff --git a/src/core/menu/islands/Sidebar.mjs b/src/core/menu/islands/Sidebar.mjs
index cbad8b0..d291a67 100644
--- a/src/core/menu/islands/Sidebar.mjs
+++ b/src/core/menu/islands/Sidebar.mjs
@@ -31,8 +31,8 @@ function SidebarButton({ id, icon, ...props }, ...children) {
       ${icon
         ? html`<i
             class="i-${icon} ${icon.startsWith("notion-enhancer")
-              ? "w-[17px] h-[17px] ml-[1.5px] mr-[9.5px]"
-              : "w-[18px] h-[18px] ml-px mr-[9px]"}"
+              ? "size-[17px] ml-[1.5px] mr-[9.5px]"
+              : "size-[18px] ml-px mr-[9px]"}"
           ></i>`
         : ""}
       <span class="leading-[20px]">${children}</span>
diff --git a/src/core/menu/islands/Toggle.mjs b/src/core/menu/islands/Toggle.mjs
index fa48a21..c0ba236 100644
--- a/src/core/menu/islands/Toggle.mjs
+++ b/src/core/menu/islands/Toggle.mjs
@@ -11,7 +11,7 @@ function Toggle({ _get, _set, _requireReload = true, ...props }) {
   const { html, extendProps, setState, useState } = globalThis.__enhancerApi,
     $input = html`<input
       type="checkbox"
-      class="hidden checked:sibling:children:(
+      class="hidden checked:&+div>div:(
       bg-[color:var(--theme--accent-primary)]
       after:translate-x-[12px])"
       ...${props}
@@ -43,9 +43,9 @@ function Toggle({ _get, _set, _requireReload = true, ...props }) {
         class="w-full h-full rounded-[44px] text-[12px]
         p-[2px] hover:bg-[color:var(--theme--bg-hover)]
         transition duration-200 after:(
-          inline-block w-[14px] h-[14px] rounded-[44px]
+          inline-block size-[14px] rounded-[44px]
           bg-[color:var(--theme--accent-primary\\_contrast)]
-          transition duration-200
+          transition duration-200 content-empty
         )"
       ></div>
     </div>
diff --git a/src/core/menu/islands/View.mjs b/src/core/menu/islands/View.mjs
index 3daf13c..f8b1b39 100644
--- a/src/core/menu/islands/View.mjs
+++ b/src/core/menu/islands/View.mjs
@@ -12,7 +12,7 @@ function View({ id }, ...children) {
     $view = html`<article
       id=${id}
       class="notion-enhancer--menu-view absolute h-full w-full
-      min-w-[580px] px-[60px] pt-[36px] !children:last:pb-[36px]"
+      min-w-[580px] px-[60px] pt-[36px] !&>*:last:pb-[36px]"
     >
       ${children}
     </article>`;
diff --git a/src/core/menu/menu.mjs b/src/core/menu/menu.mjs
index 2d3efba..2d5249c 100644
--- a/src/core/menu/menu.mjs
+++ b/src/core/menu/menu.mjs
@@ -200,7 +200,7 @@ const importApi = () => {
     useState(["rerender"], renderMenu);
   };
 
-window.addEventListener("message", async (event) => {
+addEventListener("message", async (event) => {
   if (event.data?.channel !== "notion-enhancer") return;
   await importApi().then(hookIntoState);
   const { setState, useState } = globalThis.__enhancerApi;
diff --git a/src/extensions/titlebar/buttons.mjs b/src/extensions/titlebar/buttons.mjs
index 4504e65..705d27f 100644
--- a/src/extensions/titlebar/buttons.mjs
+++ b/src/extensions/titlebar/buttons.mjs
@@ -60,7 +60,7 @@ const createWindowButtons = async () => {
     $maximize.style.display = isMaximized ? "none" : "";
     $unmaximize.style.display = isMaximized ? "" : "none";
   };
-  window.addEventListener("resize", resizeWindow);
+  addEventListener("resize", resizeWindow);
   resizeWindow();
 
   return html`<div class="flex flex-nowrap">${$minimize}${$maximize}${$unmaximize}${$close}</div>`;
diff --git a/src/extensions/topbar/client.mjs b/src/extensions/topbar/client.mjs
index 8ffb2dc..3095e23 100644
--- a/src/extensions/topbar/client.mjs
+++ b/src/extensions/topbar/client.mjs
@@ -41,7 +41,8 @@ export default async function (api, db) {
   addMutationListener(shareSelector, () => {
     const $btn = document.querySelector(shareSelector);
     let icon = shareIcon?.content;
-    icon ??= `<i class="i-share2 w-[20px] h-[20px]"></i>`;
+    icon ??= `<i class="i-share2 size-[20px]"></i>`;
+    if (!$btn) return;
     if (shareButton === "Icon") displayIcon($btn, icon);
     if (shareButton === "Disabled" && $btn.style.display !== "none")
       $btn.style.display = "none";
@@ -53,6 +54,7 @@ export default async function (api, db) {
   addMutationListener(commentsSelector, () => {
     const $btn = document.querySelector(commentsSelector),
       icon = commentsIcon?.content;
+    if (!$btn) return;
     if (commentsButton === "Text") displayLabel($btn);
     if (commentsButton === "Icon" && icon) displayIcon($btn, icon);
     if (commentsButton === "Disabled" && $btn.style.display !== "none")
@@ -65,6 +67,7 @@ export default async function (api, db) {
   addMutationListener(updatesSelector, () => {
     const $btn = document.querySelector(updatesSelector),
       icon = updatesIcon?.content;
+    if (!$btn) return;
     if (updatesButton === "Text") displayLabel($btn);
     if (updatesButton === "Icon" && icon) displayIcon($btn, icon);
     if (updatesButton === "Disabled" && $btn.style.display !== "none")
@@ -77,6 +80,7 @@ export default async function (api, db) {
   addMutationListener(favoriteSelector, () => {
     const $btn = document.querySelector(favoriteSelector),
       icon = favoriteIcon?.content;
+    if (!$btn) return;
     if (favoriteButton === "Text") displayLabel($btn);
     if (favoriteButton === "Icon" && icon) displayIcon($btn, icon);
     if (favoriteButton === "Disabled" && $btn.style.display !== "none")
@@ -89,6 +93,7 @@ export default async function (api, db) {
   addMutationListener(moreSelector, () => {
     const $btn = document.querySelector(moreSelector),
       icon = moreIcon?.content;
+    if (!$btn) return;
     $btn.ariaLabel = "More";
     if (moreButton === "Text") displayLabel($btn);
     if (moreButton === "Icon" && icon) displayIcon($btn, icon);
diff --git a/src/extensions/tweaks/client.mjs b/src/extensions/tweaks/client.mjs
index 66a2660..2a2671d 100644
--- a/src/extensions/tweaks/client.mjs
+++ b/src/extensions/tweaks/client.mjs
@@ -26,7 +26,7 @@ export default async function ({ web }, db) {
         document.body.classList.add('enhancer--tweak-responsive_breakpoint');
       }
     };
-  window.addEventListener('resize', addResponsiveBreakpoint);
+  addEventListener('resize', addResponsiveBreakpoint);
   addResponsiveBreakpoint();
 
   const tweaks = [