Refactor: share nav drag and drop logic

This commit is contained in:
MangoPig
2026-06-24 02:11:02 +01:00
parent 69af324b1b
commit 212dd1c435
6 changed files with 626 additions and 712 deletions
@@ -1,3 +1,5 @@
@use "../shared/tree-nav" as treeNav;
.sidebar {
--sidebar-nav-item-min-height: var(--control-size-lg);
position: relative;
@@ -117,56 +119,25 @@
}
.treeSectionLabel {
@include text-caption;
@include treeNav.section-label;
margin: var(--space-3) 0 var(--space-2);
padding: 0 var(--space-3);
color: var(--color-text-subtle);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.treeList {
list-style: none;
display: grid;
gap: var(--space-1);
padding: 0;
@include treeNav.tree-list;
}
.treeEmptySlot {
min-height: calc(var(--control-size-lg) - var(--space-2));
padding-left: calc(var(--space-3) + (var(--tree-depth, 0) * var(--space-4)));
border-radius: var(--radius-lg);
border: 1px dashed color-mix(in srgb, var(--color-border) 38%, transparent);
opacity: 0.35;
@include treeNav.empty-slot;
}
.treeInputRow {
width: 100%;
min-width: 0;
display: grid;
grid-template-columns: auto minmax(0, 1fr);
align-items: center;
gap: var(--space-2);
min-height: calc(var(--control-size-lg) - var(--space-2));
padding: var(--space-2) var(--space-3);
padding-left: calc(var(--space-3) + (var(--tree-depth, 0) * var(--space-4)));
border: 1px solid color-mix(in srgb, var(--color-border) 42%, transparent);
border-radius: var(--radius-lg);
background: color-mix(in srgb, var(--color-surface) 94%, transparent);
@include treeNav.input-row;
}
.treeInput {
width: 100%;
min-width: 0;
border: 0;
background: transparent;
color: var(--color-text);
font: inherit;
outline: none;
}
.treeInput::placeholder {
color: var(--color-text-muted);
@include treeNav.input;
}
.navItem {
@@ -184,125 +155,44 @@
}
.treeItem {
width: 100%;
min-width: 0;
display: grid;
position: relative;
isolation: isolate;
grid-template-columns: auto auto minmax(0, 1fr) auto;
align-items: center;
gap: var(--space-2);
min-height: calc(var(--control-size-lg) - var(--space-2));
padding: var(--space-2) var(--space-3);
padding-left: calc(var(--space-3) + (var(--tree-depth, 0) * var(--space-4)));
border: 0;
border-radius: 0;
background: transparent;
color: var(--color-text-muted);
text-align: left;
transition:
color 160ms var(--easing-standard),
box-shadow 160ms var(--easing-standard),
transform 180ms var(--easing-standard);
&::after {
content: "";
position: absolute;
inset: 0;
border: 1px solid transparent;
border-radius: var(--radius-lg);
background: transparent;
transition:
background 160ms var(--easing-standard),
border-color 160ms var(--easing-standard),
box-shadow 160ms var(--easing-standard);
pointer-events: none;
z-index: 0;
}
> * {
position: relative;
z-index: 1;
}
@include treeNav.item;
}
.treeItem:hover,
.treeItem:focus-visible {
color: var(--color-text);
&::after {
background: color-mix(in srgb, var(--color-surface-hover) 80%, var(--color-accent-soft) 20%);
box-shadow: inset 0 1px 0 color-mix(in srgb, white 4%, transparent);
}
@include treeNav.item-hover;
}
.treeItemFolder {
color: var(--color-text);
@include treeNav.item-folder;
}
.treeItemDragging {
opacity: 0.45;
transform: scale(0.985);
box-shadow: none;
@include treeNav.item-dragging;
}
.treeItemDropBefore {
&::before {
content: "";
position: absolute;
left: calc(var(--space-3) + (var(--tree-depth, 0) * var(--space-4)));
right: var(--space-3);
top: calc((var(--space-1) * -0.5) - 1px);
height: 2px;
border-radius: 999px;
background: color-mix(in srgb, var(--color-accent-strong) 78%, transparent);
pointer-events: none;
z-index: 2;
}
@include treeNav.item-drop-before;
}
.treeItemDropAfter {
&::before {
content: "";
position: absolute;
left: calc(var(--space-3) + (var(--tree-depth, 0) * var(--space-4)));
right: var(--space-3);
bottom: calc((var(--space-1) * -0.5) - 1px);
height: 2px;
border-radius: 999px;
background: color-mix(in srgb, var(--color-accent-strong) 78%, transparent);
pointer-events: none;
z-index: 2;
}
@include treeNav.item-drop-after;
}
.treeItemDropInside {
color: var(--color-text);
&::after {
border-color: color-mix(in srgb, var(--color-accent-strong) 55%, transparent);
background: color-mix(in srgb, var(--color-accent-soft) 36%, var(--color-surface));
box-shadow: inset 0 1px 0 color-mix(in srgb, white 4%, transparent);
}
@include treeNav.item-drop-inside;
}
.folderChevron {
color: var(--color-text-muted);
transition: transform 160ms var(--easing-standard);
@include treeNav.folder-chevron;
}
.folderChevronOpen {
transform: rotate(90deg);
@include treeNav.folder-chevron-open;
}
.treeItemActive {
color: var(--color-text);
&::after {
border-color: var(--color-border);
background: var(--color-surface);
box-shadow: inset 0 1px 0 color-mix(in srgb, white 4%, transparent);
}
@include treeNav.item-active;
}
.navItemActive {
@@ -313,18 +203,15 @@
}
.icon {
color: inherit;
opacity: 0.85;
@include treeNav.icon;
}
.label {
@include text-label;
min-width: 0;
@include treeNav.label;
}
.itemMeta {
@include text-caption;
color: var(--color-text-muted);
@include treeNav.item-meta;
}
.sidebarCollapsed {