diff --git a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.css b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.css
index c3c75ec..e040404 100644
--- a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.css
+++ b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.css
@@ -27,22 +27,31 @@
}
.move-menu-panel {
- /* Solid, non-transparent panel aligned with site menus */
- background: var(--card-bg);
- border: 1px solid var(--border);
- border-radius: 1rem;
- box-shadow:
- 0 16px 42px var(--shadow-color),
- 0 4px 10px color-mix(in srgb, var(--shadow-color) 55%, transparent);
- overflow: hidden;
- backdrop-filter: none;
- opacity: 1;
+ /* Ne pas remettre de background ici: on s'appuie sur bg-card du HTML */
+ position: relative; /* needed for ::before background layer */
+ backdrop-filter: none !important;
+ opacity: 1 !important;
isolation: isolate;
+ mix-blend-mode: normal !important;
+ max-height: min(80vh, 560px);
+ overflow: auto;
+}
+
+/* Solid background layer to guarantee full opacity regardless of ancestors */
+.move-menu-panel::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: var(--card);
+ border-radius: inherit;
+ z-index: -1; /* sit behind content but inside panel */
+ opacity: 1 !important;
+ pointer-events: none;
}
.move-menu-header {
padding: 1rem 1.1rem 0.7rem;
- border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
+ border-bottom: 1px solid color-mix(in srgb, var(--border) 60%);
}
.move-menu-title {
diff --git a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.html b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.html
index ab57ec1..5ca0151 100644
--- a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.html
+++ b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.html
@@ -11,10 +11,14 @@
▾
- @if (showMenu()) {
-
- }
+
diff --git a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.ts b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.ts
index 80fe33f..2ddf187 100644
--- a/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.ts
+++ b/src/app/features/note/components/move-note-to-folder/move-note-to-folder.component.ts
@@ -7,11 +7,16 @@ import {
Input,
Output,
ViewChild,
+ TemplateRef,
+ ViewContainerRef,
computed,
effect,
inject,
signal
} from '@angular/core';
+import { Overlay, OverlayModule, OverlayRef, ConnectedPosition } from '@angular/cdk/overlay';
+import { TemplatePortal, PortalModule } from '@angular/cdk/portal';
+import { A11yModule } from '@angular/cdk/a11y';
import { splitPathKeepFilename } from '../../../../shared/utils/path';
import { ToastService } from '../../../../shared/toast/toast.service';
import { VaultService } from '../../../../../services/vault.service';
@@ -32,7 +37,7 @@ interface FlattenedFolder {
@Component({
selector: 'app-move-note-to-folder',
standalone: true,
- imports: [CommonModule],
+ imports: [CommonModule, OverlayModule, PortalModule, A11yModule],
templateUrl: './move-note-to-folder.component.html',
styleUrls: ['./move-note-to-folder.component.css']
})
@@ -49,6 +54,7 @@ export class MoveNoteToFolderComponent {
@ViewChild('searchField') searchField?: ElementRef;
@ViewChild('trigger') trigger?: ElementRef;
+ @ViewChild('panelTpl') panelTpl?: TemplateRef;
readonly showMenu = signal(false);
readonly searchQuery = signal('');
@@ -95,6 +101,9 @@ export class MoveNoteToFolderComponent {
private readonly toast = inject(ToastService);
private readonly destroyRef = inject(DestroyRef);
private readonly host = inject(ElementRef);
+ private readonly overlay = inject(Overlay);
+ private readonly vcr = inject(ViewContainerRef);
+ private overlayRef?: OverlayRef;
private listenersAttached = false;
@@ -107,6 +116,15 @@ export class MoveNoteToFolderComponent {
{ allowSignalWrites: true }
);
+ this.destroyRef.onDestroy(() => {
+ this.detachGlobalListeners();
+ if (this.overlayRef) {
+ try { this.overlayRef.detach(); } catch {}
+ try { this.overlayRef.dispose(); } catch {}
+ this.overlayRef = undefined;
+ }
+ });
+
effect(
() => {
const path = this.currentFolderPath();
@@ -132,7 +150,29 @@ export class MoveNoteToFolderComponent {
this.attachGlobalListeners();
queueMicrotask(() => {
- this.computeMenuPosition();
+ const tpl = this.panelTpl;
+ if (!tpl) return;
+
+ const positionStrategy = this.overlay
+ .position()
+ .global()
+ .centerHorizontally()
+ .centerVertically();
+
+ this.overlayRef = this.overlay.create({
+ hasBackdrop: true,
+ backdropClass: 'ov-blur-backdrop',
+ positionStrategy,
+ scrollStrategy: this.overlay.scrollStrategies.reposition()
+ });
+
+ this.overlayRef.backdropClick().subscribe(() => this.closeMenu());
+ this.overlayRef.keydownEvents().subscribe((e) => {
+ if (e.key === 'Escape') this.closeMenu();
+ });
+
+ const portal = new TemplatePortal(tpl, this.vcr);
+ this.overlayRef.attach(portal);
setTimeout(() => this.focusSearchField(), 0);
});
}
@@ -303,6 +343,11 @@ export class MoveNoteToFolderComponent {
private closeMenu(): void {
this.showMenu.set(false);
+ if (this.overlayRef) {
+ try { this.overlayRef.detach(); } catch {}
+ try { this.overlayRef.dispose(); } catch {}
+ this.overlayRef = undefined;
+ }
this.detachGlobalListeners();
this.searchQuery.set('');
this.processingPath.set(null);
@@ -319,18 +364,8 @@ export class MoveNoteToFolderComponent {
}
}
- private computeMenuPosition(): void {
- const t = this.trigger?.nativeElement;
- if (!t) return;
- const rect = t.getBoundingClientRect();
- // Place menu just under the trigger (fixed panel -> viewport coords)
- this.menuTop.set(Math.round(rect.bottom + 8));
- // Align left edge; clamp to viewport
- const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
- const desiredLeft = Math.round(rect.left);
- const clampedLeft = Math.min(Math.max(8, desiredLeft), vw - 8 - 320); // ~w-80
- this.menuLeft.set(clampedLeft);
- }
+ private computeMenuPosition(): void {}
+ private repositionPanel(): void {}
private attachGlobalListeners(): void {
if (typeof document === 'undefined' || this.listenersAttached) {
@@ -354,7 +389,10 @@ export class MoveNoteToFolderComponent {
if (!this.showMenu()) {
return;
}
- if (!this.host.nativeElement.contains(event.target as Node)) {
+ const target = event.target as Node;
+ const hostContains = this.host.nativeElement.contains(target);
+ const overlayContains = this.overlayRef?.overlayElement.contains(target) ?? false;
+ if (!hostContains && !overlayContains) {
this.closeMenu();
}
};
@@ -365,6 +403,16 @@ export class MoveNoteToFolderComponent {
}
};
+ onSearchEnter(event: KeyboardEvent): void {
+ event.preventDefault();
+ if (this.isSearching() && this.searchResults().length > 0) {
+ const first = this.searchResults()[0];
+ this.onSearchResultSelected(first);
+ return;
+ }
+ this.moveToCurrentFolder();
+ }
+
private normalizeFolderPath(value: string | null | undefined): string {
return (value ?? '')
.replace(/\\/g, '/')
diff --git a/src/app/features/note/components/note-header/note-header.component.html b/src/app/features/note/components/note-header/note-header.component.html
index bf27b70..c0f502f 100644
--- a/src/app/features/note/components/note-header/note-header.component.html
+++ b/src/app/features/note/components/note-header/note-header.component.html
@@ -1,7 +1,7 @@