Fix article list not scrolling: duplicate <main> broke the scroll area
All checks were successful
CI / check (pull_request) Successful in 4m55s
CI / test (pull_request) Successful in 4m2s
CI / audit (pull_request) Successful in 14s

Articles past the first screenful were unreachable — not clipped by
accident, genuinely inaccessible, since the page itself couldn't
scroll either (the sidebar wrapper is overflow: hidden by design, so
the intended scroll boundary is internal to the main content pane).

Root cause: SidebarInset already renders a <main> (class
dx-sidebar-inset, a properly height-bound flex column — main{
height:900px in a 900px viewport, flex-direction:column}), but I'd
also written an explicit `main { ... }` as ITS child, producing a
`<main><main>...</main></main>` (confirmed via a headless Playwright
probe against the live dev server, not just DevTools guesswork). The
inner <main> is just a plain flex item with the default flex: 0 1 auto,
so it sized to its own content (6500+px) instead of being constrained
by the outer one's box, and the ScrollArea inside it had nothing
bounded to scroll within.

Removed the redundant inner <main> — SidebarInset's children (the
content-header div and ScrollArea) now sit directly in its own <main>,
which is the actual flex column that needs to size them. Also pinned
ScrollArea's direction to Vertical (it defaults to Both, which was
adding an unnecessary horizontal scrollbar) and moved the sizing rule
in app.css off a class ScrollArea silently drops (confirmed via the
same probe — a caller-supplied `class` never reaches ScrollArea's
rendered DOM, only its own internal one does) onto its stable
data-scroll-direction attribute instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
This commit is contained in:
Austin Schaefer 2026-09-03 19:17:57 +02:00
parent 44e2fb4d4e
commit f0e42e2ad5
2 changed files with 35 additions and 29 deletions

View file

@ -2,7 +2,14 @@ body { font-family: system-ui, sans-serif; margin: 0; color: #1a1a1a; height: 10
.app-shell { display: flex; height: 100vh; } .app-shell { display: flex; height: 100vh; }
.content-header { display: flex; align-items: center; gap: 0.75rem; padding: 1.5rem 1.5rem 0.5rem; } .content-header { display: flex; align-items: center; gap: 0.75rem; padding: 1.5rem 1.5rem 0.5rem; }
.content-header h2 { margin: 0; } .content-header h2 { margin: 0; }
.article-scroll-area { flex: 1; min-height: 0; padding: 0 1.5rem 1.5rem; } /* Target the primitive's own stable data attribute, not a class we pass in:
ScrollArea sets its own `class` after spreading our attributes, so a
caller-supplied class never reaches the DOM (confirmed by inspecting the
live element it only ever carries "dx-scroll-area-auto-hide"). Without
this, the scroll div has no bounded height, so it just grows to fit every
article (nothing to scroll) while its ancestor's overflow: hidden clips
everything past the viewport instead. */
main > [data-scroll-direction] { flex: 1; min-height: 0; padding: 0 1.5rem 1.5rem; }
.article-list { list-style: none; padding: 0; margin: 0; } .article-list { list-style: none; padding: 0; margin: 0; }
.article-row { border-bottom: 1px solid #ddd; padding: 1rem 0; display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; } .article-row { border-bottom: 1px solid #ddd; padding: 1rem 0; display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.article-row-header { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.5rem; } .article-row-header { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.5rem; }

View file

@ -85,7 +85,6 @@ pub fn App() -> Element {
} }
} }
SidebarInset { SidebarInset {
main {
div { class: "content-header", div { class: "content-header",
SidebarTrigger {} SidebarTrigger {}
h2 { h2 {
@ -104,7 +103,8 @@ pub fn App() -> Element {
} }
} }
} }
ScrollArea { class: "article-scroll-area", ScrollArea {
direction: dioxus_primitives::scroll_area::ScrollDirection::Vertical,
match articles.read().as_ref() { match articles.read().as_ref() {
Some(Ok(articles)) => rsx! { Some(Ok(articles)) => rsx! {
ul { class: "article-list", ul { class: "article-list",
@ -121,5 +121,4 @@ pub fn App() -> Element {
} }
} }
} }
}
} }