Add custom scroll-into-view for tree items with smooth positioning and improve sidebar panel collapse animations with flex-based layout transitions
This commit is contained in:
parent
a42f61e59a
commit
7aec49776e
@ -232,6 +232,30 @@
|
|||||||
if (quickSelect) quickSelect.value = selectedContextVault;
|
if (quickSelect) quickSelect.value = selectedContextVault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scrollTreeItemIntoView(element, alignToTop) {
|
||||||
|
if (!element) return;
|
||||||
|
const scrollContainer = document.getElementById("vault-panel-content");
|
||||||
|
if (!scrollContainer) return;
|
||||||
|
|
||||||
|
const containerRect = scrollContainer.getBoundingClientRect();
|
||||||
|
const elementRect = element.getBoundingClientRect();
|
||||||
|
const isAbove = elementRect.top < containerRect.top;
|
||||||
|
const isBelow = elementRect.bottom > containerRect.bottom;
|
||||||
|
|
||||||
|
if (!isAbove && !isBelow && !alignToTop) return;
|
||||||
|
|
||||||
|
const currentTop = scrollContainer.scrollTop;
|
||||||
|
const offsetTop = element.offsetTop;
|
||||||
|
const targetTop = alignToTop
|
||||||
|
? Math.max(0, offsetTop - 8)
|
||||||
|
: Math.max(0, currentTop + (elementRect.top - containerRect.top) - (containerRect.height * 0.35));
|
||||||
|
|
||||||
|
scrollContainer.scrollTo({
|
||||||
|
top: targetTop,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshSidebarForContext() {
|
async function refreshSidebarForContext() {
|
||||||
const container = document.getElementById("vault-tree");
|
const container = document.getElementById("vault-tree");
|
||||||
container.innerHTML = "";
|
container.innerHTML = "";
|
||||||
@ -267,7 +291,7 @@
|
|||||||
if (childContainer && childContainer.classList.contains("collapsed")) {
|
if (childContainer && childContainer.classList.contains("collapsed")) {
|
||||||
await toggleVault(vaultItem, vaultName, true);
|
await toggleVault(vaultItem, vaultName, true);
|
||||||
}
|
}
|
||||||
vaultItem.scrollIntoView({ block: "nearest" });
|
scrollTreeItemIntoView(vaultItem, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshTagsForContext() {
|
async function refreshTagsForContext() {
|
||||||
@ -323,6 +347,8 @@
|
|||||||
const childContainer = document.getElementById(`vault-children-${vaultName}`);
|
const childContainer = document.getElementById(`vault-children-${vaultName}`);
|
||||||
if (!childContainer) return;
|
if (!childContainer) return;
|
||||||
|
|
||||||
|
scrollTreeItemIntoView(itemEl, false);
|
||||||
|
|
||||||
const shouldExpand = forceExpand || childContainer.classList.contains("collapsed");
|
const shouldExpand = forceExpand || childContainer.classList.contains("collapsed");
|
||||||
|
|
||||||
if (shouldExpand) {
|
if (shouldExpand) {
|
||||||
@ -364,6 +390,7 @@
|
|||||||
fragment.appendChild(subContainer);
|
fragment.appendChild(subContainer);
|
||||||
|
|
||||||
dirItem.addEventListener("click", async () => {
|
dirItem.addEventListener("click", async () => {
|
||||||
|
scrollTreeItemIntoView(dirItem, false);
|
||||||
if (subContainer.classList.contains("collapsed")) {
|
if (subContainer.classList.contains("collapsed")) {
|
||||||
if (subContainer.children.length === 0) {
|
if (subContainer.children.length === 0) {
|
||||||
await loadDirectory(vaultName, item.path, subContainer);
|
await loadDirectory(vaultName, item.path, subContainer);
|
||||||
@ -387,6 +414,7 @@
|
|||||||
document.createTextNode(` ${displayName}`),
|
document.createTextNode(` ${displayName}`),
|
||||||
]);
|
]);
|
||||||
fileItem.addEventListener("click", () => {
|
fileItem.addEventListener("click", () => {
|
||||||
|
scrollTreeItemIntoView(fileItem, false);
|
||||||
openFile(vaultName, item.path);
|
openFile(vaultName, item.path);
|
||||||
closeMobileSidebar();
|
closeMobileSidebar();
|
||||||
});
|
});
|
||||||
@ -747,6 +775,7 @@
|
|||||||
|
|
||||||
function setPanelExpanded(panelKey, expanded) {
|
function setPanelExpanded(panelKey, expanded) {
|
||||||
panelState[panelKey] = expanded;
|
panelState[panelKey] = expanded;
|
||||||
|
const sidebar = document.getElementById("sidebar");
|
||||||
const toggle = document.getElementById(`${panelKey}-panel-toggle`);
|
const toggle = document.getElementById(`${panelKey}-panel-toggle`);
|
||||||
const content = document.getElementById(`${panelKey}-panel-content`);
|
const content = document.getElementById(`${panelKey}-panel-content`);
|
||||||
if (!toggle || !content) return;
|
if (!toggle || !content) return;
|
||||||
@ -762,6 +791,10 @@
|
|||||||
if (tagSection) tagSection.classList.toggle("collapsed-panel", !expanded);
|
if (tagSection) tagSection.classList.toggle("collapsed-panel", !expanded);
|
||||||
if (resizeHandle) resizeHandle.classList.toggle("hidden", !expanded);
|
if (resizeHandle) resizeHandle.classList.toggle("hidden", !expanded);
|
||||||
}
|
}
|
||||||
|
if (sidebar) {
|
||||||
|
sidebar.classList.toggle("vault-collapsed", !panelState.vault);
|
||||||
|
sidebar.classList.toggle("tag-collapsed", !panelState.tag);
|
||||||
|
}
|
||||||
safeCreateIcons();
|
safeCreateIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -314,6 +314,17 @@ a:hover {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar.vault-collapsed .tag-cloud-section {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar.tag-collapsed .sidebar-tree {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* --- Sidebar filter --- */
|
/* --- Sidebar filter --- */
|
||||||
.sidebar-filter {
|
.sidebar-filter {
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
@ -347,9 +358,11 @@ a:hover {
|
|||||||
|
|
||||||
.sidebar-tree {
|
.sidebar-tree {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow: hidden;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-tree::-webkit-scrollbar {
|
.sidebar-tree::-webkit-scrollbar {
|
||||||
@ -396,7 +409,29 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-panel-content.collapsed {
|
.sidebar-panel-content.collapsed {
|
||||||
display: none;
|
max-height: 0 !important;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-panel-content {
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 1;
|
||||||
|
transition: max-height 340ms ease, opacity 220ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#vault-panel-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 1000px;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tag-panel-content {
|
||||||
|
max-height: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-item {
|
.tree-item {
|
||||||
@ -446,6 +481,7 @@ a:hover {
|
|||||||
|
|
||||||
.tree-children {
|
.tree-children {
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-children.collapsed {
|
.tree-children.collapsed {
|
||||||
@ -476,14 +512,18 @@ a:hover {
|
|||||||
height: 180px;
|
height: 180px;
|
||||||
min-height: 60px;
|
min-height: 60px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
overflow: hidden;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: height 340ms ease, min-height 340ms ease, max-height 340ms ease, flex 340ms ease;
|
||||||
}
|
}
|
||||||
.tag-cloud-section.collapsed-panel {
|
.tag-cloud-section.collapsed-panel {
|
||||||
height: auto;
|
height: auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
.tag-cloud-section::-webkit-scrollbar {
|
.tag-cloud-section::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
@ -510,6 +550,11 @@ a:hover {
|
|||||||
padding: 0 16px 12px;
|
padding: 0 16px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-cloud-section:not(.collapsed-panel) #tag-panel-content {
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.tag-item {
|
.tag-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
@ -1281,6 +1326,14 @@ body.resizing-v {
|
|||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#vault-panel-content {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tag-panel-content {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
.help-content {
|
.help-content {
|
||||||
padding: 20px 16px 28px;
|
padding: 20px 16px 28px;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user