fix(workspace): single scroll area, drag cleanup, thin note titles with bundled Inter
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m18s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m18s
- the workspace fills the window; only the note scrolls (also on phones, where the sideways scroll area used to scroll on its own) - clear drag state on dragend, calmer sidebar toggle when collapsed - ship Inter as variable font, light and larger note titles; header shows the title only after the big title scrolled away and stays one row on phones - main builds show the package version without -dev Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ad4829796c
commit
6c154af251
11 files changed
+88
-19
No files matched your search
@@ -230,6 +230,9 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
|
||||
|
||||
const titleInputRef = useRef<HTMLTextAreaElement | HTMLInputElement | null>(null);
|
||||
const scrollRef = useRef<HTMLDivElement | null>(null);
|
||||
// The header repeats the title only once the big title has scrolled out of view
|
||||
const [titleScrolledAway, setTitleScrolledAway] = useState(false);
|
||||
const outlinerTreeRef = useRef<OutlinerTreeHandle | null>(null);
|
||||
const docRef = useRef<Document | null>(doc);
|
||||
docRef.current = doc;
|
||||
@@ -239,6 +242,22 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
const currentBlocksRef = useRef<DocumentBlock[]>(blocks);
|
||||
currentBlocksRef.current = blocks;
|
||||
|
||||
useEffect(() => {
|
||||
const root = scrollRef.current;
|
||||
const el = titleInputRef.current;
|
||||
if (!root || !el || typeof IntersectionObserver === 'undefined') {
|
||||
setTitleScrolledAway(false);
|
||||
return;
|
||||
}
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => setTitleScrolledAway(!entry.isIntersecting),
|
||||
// the sticky header covers the top of the scroll area
|
||||
{ root, rootMargin: '-56px 0px 0px 0px' }
|
||||
);
|
||||
observer.observe(el);
|
||||
return () => observer.disconnect();
|
||||
}, [zoomedBlockId, doc?.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && (autoFocusTitle || (doc?.title === 'Neue Notiz' && (!doc?.blocks || doc?.blocks.length <= 1)))) {
|
||||
const focusTitle = () => {
|
||||
@@ -763,15 +782,15 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 flex flex-col h-full min-h-0 bg-editor overflow-y-auto" data-sync-channel={engineState?.channel}>
|
||||
<div ref={scrollRef} className="flex-1 flex flex-col h-full min-h-0 bg-editor overflow-y-auto" data-sync-channel={engineState?.channel}>
|
||||
{/* Top Document Action Bar */}
|
||||
<div className="sticky top-0 z-20 flex flex-wrap items-center justify-between gap-2 px-4 sm:px-6 py-2 bg-editor border-b border-border">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<div className="sticky top-0 z-20 flex items-center justify-between gap-2 px-4 sm:px-6 py-2 bg-editor border-b border-border">
|
||||
<div className="flex flex-1 items-center gap-2 min-w-0">
|
||||
{onBackMobile && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onBackMobile}
|
||||
className="lg:hidden btn-icon h-11 w-11 sm:h-7 sm:w-7"
|
||||
className="lg:hidden btn-icon shrink-0 h-11 w-11 sm:h-7 sm:w-7"
|
||||
title="Zurück zur Seitenleiste"
|
||||
>
|
||||
<ArrowLeft className="w-3.5 h-3.5" />
|
||||
@@ -823,7 +842,12 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
})}
|
||||
</nav>
|
||||
) : (
|
||||
<div className="flex items-center gap-1.5 text-xs text-muted">
|
||||
<div
|
||||
className={`flex min-w-0 items-center gap-1.5 text-xs text-muted transition-opacity duration-200 ${
|
||||
titleScrolledAway ? 'opacity-100' : 'opacity-0 pointer-events-none'
|
||||
}`}
|
||||
aria-hidden={!titleScrolledAway}
|
||||
>
|
||||
<FileText className="w-3.5 h-3.5 text-accent shrink-0" />
|
||||
<span className="truncate max-w-[180px] font-medium text-main">
|
||||
{title || doc?.title || 'Dokument'}
|
||||
@@ -868,7 +892,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Right Action Buttons */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="flex shrink-0 items-center gap-1.5">
|
||||
{!inTrash && (
|
||||
<>
|
||||
<button
|
||||
@@ -1022,7 +1046,8 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
|
||||
{/* Main Content Area */}
|
||||
{/* Phones: almost no side margin; very deep outlines scroll sideways (rows keep a minimum width) */}
|
||||
<div className="w-full pl-2 pr-1 sm:px-8 py-5 flex-1 overflow-x-auto sm:overflow-x-visible [-webkit-overflow-scrolling:touch]">
|
||||
{/* shrink-0: the sideways scroll area must keep its full height, so only the editor scrolls vertically */}
|
||||
<div className="w-full pl-2 pr-1 sm:px-8 py-5 flex-auto shrink-0 overflow-x-auto sm:overflow-x-visible [-webkit-overflow-scrolling:touch]">
|
||||
{zoomedBlock ? (
|
||||
/* =========================================================================
|
||||
FOKUS-MODUS & ZOOM-IN (HOISTED SUBTREE VIEW)
|
||||
@@ -1061,7 +1086,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
}}
|
||||
placeholder="Ast-Titel…"
|
||||
readOnly={!canEdit}
|
||||
className="w-full text-2xl sm:text-3xl font-extrabold text-main bg-transparent border-0 focus:outline-none focus:ring-0 tracking-tight leading-tight"
|
||||
className="w-full text-2xl sm:text-3xl font-light text-main bg-transparent border-0 focus:outline-none focus:ring-0 tracking-tight leading-tight"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1183,7 +1208,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
}}
|
||||
onBlur={handleTitleBlur}
|
||||
placeholder="Titel der Notiz…"
|
||||
className="flex-1 min-w-0 text-xl sm:text-2xl font-bold text-main bg-transparent border-0 focus:outline-none focus:ring-0 tracking-tight resize-none leading-snug whitespace-pre-wrap break-words [overflow-wrap:anywhere]"
|
||||
className="flex-1 min-w-0 text-2xl sm:text-3xl font-light text-main bg-transparent border-0 focus:outline-none focus:ring-0 tracking-tight resize-none leading-snug whitespace-pre-wrap break-words [overflow-wrap:anywhere]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user