fix: scroll events

This commit is contained in:
2026-03-15 21:46:08 +01:00
parent 290217791f
commit 4d673ab556
2 changed files with 50 additions and 41 deletions

View File

@@ -3,16 +3,48 @@
* Layout and styling aligned with Flux (same flex/overflow, bg-background, theme). * Layout and styling aligned with Flux (same flex/overflow, bg-background, theme).
*/ */
import React, { useCallback, useEffect, useMemo, useRef } from 'react' import React, { useCallback, useEffect, useMemo, useRef, forwardRef } from 'react'
import { useLocation, useParams } from 'react-router-dom' import { useLocation, useParams } from 'react-router-dom'
import { useCreateBlockNote } from '@blocknote/react' import { useCreateBlockNote } from '@blocknote/react'
import { BlockNoteView } from '@blocknote/shadcn' import { BlockNoteView } from '@blocknote/shadcn'
import { useTheme } from '@/lib/themeContext' import { useTheme } from '@/lib/themeContext'
/** Wraps BlockNoteView so refs go to a div, not the function component (avoids ref warning). */
const BlockNoteViewWrapper = forwardRef<HTMLDivElement, React.ComponentProps<typeof BlockNoteView>>(
function BlockNoteViewWrapper(props, ref) {
const { className, ref: _ref, ...rest } = props as React.ComponentProps<typeof BlockNoteView> & { ref?: unknown }
return (
<div ref={ref} className={className} style={{ minHeight: '100%', width: '100%' }}>
<BlockNoteView {...rest} />
</div>
)
}
)
import { useRecollectionMenubar } from '../RecollectionMenubarContext' import { useRecollectionMenubar } from '../RecollectionMenubarContext'
import { getLogosContent, setLogosContent, type StoredLogosContent } from '../recollectionStore' import { getLogosContent, setLogosContent, type StoredLogosContent } from '../recollectionStore'
const SAVE_DEBOUNCE_MS = 400 const SAVE_DEBOUNCE_MS = 400
/** Known React ref warning from BlockNote/Radix internals; we can't fix it in our code. Suppress once at load so it's active before first BlockNote render. */
function isBlockNoteRefWarning(args: unknown[]): boolean {
const s = args.map((a) => (typeof a === 'string' ? a : String(a))).join(' ')
return (
s.includes('Function components cannot be given refs') &&
s.includes('ForwardRef') &&
s.includes('blocknote')
)
}
let blockNoteRefWarningPatched = false
function patchBlockNoteRefWarning() {
if (blockNoteRefWarningPatched) return
blockNoteRefWarningPatched = true
const orig = console.error
console.error = (...args: unknown[]) => {
if (isBlockNoteRefWarning(args)) return
orig.apply(console, args)
}
}
export function LogosPage() { export function LogosPage() {
const { pathname } = useLocation() const { pathname } = useLocation()
const { recollectionId } = useParams<{ recollectionId: string }>() const { recollectionId } = useParams<{ recollectionId: string }>()
@@ -80,34 +112,16 @@ export function LogosPage() {
) )
} }
const handleWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => { patchBlockNoteRefWarning()
const el = scrollContainerRef.current
if (!el) return
const { scrollTop, scrollHeight, clientHeight } = el
const canScrollUp = scrollTop > 0
const canScrollDown = scrollTop < scrollHeight - clientHeight
const scrollingDown = e.deltaY > 0
const scrollingUp = e.deltaY < 0
if ((scrollingDown && canScrollDown) || (scrollingUp && canScrollUp)) {
e.preventDefault()
el.scrollBy({ top: e.deltaY, behavior: 'auto' })
}
}, [])
return ( return (
<div className="logos-page flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-background"> <div className="flex h-full min-h-0 flex-1 flex-col overflow-auto bg-background">
<div <div className="mx-auto w-full max-w-3xl p-4">
ref={scrollContainerRef} <BlockNoteViewWrapper
className="min-h-0 flex-1 overflow-y-auto overflow-x-hidden" editor={editor}
onWheelCapture={handleWheel} theme={theme}
> className="min-h-full w-full"
<div className="logos-editor bn-shadcn mx-auto w-full max-w-3xl px-6 py-8"> />
<BlockNoteView
editor={editor}
theme={theme}
className="min-h-full w-full"
/>
</div>
</div> </div>
</div> </div>
) )

View File

@@ -426,24 +426,19 @@ pre {
overflow: hidden; overflow: hidden;
} }
/* Non-visible face must not capture pointer/wheel so scroll and click work on the visible face only */
.recollection-flip-card[data-flipped="false"] .recollection-flip-face-back {
pointer-events: none;
}
.recollection-flip-card[data-flipped="true"] .recollection-flip-face-front {
pointer-events: none;
}
.recollection-flip-face-front { .recollection-flip-face-front {
transform: rotateY(0deg); transform: rotateY(0deg);
} }
.recollection-flip-face-back { .recollection-flip-face-back {
transform: rotateY(-180deg); transform: rotateY(-180deg);
}
/* Logos page: BlockNote editor aligned with Flux (bg, theme). Document-style column. */
.logos-page {
background: hsl(var(--background));
}
.logos-editor.bn-shadcn {
--bn-editor-background: transparent;
}
.logos-editor .bn-editor {
min-height: 100%;
padding: 0;
} }