Repository navigation
feat(files): render Markdown previews with a centered outline - #651
Closed
od-studio-webagency wants to merge 1 commit into
Closed
od-studio-webagency wants to merge 1 commit into
od-studio-webagency wants to merge 1 commit into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Owner
|
Thanks for this. Markdown previews in the file viewer are already under review in #429, which the maintainer has reviewed several times (#669, #670 and #671 were split out of it and have landed), and #616 covers the same ground with images. Closing this as a duplicate to keep the work in one place. If the centered outline is something you'd like to propose on top, please open an issue for it once a preview has landed. |
devswha
added a commit
that referenced
this pull request
Nov 5, 2026
Fixes #636. ## What A new opt-in setting, **Settings > File viewer > Markdown outline** (off by default, a device setting in its own storage key like the other recent opt-ins). With it on, a Markdown Preview that has two headings or more lists them: - **Levels and repeated titles.** The outline lists the document's own headings (not ones inside a quote), each level under the shallowest one stepped in. A title written twice is two entries, and each goes to its own heading. - **Follows the reading.** As the document scrolls, the heading being read (the last one past a line 32 px under the body's top) is marked with the accent on a tint, and kept in the middle of the list. Only the list scrolls to do that, so the browser clamps it at the list's start and end, and the document's position and the keyboard focus never move with it. At the very end of the document, the last heading in view is marked (short final sections cannot reach the reading line). - **Choosing an entry** brings its heading to 8 px under the top. A chosen entry stays marked while the document rests where the choice left it, even when the end of the document keeps the heading from reaching the top. - **Wide viewer** (body at least 760 px: the popup and the reader tab on a desktop): a 240 px column after the document. The header's new **Outline** button folds and unfolds it. - **Narrow viewer** (a phone, the docked panel): nothing changes until the **Outline** button (header; the toolbar when docked) is pressed. It opens the outline as a drawer over the document's end edge, so the text keeps its whole width. Opening the drawer centers the heading being read and puts the focus on it. A choice, Escape (which closes the drawer only, not the viewer) or a press outside closes it, and the focus returns to the button. With the setting off (the default), the viewer is unchanged: the body's new wrapper is `display: contents`, so it lays nothing out. The wrapper is always rendered so the body is never remounted when an outline appears, which keeps its focus and scroll. **Design reference:** Zed's outline panel (the current symbol is marked and kept in view while the editor scrolls) for the column, and GitHub's Markdown file outline button for the narrow drawer. There is a DESIGN.md entry. Compared with #651 (closed as a duplicate before the Markdown preview landed): this builds on the preview that is on main now, adds only the outline, and keeps it opt-in. ## Tests - `scripts/markdown-outline-browser-qa.ts` (new, added to `scripts/ci-browser.sh`): the real viewer built by Vite and served under the app's CSP, light and dark. - Off: no outline, no button, and the wrapper computes to `display: contents`. - 1280 popup: a column whose width plus the body's equals the row; 61 entries for 61 headings; depth classes for `#`/`##`/`###`; the first entry marked at the start with the list at scrollTop 0; scrolling to Section 16 marks it within 2 px of the list's center while the body's scrollTop and `document.activeElement` stay unchanged; at the end the list is at its own end; the third "Notes" entry lands the third Notes heading at 8 px; choosing Section 30 near the end keeps it marked; the button folds and restores the column. - 390 phone: no column until the button; the drawer does not change the body's width; opening centers and focuses Section 21; Escape closes only the drawer and returns focus to the button; a choice scrolls to the heading, closes, and returns focus; a tap on the document closes it. - Narrow, after review: a dialog in front of the viewer (Settings) keeps its Escape and focus while the drawer stays open; a touch stroke down the drawer at its top does not drag the viewer's sheet. - Docked at 1280: the toolbar's Outline button opens a drawer over the panel, and the pane beside it keeps its Escape and focus. - **Failing first:** with `src/` at origin/main the script fails at its first step (no wrapper, no outline). - `src/lib/markdownOutline.test.ts`: the entry list (levels, words with formatting dropped, quoted headings left out, repeated titles as separate places, wordless headings skipped) and the current-heading rule. - `src/lib/settings.test.ts`: the default, sanitising and device scope, and the setting's own key surviving an old tab's whole-record save. ## Screenshots Fixture data (no user session), 1280x800 and 390x844, dark and light; checked by eye: the column and the drawer, the marked entry centered, the indent per level, and the Outline button's on state. ## Validation - `bun run check fast`: pass on the merged head 57863e2 (workflow syntax, generated types/themes, typecheck, build, 12364 unit tests, 0 failures). - `bun scripts/markdown-outline-browser-qa.ts`: pass, also on the merged head (with `files-prompt-regression`, whose #3053 Escape steps landed meanwhile). - Sheet-drag regressions after the review fix (`src/lib/sheets.ts`), in `herdr-ci-runner:local`: `key-bar-customization-demo-regression`, `link-menu-demo-regression`, `phone-worktree-sheet-regression`: all PASS. - Browser regressions covering FileViewer, run in `herdr-ci-runner:local`: all pass: `markdown-outline-browser-qa`, `file-viewer-regression` (79 PASS), `file-viewer-mobile-regression`, `file-preview-text-browser-qa`, `virtual-source-browser-qa`, `files-panel-demo-regression`, `file-text-size-demo-regression`, `settings-pages-demo-regression`, `deep-link-demo-regression`, `render-crash-demo-regression`, `web-panel-mobile-regression`, `repo-diff-browser-qa`, `relay-media-browser-qa`, `link-menu-demo-regression`, and `files-prompt-regression` (through `bun run check run`, 8 PASS). - Not run: the full browser suite (CI runs it), and native iOS/Android or Windows checks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change
Closes #636
#510, #429, #616과 겹치는 미리보기 논의를 연결합니다. 이 초안의 추가 제안은 목차와 읽기 위치 탐색이며, Mermaid나 새 구문 강조 의존성을 넣지 않았습니다.
Validation
generate:types --check,typecheck,build,test:unit통과. 새 preview/TOC 회귀는 1440/390px 밝은·어두운 테마에서 통과했습니다. 기존 파일 열기/뒤로·앞으로/Settings·Add PC 포커스 검사와 모바일 미디어 16개 경우도 통과했습니다.모든 검증은 별도 작업 공간과 소유한 테스트/demo 환경에서 수행했습니다. 사용자의 실행 중 앱·terminal은 변경하지 않았습니다.
화면 증거
개인 대화나 사용자 세션이 아닌, 소유한 테스트/demo 환경의 가상 데이터로 촬영했습니다.