feat: Improved glance buttons to be more consistent, better aligned and more pleasing to look at in general, b=no-bug, c=common, glance, split-view, workspaces

This commit is contained in:
Mr. M
2025-07-17 19:04:39 +02:00
parent 3f4595f86e
commit 5ad1c6c323
8 changed files with 123 additions and 107 deletions

View File

@@ -53,6 +53,10 @@
<command id="cmd_zenCopyCurrentURL" />
<command id="cmd_zenCopyCurrentURLMarkdown" />
<command id="cmd_zenGlanceClose" />
<command id="cmd_zenGlanceExpand" />
<command id="cmd_zenGlanceSplit" />
</commandset>
<keyset id="zenKeyset"></keyset>

View File

@@ -34,7 +34,7 @@
#stop-button,
.close-icon,
#zen-glance-sidebar-close,
.zen-glance-sidebar-close,
.zen-theme-picker-custom-list-item-remove {
list-style-image: url('close.svg') !important;
}
@@ -257,7 +257,7 @@
#restore-button,
#fullscreen-button,
#zen-glance-sidebar-open,
.zen-glance-sidebar-open,
#appMenu-fullscreen-button2,
.zen-tab-unsplit-button {
list-style-image: url('fullscreen.svg') !important;
@@ -432,7 +432,7 @@
list-style-image: url('bookmark.svg') !important;
}
#zen-glance-sidebar-split {
.zen-glance-sidebar-split {
list-style-image: url('split.svg');
&[disabled='true'] {

View File

@@ -111,6 +111,7 @@ document.addEventListener(
gZenWorkspaces.openWorkspaceCreation(event);
break;
default:
gZenGlanceManager.handleMainCommandSet(event);
if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) {
const index = parseInt(event.target.id.replace('cmd_zenWorkspaceSwitch', ''), 10) - 1;
gZenWorkspaces.shortcutSwitchTo(index);

View File

@@ -22,35 +22,25 @@
false
);
ChromeUtils.defineLazyGetter(this, 'sidebarButtons', () =>
document.getElementById('zen-glance-sidebar-container')
);
document
.getElementById('tabbrowser-tabpanels')
.addEventListener('click', this.onOverlayClick.bind(this));
Services.obs.addObserver(this, 'quit-application-requested');
this.#addSidebarButtonListeners();
}
#addSidebarButtonListeners() {
this.sidebarButtons.addEventListener('command', (event) => {
const button = event.target.closest('toolbarbutton');
if (!button) {
return;
}
switch (button.id) {
case 'zen-glance-sidebar-close':
this.closeGlance({ onTabClose: true });
break;
case 'zen-glance-sidebar-open':
this.fullyOpenGlance();
break;
case 'zen-glance-sidebar-split':
this.splitGlance();
break;
}
});
handleMainCommandSet(event) {
const command = event.target;
switch (command.id) {
case 'cmd_zenGlanceClose':
this.closeGlance({ onTabClose: true });
break;
case 'cmd_zenGlanceExpand':
this.fullyOpenGlance();
break;
case 'cmd_zenGlanceSplit':
this.splitGlance();
break;
}
}
get #currentBrowser() {
@@ -120,28 +110,24 @@
this.contentWrapper = browser.closest('.browserStack');
}
showSidebarButtons(animate = false) {
if (this.sidebarButtons.hasAttribute('hidden') && animate) {
const isRightSide = gZenVerticalTabsManager._prefsRightSide;
this.sidebarButtons.setAttribute('right', isRightSide);
for (const button of this.sidebarButtons.querySelectorAll('toolbarbutton')) {
button.style.opacity = 0;
#createNewOverlayButtons() {
const newButtons = document
.getElementById('zen-glance-sidebar-template')
.content.cloneNode(true);
const container = newButtons.querySelector('.zen-glance-sidebar-container');
container.style.opacity = 0;
gZenUIManager.motion.animate(
container,
{
opacity: [0, 1],
},
{
duration: 0.2,
type: 'spring',
delay: 0.05,
}
const startX = isRightSide ? -50 : 50;
gZenUIManager.motion.animate(
this.sidebarButtons.querySelectorAll('toolbarbutton'),
{ x: [startX, 0], opacity: [0, 1] },
{ delay: gZenUIManager.motion.stagger(0.1) }
);
}
this.sidebarButtons.removeAttribute('hidden');
}
hideSidebarButtons() {
this.sidebarButtons.setAttribute('hidden', true);
);
return newButtons;
}
openGlance(data, existingTab = null, ownerTab = null) {
@@ -177,8 +163,9 @@
this.browserWrapper.removeAttribute('animate-end');
return new Promise((resolve) => {
window.requestAnimationFrame(() => {
this.quickOpenGlance({ dontOpenButtons: true });
this.showSidebarButtons(true);
this.quickOpenGlance();
const newButtons = this.#createNewOverlayButtons();
this.browserWrapper.appendChild(newButtons);
gZenUIManager.motion.animate(
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer'),
@@ -222,9 +209,9 @@
opacity: 1,
},
{
duration: 0.3,
duration: 0.5,
type: 'spring',
bounce: 0.2,
bounce: 0.3,
}
)
.then(() => {
@@ -272,8 +259,11 @@
}
}
if (onTabClose && hasFocused && !this.#confirmationTimeout) {
const cancelButton = document.getElementById('zen-glance-sidebar-close');
const browserSidebarContainer = this.#currentParentTab?.linkedBrowser?.closest(
'.browserSidebarContainer'
);
if (onTabClose && hasFocused && !this.#confirmationTimeout && browserSidebarContainer) {
const cancelButton = browserSidebarContainer?.querySelector('.zen-glance-sidebar-close');
cancelButton.setAttribute('waitconfirmation', true);
this.#confirmationTimeout = setTimeout(() => {
cancelButton.removeAttribute('waitconfirmation');
@@ -284,9 +274,7 @@
this.browserWrapper.removeAttribute('has-finished-animation');
if (noAnimation) {
this._clearContainerStyles(
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer')
);
this._clearContainerStyles(browserSidebarContainer);
this.quickCloseGlance({ closeCurrentTab: false });
return;
}
@@ -311,9 +299,27 @@
this.overlay.style.pointerEvents = 'none';
this.quickCloseGlance({ justAnimateParent: true, clearID: false });
const originalPosition = this.#glances.get(this.#currentGlanceID).originalPosition;
const sidebarButtons = this.browserWrapper.querySelector('.zen-glance-sidebar-container');
if (sidebarButtons) {
gZenUIManager.motion
.animate(
sidebarButtons,
{
opacity: [1, 0],
},
{
duration: 0.2,
type: 'spring',
bounce: 0.2,
}
)
.then(() => {
sidebarButtons.remove();
});
}
gZenUIManager.motion
.animate(
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer'),
browserSidebarContainer,
{
scale: [0.98, 1],
backdropFilter: ['blur(5px)', 'blur(0px)'],
@@ -326,9 +332,7 @@
}
)
.then(() => {
this._clearContainerStyles(
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer')
);
this._clearContainerStyles(browserSidebarContainer);
});
this.browserWrapper.style.opacity = 1;
return new Promise((resolve) => {
@@ -407,14 +411,11 @@
});
}
quickOpenGlance({ dontOpenButtons = false } = {}) {
quickOpenGlance({} = {}) {
if (!this.#currentBrowser || this._duringOpening) {
return;
}
this._duringOpening = true;
if (!dontOpenButtons) {
this.showSidebarButtons();
}
const parentBrowserContainer = this.#currentParentTab.linkedBrowser.closest(
'.browserSidebarContainer'
@@ -443,18 +444,16 @@
clearID = true,
} = {}) {
const parentHasBrowser = !!this.#currentParentTab.linkedBrowser;
this.hideSidebarButtons();
const browserContainer = this.#currentParentTab.linkedBrowser.closest(
'.browserSidebarContainer'
);
if (parentHasBrowser) {
this.#currentParentTab.linkedBrowser
.closest('.browserSidebarContainer')
.classList.remove('zen-glance-background');
browserContainer.classList.remove('zen-glance-background');
}
if (!justAnimateParent && this.overlay) {
if (parentHasBrowser && !this.#currentParentTab.hasAttribute('split-view')) {
if (closeParentTab) {
this.#currentParentTab.linkedBrowser
.closest('.browserSidebarContainer')
.classList.remove('deck-selected');
browserContainer.classList.remove('deck-selected');
}
this.#currentParentTab.linkedBrowser.zenModeActive = false;
}
@@ -484,18 +483,9 @@
}
}
clearConfirmationTimeout() {
if (this.#confirmationTimeout) {
clearTimeout(this.#confirmationTimeout);
this.#confirmationTimeout = null;
}
document.getElementById('zen-glance-sidebar-close')?.removeAttribute('waitconfirmation');
}
// note: must be sync to avoid timing issues
onLocationChange(event) {
const tab = event.target;
this.clearConfirmationTimeout();
if (this.animatingFullOpen || this.closingGlance) {
return;
}
@@ -643,7 +633,10 @@
.closest('.browserSidebarContainer')
.classList.remove('zen-glance-background');
this.#currentParentTab._visuallySelected = false;
this.hideSidebarButtons();
const sidebarButtons = this.browserWrapper.querySelector('.zen-glance-sidebar-container');
if (sidebarButtons) {
sidebarButtons.remove();
}
if (forSplit) {
this.finishOpeningGlance();
return;

View File

@@ -4,40 +4,41 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#zen-glance-sidebar-container {
.zen-glance-sidebar-container {
position: absolute;
display: flex;
z-index: 999;
&[hidden='true'] {
display: none;
}
top: 10%;
transform: translateY(-50%);
padding: 5px;
top: 0;
padding: 12px;
gap: 12px;
max-width: 56px;
&[right='true'] {
right: 2%;
:root[zen-right-side='true'] & {
left: 100%;
}
&[right='false'] {
left: 2%;
:root:not([zen-right-side='true']) & {
right: 100%;
}
& toolbarbutton {
width: 32px;
height: 32px;
background: light-dark(rgb(24, 24, 24), rgb(231, 231, 231));
background: color-mix(
in srgb,
light-dark(rgb(24, 24, 24), rgb(231, 231, 231)) 90%,
var(--zen-primary-color)
);
transition:
background 0.05s ease,
scale 0.05s ease;
border-radius: 999px;
appearance: none;
box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.07);
opacity: 0;
padding: 8px;
opacity: 1 !important;
color: var(--zen-primary-color);
&:hover {
background: light-dark(rgb(41, 41, 41), rgb(204, 204, 204));
@@ -56,12 +57,15 @@
}
}
& image {
filter: invert(1);
&[disabled='true'] {
scale: 1 !important;
& image {
opacity: 0.5;
}
}
}
& #zen-glance-sidebar-close {
& .zen-glance-sidebar-close {
width: fit-content;
& label {
display: block;
@@ -139,7 +143,7 @@
&[animate-full='true'] {
transform: translate(-50%, -50%);
& #zen-glance-sidebar-container {
& .zen-glance-sidebar-container {
opacity: 0 !important;
}
}

View File

@@ -1,5 +1,11 @@
<vbox id="zen-glance-sidebar-container" hidden="true">
<toolbarbutton id="zen-glance-sidebar-close" data-l10n-id="zen-general-confirm" class="toolbarbutton-1"/>
<toolbarbutton id="zen-glance-sidebar-open" class="toolbarbutton-1"/>
<toolbarbutton id="zen-glance-sidebar-split" class="toolbarbutton-1"/>
</vbox>
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
<html:template id="zen-glance-sidebar-template">
<vbox class="zen-glance-sidebar-container">
<toolbarbutton class="zen-glance-sidebar-close toolbarbutton-1" command="cmd_zenGlanceClose" data-l10n-id="zen-general-confirm" />
<toolbarbutton class="zen-glance-sidebar-open toolbarbutton-1" command="cmd_zenGlanceExpand" />
<toolbarbutton class="zen-glance-sidebar-split toolbarbutton-1" command="cmd_zenGlanceSplit" />
</vbox>
</html:template>

View File

@@ -1887,7 +1887,12 @@ class nsZenViewSplitter extends ZenDOMOperatedFeature {
document
.getElementById('cmd_zenSplitViewLinkInNewTab')
.setAttribute('disabled', shouldBeDisabled);
document.getElementById('zen-glance-sidebar-split').setAttribute('disabled', shouldBeDisabled);
const splitGlanceCommand = document.getElementById('cmd_zenGlanceSplit');
if (shouldBeDisabled) {
splitGlanceCommand.setAttribute('disabled', true);
} else {
splitGlanceCommand.removeAttribute('disabled');
}
}
canOpenLinkInSplitView() {

View File

@@ -310,7 +310,10 @@ zen-workspace {
.workspace-arrowscrollbox {
font-size: 14px;
font-weight: 500;
@media not (-moz-platform: linux) {
font-weight: 500;
}
}
/** Customiable UI, this is an auto generated ID */