Skip to content

ENG-2409 Long settings pages are hard to scan: add collapsible sections and sticky headers - #1559

Open
trangdoan982 wants to merge 8 commits into
roam-setting-overhaulfrom
eng-2409-long-settings-pages-are-hard-to-scan-add-collapsible
Open

trangdoan982 wants to merge 8 commits into
roam-setting-overhaulfrom
eng-2409-long-settings-pages-are-hard-to-scan-add-collapsible

Conversation

@trangdoan982

@trangdoan982 trangdoan982 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Reviewer brief

Stacked on #1525 (Roam settings menu overhaul). Merge that first; this PR targets roam-setting-overhaul.

  • Result: each of the six node type sections collapses on its own, and a Collapse all / Expand all button sits in the node page header. Section headings stick to the top of the scroll area on every settings page that has them. A settings search jump into Grammar > Nodes expands every section, then scrolls to the row and flashes it.
  • Review focus:
    • apps/roam/src/components/settings/components/SettingsHeadings.tsx: SettingsGroup keeps collapsed rows mounted with Blueprint Collapse and marks them inert. When a stuck section collapses, it keeps the heading in place by adjusting only the settings scroller. StickyHeading copies the dialog's background, so Roam themes stay opaque and matched.
    • apps/roam/src/components/settings/navigation/useSettingAnchorScroll.ts: the search jump now waits until every ancestor Collapse reaches height: auto, with a 500ms limit.
  • Risk or follow-up (known limits):
    • The heading colour is read when the heading mounts. It goes stale if the Roam theme changes while Settings is open.
    • getNodeConfigSections repeats NodeConfig.tsx's section list and its isSyncEnabled() condition by hand.
    • Collapse all doesn't preserve the scroll position. The page shrinks to its headings and scrolls to the top.
    • A setting search jump into Grammar > Nodes expands every section, not only the target's (agreed during planning).

Collapse state lives in the dialog and flows down to the node page. Search jumps reset it before scrolling.

flowchart LR
  SD["Settings.tsx<br/>collapsedNodeSections state<br/>search jump: reset to all expanded"] --> GNR["GrammarNodesRoute.tsx<br/>Collapse all / Expand all"]
  GNR --> NC["NodeConfig.tsx<br/>6 × SettingsGroup collapsible"]
  NC --> SG["SettingsGroup<br/>sticky heading + Collapse keepChildrenMounted + inert"]
  SD --> Hook["useSettingAnchorScroll<br/>wait for Collapse height: auto, then scroll + flash"]
  Hook -.-> SG
Loading

Verification

Ran live in Roam with dg-roam-load-extension on slot 1 against 2f843b81.

Scenario Input Expected Actual Pass
Default Open Grammar > Nodes > Claim All 6 sections expanded, button reads "Collapse all" As expected ✅
Collapse all Click Collapse all Only headings visible, button reads "Expand all", content inert As expected ✅
Sticky heading Scroll into Canvas Canvas heading pinned at the scroll box top 184.1 = 184.1 ✅
Collapse a stuck heading Click the stuck Canvas heading Canvas collapses, heading stays at the top, overlay doesn't scroll Offset 0 on every frame for 450ms; overlay scrollTop 0 ✅
Node switch Collapse Legacy on Claim, open Evidence Legacy still collapsed As expected ✅
Search jump Collapse all, then search "Overlay" All sections expand, row scrolls into view and flashes Flash after expand (317ms); row inside the box at max scroll ✅
Keyboard Enter, then Space on a heading Toggles As expected ✅
Tab order Collapse Canvas, Tab from its heading Focus skips Canvas controls Lands on the Legacy heading ✅
Other pages Features > Canvas, Left sidebar, Preferences > General Headings sticky; Node trigger renders as before Sticky at the box top; Node trigger can't reach the top (last, short group) ✅
Dark and custom themes bp3-dark probe; injected .bp3-dialog background Heading background matches the dialog rgb(41,55,66) and rgb(30,30,46) match ✅
Scenario Screenshot
Collapse all leaves only headings Collapse all leaves only headings
Canvas heading stuck while scrolling Canvas heading stuck while scrolling
Clicking the stuck heading collapses it in place Clicking the stuck heading collapses it in place
Search jump to Overlay after Collapse all Search jump to Overlay after Collapse all
Tab skips the collapsed Canvas section Tab skips the collapsed Canvas section
Dark theme: heading matches dialog Dark theme: heading matches dialog
Custom theme: heading copies dialog background Custom theme: heading copies dialog background
Left sidebar before: heading scrolls away Left sidebar before: heading scrolls away
Left sidebar after: Global heading sticks Left sidebar after: Global heading sticks

