diff --git a/website/src/lib/components/collapsible-tree/CollapsibleTree.svelte b/website/src/lib/components/collapsible-tree/CollapsibleTree.svelte index 4c55f0a65..ad9269fb9 100644 --- a/website/src/lib/components/collapsible-tree/CollapsibleTree.svelte +++ b/website/src/lib/components/collapsible-tree/CollapsibleTree.svelte @@ -1,18 +1,26 @@ {@render children()} diff --git a/website/src/lib/components/collapsible-tree/CollapsibleTreeNode.svelte b/website/src/lib/components/collapsible-tree/CollapsibleTreeNode.svelte index ddd11dac6..1352fabd6 100644 --- a/website/src/lib/components/collapsible-tree/CollapsibleTreeNode.svelte +++ b/website/src/lib/components/collapsible-tree/CollapsibleTreeNode.svelte @@ -5,37 +5,58 @@ import { getContext, setContext, type Snippet } from 'svelte'; import type { ClassValue } from 'svelte/elements'; import type { CollapsibleTreeState } from './utils.svelte'; + import { stickyKey, stickyZIndex, trackStuck, type StickyLevel } from './sticky'; const props: { id: string | number; class?: ClassValue; trigger: Snippet; - /** Classes and style of the trigger row (when the trigger holds the content), to make it stick. */ - triggerClass?: ClassValue; - triggerStyle?: string; /** Gets whether the node is open, for contents that are only worth building then. */ content: Snippet<[boolean]>; } = $props(); - let state = getContext('collapsible-tree-state'); + let treeState = getContext('collapsible-tree-state'); let side = getContext<'left' | 'right'>('collapsible-tree-side'); let nohover = getContext('collapsible-tree-nohover'); let slotInsideTrigger = getContext('collapsible-tree-slot-inside-trigger'); let parentId = getContext('collapsible-tree-parent-id'); + // where the row sticks, under the rows of the nodes this one is in + let level = getContext(stickyKey); let fullId = `${parentId}.${props.id}`; setContext('collapsible-tree-parent-id', fullId); - let open = state.get(fullId); + let open = treeState.get(fullId); + + // the rows of the nodes in this one stick under this row, whatever its height + let rowHeight = $state(0); + setContext(stickyKey, { + get enabled() { + return level.enabled; + }, + get top() { + return level.top + rowHeight; + }, + get depth() { + return level.depth + 1; + }, + get stuckRows() { + return level.stuckRows; + }, + }); + // the row is on top of the content that goes under it + let stuck = $state(false); + // only the deepest row that is stuck has a border: the rows above it run into it + let bordered = $derived(stuck && level.stuckRows.deepest === level.depth); export function openNode() { open.current = true; } - +{#snippet row()} {#if slotInsideTrigger} - +