fix: eliminate dual scrollbars by allowing spell feeds to flow naturally

Removed fixed heights (h-[60vh] min-h-[400px]) from spell feed containers
to create a true single-scrollbar experience throughout the viewers.

Problem:
The previous design had two scrollbars:
1. Main container scrollbar (for content + spell section)
2. Spell feed scrollbar (fixed height container with overflow)

This created a confusing UX where users had to manage two separate scroll
contexts, and spell feeds felt "trapped" in a small box.

Solution:
- Remove all fixed heights from TabsContent wrappers
- Let spell feeds (EventFeed/CountViewer) render at their natural height
- Single scrollbar controls everything - content flows naturally
- Users scroll down through event/profile/relay content, then continue
  scrolling through spell tabs and their feeds seamlessly

Benefits:
- Single, intuitive scrollbar for entire page
- Spell feeds expand naturally without artificial constraints
- Cleaner visual design without nested scroll containers
- Works perfectly on all screen sizes (tall and short windows)
- Sticky tab headers still keep tabs accessible when scrolling

The layout now behaves like a traditional webpage: one continuous
scrollable area where everything flows naturally top to bottom.

Files modified:
- EventDetailViewer.tsx: Removed fixed heights from spell TabsContent
- ProfileViewer.tsx: Removed fixed heights from spell TabsContent
- RelayViewer.tsx: Removed fixed heights from spell TabsContent
This commit is contained in:
Claude
2026-01-24 09:48:38 +00:00
parent 3edde7fdaa
commit 39b5165205
3 changed files with 45 additions and 57 deletions

View File

@@ -183,15 +183,13 @@ function SpellTabContent({
</div>
</div>
) : isCountSpell ? (
<div className="h-[60vh] min-h-[400px]">
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
</div>
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
) : (
<div className="flex flex-col h-[60vh] min-h-[400px]">
<>
<SpellHeader
loading={loading}
overallState={overallState}
@@ -203,17 +201,15 @@ function SpellTabContent({
exportFilename={spell.name || "spell-events"}
onOpenNip={(number) => addWindow("nip", { number })}
/>
<div className="flex-1 overflow-y-auto min-h-0">
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</div>
</div>
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</>
)}
</TabsContent>
);

View File

@@ -270,15 +270,13 @@ function SpellTabContent({
</div>
</div>
) : isCountSpell ? (
<div className="h-[60vh] min-h-[400px]">
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
</div>
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
) : (
<div className="flex flex-col h-[60vh] min-h-[400px]">
<>
<SpellHeader
loading={loading}
overallState={overallState}
@@ -290,17 +288,15 @@ function SpellTabContent({
exportFilename={spell.name || "spell-events"}
onOpenNip={(number) => addWindow("nip", { number })}
/>
<div className="flex-1 overflow-y-auto min-h-0">
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</div>
</div>
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</>
)}
</TabsContent>
);

View File

@@ -146,15 +146,13 @@ function SpellTabContent({
</div>
</div>
) : isCountSpell ? (
<div className="h-[60vh] min-h-[400px]">
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
</div>
<CountViewer
filter={appliedFilter}
relays={finalRelays}
needsAccount={false}
/>
) : (
<div className="flex flex-col h-[60vh] min-h-[400px]">
<>
<SpellHeader
loading={loading}
overallState={overallState}
@@ -166,17 +164,15 @@ function SpellTabContent({
exportFilename={spell.name || "spell-events"}
onOpenNip={(number) => addWindow("nip", { number })}
/>
<div className="flex-1 overflow-y-auto min-h-0">
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</div>
</div>
<EventFeed
events={events}
view="list"
loading={loading}
eoseReceived={eoseReceived}
stream={true}
enableFreeze={true}
/>
</>
)}
</TabsContent>
);