From bce103e2c67cd224f6ee0d3fc261c554497e69ce Mon Sep 17 00:00:00 2001 From: Sandro Date: Tue, 27 Oct 2026 17:43:20 +0100 Subject: [PATCH] feat(outliner): prevent creating extra empty block on enter on last empty root bullet --- .../src/features/workspace/OutlinerBlock.tsx | 21 ++++++++++++++----- .../src/features/workspace/OutlinerTree.tsx | 4 +++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/frontend/src/features/workspace/OutlinerBlock.tsx b/frontend/src/features/workspace/OutlinerBlock.tsx index 928d0c8..4351002 100644 --- a/frontend/src/features/workspace/OutlinerBlock.tsx +++ b/frontend/src/features/workspace/OutlinerBlock.tsx @@ -41,6 +41,7 @@ const SLASH_COMMANDS: SlashCommand[] = [ export interface OutlinerBlockProps { block: DocumentBlock; index: number; + isLast: boolean; maxAllowedLevel: number; hasChildren: boolean; isFocused: boolean; @@ -65,6 +66,7 @@ export interface OutlinerBlockProps { export const OutlinerBlock: React.FC = ({ block, index, + isLast, maxAllowedLevel, hasChildren, isFocused, @@ -343,17 +345,26 @@ export const OutlinerBlock: React.FC = ({ return; } - // 2. Enter (without Shift) -> If block is completely empty and level > minLevel, outdent (Shift+Tab behaviour), otherwise create new block below + // 2. Enter (without Shift) -> If block is completely empty: + // - If level > minLevel, outdent (Shift+Tab behaviour) + // - If already at minLevel and is the last block, do NOT create another empty block below + // - Otherwise create new block below if (e.key === 'Enter' && !e.shiftKey && block.type !== 'code') { e.preventDefault(); e.stopPropagation(); setSlashSearch(null); const minLevel = levelOffset || 0; - if (localContent === '' && Math.max(0, block.level || 0) > minLevel) { - flushDebounce(localContent); - onIndentBlockRef.current(block.id, -1); - return; + if (localContent === '') { + if (Math.max(0, block.level || 0) > minLevel) { + flushDebounce(localContent); + onIndentBlockRef.current(block.id, -1); + return; + } + if (isLast) { + // Bereits auf oberster Ebene und der letzte Block: kein weiterer leerer Block + return; + } } flushDebounce(localContent); diff --git a/frontend/src/features/workspace/OutlinerTree.tsx b/frontend/src/features/workspace/OutlinerTree.tsx index 4686924..f0c35ac 100644 --- a/frontend/src/features/workspace/OutlinerTree.tsx +++ b/frontend/src/features/workspace/OutlinerTree.tsx @@ -360,12 +360,14 @@ export const OutlinerTree: React.FC = ({ return (
- {visibleEntries.map(({ block, index, hasChildren, maxAllowedLevel }) => { + {visibleEntries.map(({ block, index, hasChildren, maxAllowedLevel }, entryIdx) => { + const isLast = entryIdx === visibleEntries.length - 1; return (