improved sticky folders

This commit is contained in:
vcoppe committed 2026-10-17 16:39:41 +02:00
1 parent 593b43e433
commit 970cf7d1e1
8 files changed
+180 -54

No files matched your search

@@ -2,7 +2,6 @@
import { CollapsibleTree, CollapsibleTreeNode } from '$lib/components/collapsible-tree/index';
import { ScrollArea } from '$lib/components/ui/scroll-area/index';
import ExplorerTree from './ExplorerTree.svelte';
import { stickyRowStyle } from './sticky';
import { i18n } from '$lib/i18n/i18n.svelte';
import { engine } from '$lib/engine';
import { folderName } from '$lib/engine/workspace';
@@ -24,12 +23,8 @@
<!-- starts over when another folder is opened -->
{#key folder}
<!-- the folder itself, which is open at first -->
<CollapsibleTree side="left" defaultState="open">
<CollapsibleTreeNode
id="folder"
triggerClass="sticky flex items-center bg-background"
triggerStyle={stickyRowStyle(0)}
>
<CollapsibleTree side="left" defaultState="open" sticky>
<CollapsibleTreeNode id="folder">
{#snippet trigger()}
<span class="grow truncate text-left" title={folder}>
{folderName(folder)}
@@ -3,7 +3,6 @@
import { Button } from '$lib/components/ui/button';
import { FileText } from '@lucide/svelte';
import ExplorerTree from './ExplorerTree.svelte';
import { stickyRowStyle } from './sticky';
import { openPath } from '$lib/actions/file-actions';
import { engine, type FolderEntry } from '$lib/engine';
import { selectedFileIds } from '$lib/engine/selection-helpers';
@@ -11,12 +10,9 @@
let {
path,
depth = 1,
}: {
/** The folder whose content is listed, the open folder if it is not given. */
path?: string;
/** How many folders deep the folders listed are (the open folder is 0). */
depth?: number;
} = $props();
const { workspace, selection, folderVersion } = engine;
@@ -49,11 +45,7 @@
{#each entries as entry (entry.path)}
{#if entry.isDir}
<CollapsibleTreeNode
id={entry.name}
triggerClass="sticky flex items-center bg-background"
triggerStyle={stickyRowStyle(depth)}
>
<CollapsibleTreeNode id={entry.name}>
{#snippet trigger()}
<span class="grow truncate text-left">{entry.name}</span>
{/snippet}
@@ -61,7 +53,7 @@
<!-- the content of a folder is only read when it is opened -->
{#if opened}
<div class="ml-4">
<ExplorerTree path={entry.path} depth={depth + 1} />
<ExplorerTree path={entry.path} />
</div>
{/if}
{/snippet}
@@ -1,17 +0,0 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { rowHeight, stickyRowStyle } from './sticky';
describe('stickyRowStyle', () => {
it('puts each row under the ones of the folders it is in', () => {
assert.match(stickyRowStyle(0), /top: 0px/);
assert.match(stickyRowStyle(2), new RegExp(`top: ${2 * rowHeight}px`));
});
it('puts the rows of the folders above over the rows below', () => {
const zIndex = (depth: number) => Number(/z-index: (\d+)/.exec(stickyRowStyle(depth))![1]);
assert.ok(zIndex(0) > zIndex(1));
assert.ok(zIndex(1) > zIndex(5));
assert.ok(zIndex(500) >= 1);
});
});
@@ -1,11 +0,0 @@
/** The height of a row of the explorer. */
export const rowHeight = 28;
/**
* The style of the row of a folder that is `depth` folders deep (0 for the open folder), to stick
* under the rows of the folders it is in while any of its content can be seen: the rows of the
* folders above are above it too.
*/
export function stickyRowStyle(depth: number): string {
return `top: ${depth * rowHeight}px; height: ${rowHeight}px; z-index: ${Math.max(100 - depth, 1)};`;
}