chore(layout): revert work on floating panel

This commit is contained in:
Elian Doran 2025-12-09 19:07:50 +02:00
parent 9445e64c2e
commit 28bb4edbac
No known key found for this signature in database
8 changed files with 34 additions and 79 deletions

View File

@ -498,6 +498,10 @@ type EventMappings = {
noteIds: string[];
};
refreshData: { ntxId: string | null | undefined };
contentSafeMarginChanged: {
top: number;
noteContext: NoteContext;
}
};
export type EventListener<T extends EventNames> = {

View File

@ -138,21 +138,21 @@ export default class DesktopLayout {
.child(<ClosePaneButton />)
.child(<CreatePaneButton />)
)
.child(new FlexContainer("row")
.class("title-row")
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
)
.child(<Ribbon />)
.child(new WatchedFileUpdateStatusWidget())
.child(<FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
.child(
new ScrollingContainer()
.filling()
.child(new ContentHeader()
.child(new FlexContainer("row")
.class("title-row")
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
)
.child(<ReadOnlyNoteInfoBar />)
.child(<SharedInfo />)
)
.child(<Ribbon />)
.child(<PromotedAttributes />)
.child(<SqlTableSchemas />)
.child(<NoteDetail />)

View File

@ -178,15 +178,3 @@ ul.editability-dropdown li.dropdown-item > div {
.note-info-widget {
container: info-section / inline-size;
}
/*
* Styling as a floating toolbar
*/
.ribbon-container {
position: sticky;
top: 0;
left: 0;
right: 0;
background: var(--main-background-color);
z-index: 997;
}

View File

@ -6,12 +6,11 @@
.floating-buttons-children,
.show-floating-buttons {
position: absolute;
top: calc(var(--floating-buttons-vert-offset, 14px) + var(--ribbon-height, 0px) + var(--content-header-height, 0px));
top: var(--floating-buttons-vert-offset, 14px);
inset-inline-end: var(--floating-buttons-horiz-offset, 10px);
display: flex;
flex-direction: row;
z-index: 100;
transition: top 0.3s ease;
}
.note-split.rtl .floating-buttons-children,

View File

@ -48,6 +48,12 @@ export default function FloatingButtons({ items }: FloatingButtonsProps) {
const [ visible, setVisible ] = useState(true);
useEffect(() => setVisible(true), [ note ]);
useTriliumEvent("contentSafeMarginChanged", (e) => {
if (e.noteContext === noteContext) {
setTop(e.top);
}
});
return (
<div className="floating-buttons no-print" style={{top}}>
<div className={`floating-buttons-children ${!visible ? "temporarily-hidden" : ""}`}>
@ -87,9 +93,9 @@ function CloseFloatingButton({ setVisible }: { setVisible(visible: boolean): voi
className="close-floating-buttons-button"
icon="bx bx-chevrons-right"
text={t("hide_floating_buttons_button.button_title")}
onClick={() => setVisible(false)}
onClick={() => setVisible(false)}
noIconActionClass
/>
</div>
);
}
}

View File

@ -1,15 +1 @@
.content-header-widget {
position: relative;
z-index: 998;
background-color: var(--main-background-color);
}
.note-split.bgfx .content-header-widget {
background-color: transparent;
}
.content-header-widget.floating {
position: sticky;
top: 0;
background-color: var(--main-background-color, #fff) !important;
}
/** Intentionally left empty for now **/

View File

@ -2,19 +2,15 @@ import { EventData } from "../../components/app_context";
import BasicWidget from "../basic_widget";
import Container from "./container";
import NoteContext from "../../components/note_context";
import "./content_header.css";
export default class ContentHeader extends Container<BasicWidget> {
noteContext?: NoteContext;
thisElement?: HTMLElement;
parentElement?: HTMLElement;
resizeObserver: ResizeObserver;
currentHeight: number = 0;
currentSafeMargin: number = NaN;
previousScrollTop: number = 0;
isFloating: boolean = false;
scrollThreshold: number = 10; // pixels before triggering float
constructor() {
super();
@ -39,44 +35,19 @@ export default class ContentHeader extends Container<BasicWidget> {
this.thisElement = this.$widget.get(0)!;
this.resizeObserver.observe(this.thisElement);
this.parentElement.addEventListener("scroll", this.updateScrollState.bind(this), { passive: true });
}
updateScrollState() {
const currentScrollTop = this.parentElement!.scrollTop;
const isScrollingUp = currentScrollTop < this.previousScrollTop;
const hasDropdownOpen = this.thisElement!.querySelector(".dropdown-menu.show") !== null;
const hasMovedEnough = Math.abs(currentScrollTop - this.previousScrollTop) > this.scrollThreshold;
if (hasDropdownOpen) {
this.setFloating(true);
} else if (currentScrollTop === 0) {
this.setFloating(false);
} else if (hasMovedEnough) {
this.setFloating(isScrollingUp);
}
this.previousScrollTop = currentScrollTop;
this.updateSafeMargin();
}
setFloating(shouldFloat: boolean) {
if (shouldFloat !== this.isFloating) {
this.isFloating = shouldFloat;
if (shouldFloat) {
this.$widget.addClass("floating");
} else {
this.$widget.removeClass("floating");
}
}
this.parentElement.addEventListener("scroll", this.updateSafeMargin.bind(this));
}
updateSafeMargin() {
const parentEl = this.parentElement?.closest<HTMLDivElement>(".note-split");
if (this.isFloating || this.parentElement!.scrollTop === 0) {
parentEl!.style.setProperty("--content-header-height", `${this.currentHeight}px`);
} else {
parentEl!.style.removeProperty("--content-header-height");
const newSafeMargin = Math.max(this.currentHeight - this.parentElement!.scrollTop, 0);
if (newSafeMargin !== this.currentSafeMargin) {
this.currentSafeMargin = newSafeMargin;
this.triggerEvent("contentSafeMarginChanged", {
top: newSafeMargin,
noteContext: this.noteContext!
});
}
}
@ -89,4 +60,4 @@ export default class ContentHeader extends Container<BasicWidget> {
}
}
}
}

View File

@ -17,6 +17,7 @@
.info-bar-subtle {
color: var(--muted-text-color);
background: var(--main-background-color);
border-bottom: 1px solid var(--main-border-color);
margin-block: 0;
padding-inline: 22px;
}
}