[Enhancement] app-lesson-sidebar: contain long lesson list (100vh / internal scroll vs virtual scroll) #22

Closed
opened 2026-04-28 22:44:03 +00:00 by spikerj · 1 comment
Owner

Problem

app-lesson-sidebar lists 100+ lessons and currently drives the page to a very tall scroll height. Users can accidentally scroll the whole page with the mouse wheel and lose context (question, editor, answer area) instead of staying focused in the lesson workspace.

Goal

Keep the main lesson view within a predictable viewport (e.g. 100vh / full-height app shell) so the primary content does not feel like it “drifts” under global page scroll. Scrolling the lesson list should be local to the sidebar (or virtualized), not the entire document.

Options to evaluate (pick at implementation time)

A. Constrained sidebar + internal scroll

  • Sidebar column has max-height: 100vh (or fills flex grid row) with overflow-y: auto (or overflow: hidden on body with flex children).
  • Pros: Simple, no new deps, works everywhere.
  • Cons: Still renders all DOM nodes for 100+ items (usually fine at this scale).

B. Virtual scrolling (CDK or similar)

  • Render only visible lesson rows; smooth scroll for long lists.
  • Pros: Scales if lists grow further; less DOM.
  • Cons: More integration work; keyboard/focus/ARIA need care; another dependency if not already on CDK.

C. Hybrid

  • Internal scroll for the list region only; optional virtual scroll later if profiling shows need.

Acceptance criteria (high level)

  • Page-level scroll is not required only because of the lesson list length; list scroll is contained in the sidebar (or equivalent panel).
  • Question / answer / playground areas remain usable without the default wheel behavior pulling the user through a miles-long page.
  • Final approach documented in PR (A vs B vs C).

Component

app-lesson-sidebar (layout / global shell may need small adjustments so height constraints propagate).

## Problem `app-lesson-sidebar` lists **100+ lessons** and currently drives the **page** to a very tall scroll height. Users can accidentally **scroll the whole page** with the mouse wheel and lose context (question, editor, answer area) instead of staying focused in the lesson workspace. ## Goal Keep the **main lesson view** within a predictable viewport (e.g. **`100vh`** / full-height app shell) so the primary content does not feel like it “drifts” under global page scroll. Scrolling the lesson list should be **local to the sidebar** (or virtualized), not the entire document. ## Options to evaluate (pick at implementation time) ### A. Constrained sidebar + internal scroll - Sidebar column has `max-height: 100vh` (or fills flex grid row) with **`overflow-y: auto`** (or `overflow: hidden` on body with flex children). - **Pros:** Simple, no new deps, works everywhere. - **Cons:** Still renders all DOM nodes for 100+ items (usually fine at this scale). ### B. Virtual scrolling (CDK or similar) - Render only visible lesson rows; smooth scroll for long lists. - **Pros:** Scales if lists grow further; less DOM. - **Cons:** More integration work; keyboard/focus/ARIA need care; another dependency if not already on CDK. ### C. Hybrid - Internal scroll for the list region only; optional virtual scroll later if profiling shows need. ## Acceptance criteria (high level) - [ ] Page-level scroll is not required **only** because of the lesson list length; list scroll is contained in the sidebar (or equivalent panel). - [ ] Question / answer / playground areas remain usable without the default wheel behavior pulling the user through a miles-long page. - [ ] Final approach documented in PR (A vs B vs C). ## Component `app-lesson-sidebar` (layout / global shell may need small adjustments so height constraints propagate).
Author
Owner

Closing — already implemented (Approach A, exactly as this ticket proposed) and shipped with the feature-based architecture revamp (spikersoft-angular commit 4a362ba). The shared app-lesson-sidebar (libraries/shared/lesson-panes/.../lesson-sidebar.scss) carries the implementation with an explicit "Issue #22 — Approach A" comment:

  • max-height: calc(100vh - var(--app-toolbar-height) - 2rem) + overflow-y: auto — the catalog scrolls inside the sidebar, never dragging the page height
  • :host { height: 100%; min-height: 0 } so it fills the sticky workspace grid cell but stays safe in unbounded contexts
  • Option B (CDK virtual scroll) deliberately deferred in the comment — DOM cost is negligible at 100-ish items and it avoids focus/ARIA complexity

Verified the shared component is what the playground shells render (language-runner.html, clang-runtime shell). Nothing further to do; if lists grow into the thousands, reopen for Option B.

Closing — **already implemented** (Approach A, exactly as this ticket proposed) and shipped with the feature-based architecture revamp (`spikersoft-angular` commit `4a362ba`). The shared `app-lesson-sidebar` (`libraries/shared/lesson-panes/.../lesson-sidebar.scss`) carries the implementation with an explicit "Issue #22 — Approach A" comment: - `max-height: calc(100vh - var(--app-toolbar-height) - 2rem)` + `overflow-y: auto` — the catalog scrolls **inside** the sidebar, never dragging the page height - `:host { height: 100%; min-height: 0 }` so it fills the sticky workspace grid cell but stays safe in unbounded contexts - Option B (CDK virtual scroll) deliberately deferred in the comment — DOM cost is negligible at 100-ish items and it avoids focus/ARIA complexity Verified the shared component is what the playground shells render (`language-runner.html`, `clang-runtime` shell). Nothing further to do; if lists grow into the thousands, reopen for Option B.
Sign in to join this conversation.