Tests: apps/roam/src/utils/__tests__/settingsCollapsibleSections.test.ts covers the section helpers and the SettingsGroup toggle, its inert state and its keyboard handling. Rerun with pnpm -C apps/roam exec vitest run src/utils/__tests__/settingsCollapsibleSections.test.ts.

Not verified: a real third-party Roam theme. The theme checks used Blueprint's bp3-dark class and an injected .bp3-dialog background.

Loom video

https://www.loom.com/share/d7d764a701f046b2875609cfaa6285b8

Scope check

  • Ran $scope-check against the ENG ticket and final diff.
  • Scope beyond Done When:
    • Collapse state persists across node types and tabs for the dialog's lifetime.
    • Clicking a stuck heading collapses it and keeps the heading in place.
    • A setting search jump into Grammar > Nodes expands every section rather than only the target's.
  • Required now: the first two keep collapse usable when you scroll or switch node types; without them, collapsing loses your place. The third guarantees the target row is visible without a per-section lookup.
  • Anyone affected or consulted: Yes, the ticket author approved all three during planning.
  • Decision: Not documented in Linear yet; to be recorded in an ENG-2409 comment before merge.

Standards check

  • Ran $dg-pr-adherence-check against the final diff and PR metadata.

Local delegated full review

  • Ran a comprehensive review of the entire final diff in a subagent with a fresh context. Use $dg-delegated-full-review when no other full-review workflow is available.

Fixed from review: theme-matched heading background, scroller-only realign, inert collapsed rows, a time-based expand wait, and functional state updates. The remaining findings are the known limits listed in Reviewer brief.

🤖 Generated with Claude Code


Devin Review

trangdoan982 and others added 6 commits October 17, 2026 10:08
Node type sections collapse individually or all at once, with state kept
for the dialog's lifetime. Section headings stick on every settings page,
and a settings search jump expands all sections before scrolling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M552YDYWGGAM3E59DKHH4QD9
Copy the sticky heading background from the dialog so Roam themes that
restyle .bp3-dialog without .bp3-dark stay opaque and matching. Realign a
collapsed stuck section on its own scroller only, and build the collapse
all button only on the node page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M55386K5C0G4VQRKR9MD21AX
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M553DVNG21Y06NX5YBQZ7722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M553MEG7DZPAB3N071WTHMCP
Search jumps wait until an expanding Collapse reaches height: auto before
scrolling, so the row is not missed mid-animation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M553ZJ3WFZGKSK5BYG4FZBBW
Mark collapsed section content inert, wrap only collapsible groups in
Collapse, wait on a 500ms clock rather than a frame count, and reset
collapse state only for setting jumps into Grammar > Nodes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M554EQDMB7D3FMH32V5TYS2N
@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
discourse-graph Skipped Skipped Oct 17, 2026 2:58pm UTC

Request Review

@linear-code

linear-code Bot commented Oct 17, 2026

Copy link
Copy Markdown

ENG-2409

@supabase

supabase Bot commented Oct 17, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Devin Review

Comment thread apps/roam/src/components/settings/navigation/useSettingAnchorScroll.ts Outdated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M555TP1V9DCMNS8DDSFSKXHJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M555X702GD83ZXW9YBJGBCHJ

This branch was previously deployed

1 inactive deployment
Preview — e34a1862 Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant