From c50e139cc7626a9b58721c964b1506236d17a614 Mon Sep 17 00:00:00 2001
From: User
Date: Wed, 11 Feb 2026 16:45:22 +0800
Subject: [PATCH] feat: add experimental option for sidebar auto-centering
---
src/components/menulist-tab.ts | 21 ++++++++++++---------
src/config/config.ts | 1 +
src/pages/options/options-i18n.ts | 2 ++
src/pages/options/options.html | 4 ++++
src/pages/options/options.ts | 9 +++++++++
static/_locales/en/messages.json | 6 +++++-
6 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/src/components/menulist-tab.ts b/src/components/menulist-tab.ts
index fcd7113c..3d83d6dc 100644
--- a/src/components/menulist-tab.ts
+++ b/src/components/menulist-tab.ts
@@ -25,6 +25,7 @@ import { EventSink } from "weeg-events";
import { CompatTab } from 'weeg-tabs';
import { DisplayedContainer } from 'weeg-containers';
+import { config } from '../config/config';
import { TabIconService } from '../lib/TabIconService';
import { ModalSetTagElement } from './modal-set-tag';
@@ -125,9 +126,7 @@ export class MenulistTabElement extends HTMLElement {
if (tab.active) {
this.tabButton.classList.add("active");
// Scroll to center with a small delay to avoid initial render conflicts
- if (document.body.classList.contains('popup')) {
- setTimeout(() => this.scrollIntoViewIfActive(), 100);
- }
+ setTimeout(() => this.scrollIntoViewIfActive(), 100);
}
}
@@ -139,12 +138,16 @@ export class MenulistTabElement extends HTMLElement {
this.tabMainElement.style.borderColor = displayedContainer.colorCode;
}
- private scrollIntoViewIfActive(): void {
- // Scroll the active tab into view at the center of the sidebar
- // Using requestAnimationFrame to ensure DOM is ready
- requestAnimationFrame(() => {
- this.scrollIntoView({ behavior: 'smooth', block: 'center' });
- });
+ private async scrollIntoViewIfActive(): Promise {
+ const isPopup = document.body.classList.contains('popup');
+ const autoCenter = await config['tab.autoCenterInSidebar'].getValue();
+ if (isPopup || autoCenter) {
+ // Scroll the active tab into view at the center of the sidebar
+ // Using requestAnimationFrame to ensure DOM is ready
+ requestAnimationFrame(() => {
+ this.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ });
+ }
}
private getShadowElement(id: string): HTMLElement {
diff --git a/src/config/config.ts b/src/config/config.ts
index 603b2246..d23587ad 100644
--- a/src/config/config.ts
+++ b/src/config/config.ts
@@ -43,6 +43,7 @@ export const config = {
'tab.autoDiscard.minAge': new StorageConfigurationOption('tab.autoDiscard.minAge', -1),
'tab.sorting.enabled': new StorageConfigurationOption('tab.sorting.enabled', true),
'tab.autoHide.enabled': new StorageConfigurationOption('tab.autoHide.enabled', false),
+ 'tab.autoCenterInSidebar': new StorageConfigurationOption('tab.autoCenterInSidebar', false),
'menu.hideEmptyContainers': new StorageConfigurationOption('menu.hideEmptyContainers', false),
};
diff --git a/src/pages/options/options-i18n.ts b/src/pages/options/options-i18n.ts
index a239bc72..ee70e80a 100644
--- a/src/pages/options/options-i18n.ts
+++ b/src/pages/options/options-i18n.ts
@@ -78,6 +78,8 @@ setTextContent('label[for="input-syncContainers"]', 'optionSyncContainers');
setTextContent('label[for="select-externalTabContainerOption"]', 'labelExternalTabSelectContainerOption');
+setTextContent('label[for="input-autoCenterInSidebar"]', 'optionAutoCenterInSidebar');
+
setTextContent('label[for="input-autoHideContainers"]', 'optionAutoHideContainers');
setTextContent('#select-externalTabContainerOption > option[value="choose"]', 'labelExternalTabOptionChooseContainer');
diff --git a/src/pages/options/options.html b/src/pages/options/options.html
index 3fc5f320..9c4dc8c2 100644
--- a/src/pages/options/options.html
+++ b/src/pages/options/options.html
@@ -73,6 +73,10 @@ optionsHeadingExperimental
+
+
+
+