chore(right_pane): basic collapse support

This commit is contained in:
Elian Doran 2025-12-18 14:42:21 +02:00
parent b5bfb02d96
commit 682c61305c
No known key found for this signature in database
3 changed files with 63 additions and 8 deletions

View File

@ -13,5 +13,9 @@ body.experimental-feature-new-layout #right-pane {
&:last-of-type { &:last-of-type {
border-bottom: 0; border-bottom: 0;
} }
&.collapsed .card-header > .bx {
transform: rotate(-90deg);
}
} }
} }

View File

@ -2,7 +2,8 @@
import "./RightPanelContainer.css"; import "./RightPanelContainer.css";
import Split from "@triliumnext/split.js"; import Split from "@triliumnext/split.js";
import { useEffect } from "preact/hooks"; import { createContext } from "preact";
import { useEffect, useRef } from "preact/hooks";
import options from "../../services/options"; import options from "../../services/options";
import { DEFAULT_GUTTER_SIZE } from "../../services/resizer"; import { DEFAULT_GUTTER_SIZE } from "../../services/resizer";
@ -10,6 +11,11 @@ import HighlightsList from "./HighlightsList";
import TableOfContents from "./TableOfContents"; import TableOfContents from "./TableOfContents";
const MIN_WIDTH_PERCENT = 5; const MIN_WIDTH_PERCENT = 5;
const COLLAPSED_SIZE = 32;
export const RightPanelContext = createContext({
setExpanded(cardEl: HTMLElement, expanded: boolean) {}
});
export default function RightPanelContainer() { export default function RightPanelContainer() {
// Split between right pane and the content pane. // Split between right pane and the content pane.
@ -32,19 +38,46 @@ export default function RightPanelContainer() {
]; ];
// Split between items. // Split between items.
const innerSplitRef = useRef<Split.Instance>(null);
useEffect(() => { useEffect(() => {
const rightPaneContainer = document.getElementById("right-pane"); const rightPaneContainer = document.getElementById("right-pane");
const elements = Array.from(rightPaneContainer?.children ?? []) as HTMLElement[]; const elements = Array.from(rightPaneContainer?.children ?? []) as HTMLElement[];
console.log("Got ", elements);
const splitInstance = Split(elements, { const splitInstance = Split(elements, {
direction: "vertical" direction: "vertical",
minSize: COLLAPSED_SIZE,
gutterSize: 1
}); });
innerSplitRef.current = splitInstance;
return () => splitInstance.destroy(); return () => splitInstance.destroy();
}, [ items ]); }, [ items ]);
return ( return (
<div id="right-pane"> <div id="right-pane">
{items} <RightPanelContext.Provider value={{
setExpanded(cardEl, expanded) {
const splitInstance = innerSplitRef.current;
if (!splitInstance) return;
const rightPaneEl = document.getElementById("right-pane");
const children = Array.from(rightPaneEl?.querySelectorAll(":scope > .card") ?? []);
const pos = children.indexOf(cardEl);
if (pos === -1) return;
const sizes = splitInstance.getSizes();
if (!expanded) {
const sizeBeforeCollapse = sizes[pos];
sizes[pos] = 0;
const itemToExpand = pos > 0 ? pos - 1 : pos + 1;
if (sizes[itemToExpand] > COLLAPSED_SIZE) {
sizes[itemToExpand] += sizeBeforeCollapse;
}
}
console.log("Set sizes to ", sizes);
splitInstance.setSizes(sizes);
},
}}>
{items}
</RightPanelContext.Provider>
</div> </div>
); );
} }

View File

@ -1,6 +1,10 @@
import { useContext, useRef } from "preact/hooks"; import clsx from "clsx";
import { ParentComponent } from "../react/react_utils";
import { ComponentChildren } from "preact"; import { ComponentChildren } from "preact";
import { useContext, useRef, useState } from "preact/hooks";
import Icon from "../react/Icon";
import { ParentComponent } from "../react/react_utils";
import { RightPanelContext } from "./RightPanelContainer";
interface RightPanelWidgetProps { interface RightPanelWidgetProps {
title: string; title: string;
@ -9,6 +13,8 @@ interface RightPanelWidgetProps {
} }
export default function RightPanelWidget({ title, buttons, children }: RightPanelWidgetProps) { export default function RightPanelWidget({ title, buttons, children }: RightPanelWidgetProps) {
const rightPanelContext = useContext(RightPanelContext);
const [ expanded, setExpanded ] = useState(true);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const parentComponent = useContext(ParentComponent); const parentComponent = useContext(ParentComponent);
@ -17,15 +23,27 @@ export default function RightPanelWidget({ title, buttons, children }: RightPane
} }
return ( return (
<div ref={containerRef} class="card widget" style={{contain: "none"}}> <div
ref={containerRef}
class={clsx("card widget", !expanded && "collapsed")}
>
<div class="card-header"> <div class="card-header">
<Icon
icon="bx bx-chevron-down"
onClick={() => {
if (containerRef.current) {
rightPanelContext.setExpanded(containerRef.current, !expanded);
}
setExpanded(!expanded);
}}
/>
<div class="card-header-title">{title}</div> <div class="card-header-title">{title}</div>
<div class="card-header-buttons">{buttons}</div> <div class="card-header-buttons">{buttons}</div>
</div> </div>
<div id={parentComponent?.componentId} class="body-wrapper"> <div id={parentComponent?.componentId} class="body-wrapper">
<div class="card-body"> <div class="card-body">
{children} {expanded && children}
</div> </div>
</div> </div>
</div> </div>