feat(editor): resizable outline panel (#161)

Add a drag handle to resize the outline panel and persist its width in
vault state (outline_width). Outline text now scales with the editor
font size.

Reviewed-on: https://codeberg.org/ArkHost/HelixNotes/pulls/161
This commit is contained in:
mf
2026-06-24 21:01:43 +02:00
committed by ArkHost
parent 16805c96aa
commit f98b3415bc
5 changed files with 26 additions and 4 deletions
+7
View File
@@ -197,6 +197,10 @@ fn default_true() -> bool {
true true
} }
fn default_outline_width() -> f64 {
220.0
}
fn default_pdf_height() -> u32 { fn default_pdf_height() -> u32 {
600 600
} }
@@ -298,6 +302,8 @@ pub struct VaultState {
pub last_open_note: Option<String>, pub last_open_note: Option<String>,
pub sidebar_width: f64, pub sidebar_width: f64,
pub notelist_width: f64, pub notelist_width: f64,
#[serde(default = "default_outline_width")]
pub outline_width: f64,
pub sidebar_collapsed: bool, pub sidebar_collapsed: bool,
#[serde(default)] #[serde(default)]
pub notelist_collapsed: bool, pub notelist_collapsed: bool,
@@ -333,6 +339,7 @@ impl Default for VaultState {
last_open_note: None, last_open_note: None,
sidebar_width: 220.0, sidebar_width: 220.0,
notelist_width: 280.0, notelist_width: 280.0,
outline_width: default_outline_width(),
sidebar_collapsed: false, sidebar_collapsed: false,
notelist_collapsed: false, notelist_collapsed: false,
collapsed_notebooks: Vec::new(), collapsed_notebooks: Vec::new(),
+4
View File
@@ -14,6 +14,7 @@
import { import {
sidebarWidth, sidebarWidth,
notelistWidth, notelistWidth,
outlineWidth,
sidebarCollapsed, sidebarCollapsed,
notelistCollapsed, notelistCollapsed,
collapsedNotebooks, collapsedNotebooks,
@@ -201,6 +202,7 @@
last_open_note: $activeNotePath, last_open_note: $activeNotePath,
sidebar_width: $sidebarWidth, sidebar_width: $sidebarWidth,
notelist_width: $notelistWidth, notelist_width: $notelistWidth,
outline_width: $outlineWidth,
sidebar_collapsed: $sidebarCollapsed, sidebar_collapsed: $sidebarCollapsed,
notelist_collapsed: $notelistCollapsed, notelist_collapsed: $notelistCollapsed,
collapsed_notebooks: $collapsedNotebooks, collapsed_notebooks: $collapsedNotebooks,
@@ -534,6 +536,7 @@
$effect(() => { $effect(() => {
$sidebarCollapsed; $sidebarCollapsed;
$notelistCollapsed; $notelistCollapsed;
$outlineWidth;
persistState(); persistState();
}); });
@@ -573,6 +576,7 @@
const state = await loadVaultState(); const state = await loadVaultState();
$sidebarWidth = state.sidebar_width; $sidebarWidth = state.sidebar_width;
$notelistWidth = state.notelist_width; $notelistWidth = state.notelist_width;
if (typeof state.outline_width === 'number') $outlineWidth = state.outline_width;
$sidebarCollapsed = state.sidebar_collapsed; $sidebarCollapsed = state.sidebar_collapsed;
$notelistCollapsed = state.notelist_collapsed ?? false; $notelistCollapsed = state.notelist_collapsed ?? false;
$collapsedNotebooks = state.collapsed_notebooks ?? []; $collapsedNotebooks = state.collapsed_notebooks ?? [];
+10 -4
View File
@@ -39,7 +39,7 @@
import { readFile } from '@tauri-apps/plugin-fs'; import { readFile } from '@tauri-apps/plugin-fs';
import { openFile, openUrl, copyFileTo, copyImageToClipboard as copyImageToClipboardCmd, writeBytesTo, copyPngToClipboard } from '$lib/api'; import { openFile, openUrl, copyFileTo, copyImageToClipboard as copyImageToClipboardCmd, writeBytesTo, copyPngToClipboard } from '$lib/api';
import { save as saveDialog } from '@tauri-apps/plugin-dialog'; import { save as saveDialog } from '@tauri-apps/plugin-dialog';
import { activeNote, activeNotePath, appConfig, editorDirty, sourceMode, focusMode, readOnly, quickAccessPaths, notes, navHistory, canGoBack, canGoForward, viewerNote, notebooks } from '$lib/stores/app'; import { activeNote, activeNotePath, appConfig, editorDirty, sourceMode, focusMode, readOnly, quickAccessPaths, notes, navHistory, canGoBack, canGoForward, viewerNote, notebooks, outlineWidth } from '$lib/stores/app';
import { saveNote, saveImage, saveAttachment, readClipboardImage, addQuickAccess, removeQuickAccess, getQuickAccess, getNoteVersions, getNoteVersionContent, createVersion, aiAsk, getAllNoteTitles, readNote, renameNote } from '$lib/api'; import { saveNote, saveImage, saveAttachment, readClipboardImage, addQuickAccess, removeQuickAccess, getQuickAccess, getNoteVersions, getNoteVersionContent, createVersion, aiAsk, getAllNoteTitles, readNote, renameNote } from '$lib/api';
import type { VersionEntry, AiStreamEvent, NoteTitleEntry } from '$lib/types'; import type { VersionEntry, AiStreamEvent, NoteTitleEntry } from '$lib/types';
import { listen } from '@tauri-apps/api/event'; import { listen } from '@tauri-apps/api/event';
@@ -50,6 +50,7 @@
import GraphView from './GraphView.svelte'; import GraphView from './GraphView.svelte';
import TagSuggestInput from './TagSuggestInput.svelte'; import TagSuggestInput from './TagSuggestInput.svelte';
import { isMobile, isAndroid } from '$lib/platform'; import { isMobile, isAndroid } from '$lib/platform';
import ResizeHandle from './ResizeHandle.svelte';
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'; const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
@@ -178,6 +179,10 @@
outlineHeadings = headings; outlineHeadings = headings;
} }
function handleOutlineResize(delta: number) {
$outlineWidth = Math.max(160, Math.min(500, $outlineWidth - delta));
}
function scrollToHeading(pos: number) { function scrollToHeading(pos: number) {
if (!editor) return; if (!editor) return;
editor.commands.setTextSelection(pos + 1); editor.commands.setTextSelection(pos + 1);
@@ -5502,7 +5507,8 @@
</div> </div>
{/if} {/if}
{#if showOutline} {#if showOutline}
<div class="outline-panel"> <ResizeHandle onResize={handleOutlineResize} />
<div class="outline-panel" style="width: {$outlineWidth}px">
<div class="outline-header"> <div class="outline-header">
<h3>Outline</h3> <h3>Outline</h3>
<button class="outline-close" onclick={() => { showOutline = false; }}> <button class="outline-close" onclick={() => { showOutline = false; }}>
@@ -7475,7 +7481,7 @@
.outline-empty { .outline-empty {
padding: 16px 14px; padding: 16px 14px;
font-size: 12px; font-size: var(--editor-font-size, 14px);
color: var(--text-tertiary); color: var(--text-tertiary);
line-height: 1.5; line-height: 1.5;
} }
@@ -7493,7 +7499,7 @@
background: none; background: none;
border: none; border: none;
padding: 4px 14px; padding: 4px 14px;
font-size: 12px; font-size: var(--editor-font-size, 14px);
color: var(--text-secondary); color: var(--text-secondary);
cursor: pointer; cursor: pointer;
white-space: nowrap; white-space: nowrap;
+4
View File
@@ -26,6 +26,7 @@ export const sidebarCollapsed = writable(false);
export const notelistCollapsed = writable(false); export const notelistCollapsed = writable(false);
export const sidebarWidth = writable(220); export const sidebarWidth = writable(220);
export const notelistWidth = writable(280); export const notelistWidth = writable(280);
export const outlineWidth = writable(220);
export const searchQuery = writable(""); export const searchQuery = writable("");
export const showCommandPalette = writable(false); export const showCommandPalette = writable(false);
export const showSearch = writable(false); export const showSearch = writable(false);
@@ -227,6 +228,7 @@ export const vaultState = derived(
activeNotePath, activeNotePath,
sidebarWidth, sidebarWidth,
notelistWidth, notelistWidth,
outlineWidth,
sidebarCollapsed, sidebarCollapsed,
notelistCollapsed, notelistCollapsed,
collapsedNotebooks, collapsedNotebooks,
@@ -238,6 +240,7 @@ export const vaultState = derived(
$activeNotePath, $activeNotePath,
$sidebarWidth, $sidebarWidth,
$notelistWidth, $notelistWidth,
$outlineWidth,
$sidebarCollapsed, $sidebarCollapsed,
$notelistCollapsed, $notelistCollapsed,
$collapsedNotebooks, $collapsedNotebooks,
@@ -249,6 +252,7 @@ export const vaultState = derived(
last_open_note: $activeNotePath, last_open_note: $activeNotePath,
sidebar_width: $sidebarWidth, sidebar_width: $sidebarWidth,
notelist_width: $notelistWidth, notelist_width: $notelistWidth,
outline_width: $outlineWidth,
sidebar_collapsed: $sidebarCollapsed, sidebar_collapsed: $sidebarCollapsed,
notelist_collapsed: $notelistCollapsed, notelist_collapsed: $notelistCollapsed,
collapsed_notebooks: $collapsedNotebooks, collapsed_notebooks: $collapsedNotebooks,
+1
View File
@@ -129,6 +129,7 @@ export interface VaultState {
last_open_note: string | null; last_open_note: string | null;
sidebar_width: number; sidebar_width: number;
notelist_width: number; notelist_width: number;
outline_width?: number;
sidebar_collapsed: boolean; sidebar_collapsed: boolean;
notelist_collapsed: boolean; notelist_collapsed: boolean;
collapsed_notebooks: string[]; collapsed_notebooks: string[];