Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(desktop): contain first-run onboarding viewport by ARE404 · Pull Request #3195 · apache/maka · GitHub
Skip to content

fix(desktop): contain first-run onboarding viewport - #3195

Merged
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport
Aug 18, 2026
Merged

fix(desktop): contain first-run onboarding viewport#3195
Astro-Han merged 1 commit into
apache:mainfrom
ARE404:codex/fix-first-run-viewport

Conversation

@ARE404

Copy link
Copy Markdown
Contributor

Summary

  • Keep the first-run onboarding surface inside ChatLayout's actual available height instead of recomputing it from 100dvh.
  • Remove the transcript-only empty spacer and composer dock padding only while onboarding owns the empty state, so the page itself cannot scroll.
  • Preserve the existing onboarding card and provider-list scrolling, and add a real Electron regression test for the viewport contract.

Root cause

ChatMessageList reserves a flexible spacer before ordinary empty states. The onboarding surface also declared a viewport-derived minimum height, so it overflowed its half-height flex slot and expanded ChatLayout's self-scroll range. In the failing test, a 952px chat viewport produced 1159px of scrollable content even though the card itself fit on screen.

Verification

  • npx biome check apps/desktop/src/renderer/styles/onboarding.css apps/desktop/e2e/fixtures.ts apps/desktop/e2e/onboarding-viewport.spec.ts
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build:renderer
  • npx playwright test --config e2e/playwright.config.ts e2e/onboarding-viewport.spec.ts
  • Visually inspected a 3300×1984 real Electron capture: the card and skip action stay within the chat viewport and the outer scrollbar is gone.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex diagnosed the flex/viewport interaction, implemented the scoped CSS fix, and added the Electron E2E regression test.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@coderabbitai

coderabbitaiBot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ARE404, you've reached your PR review limit, so we couldn't start this review.

Next review available in:6 minutes

Limit details: You’ve used all 3 included reviews currently available under your plan.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 005c6bde-a461-472d-a613-5da11e277d30

📥 Commits

Reviewing files that changed from the base of the PR and between dd33cc1 and ba16360.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4534c559-cbb2-4a21-acb8-c7e04983dca8

📥 Commits

Reviewing files that changed from the base of the PR and between f764b54 and dd33cc1.

📒 Files selected for processing (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/e2e/onboarding-viewport.spec.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

The PR prevents first-run onboarding from causing page scrolling. It uses ChatLayout’s available height instead of a 100dvh minimum height.

It removes transcript empty spacing and composer dock padding while onboarding owns the empty state. The onboarding card and provider list retain internal scrolling.

Source of truth and solution scope

The PR extends the existing onboarding layout path. It does not create a parallel path.

The solution is focused. It adds onboarding-specific CSS, one shared Electron fixture, and two viewport regression tests. No code or test can be removed without weakening behavior or regression coverage.

Complexity delta

  • Removes the 100dvh minimum-height authority.
  • Removes the onboarding empty-state spacer and composer dock padding.
  • Adds onboarding overflow, flex-layout, clipping, and contained-scrolling rules.
  • Adds the test-only onboardingWindow: Page fixture field.
  • Adds two geometry and scrolling tests.
  • Adds test-maintenance cost for viewport and scroll assertions.
  • Adds no runtime configuration, product authority, security path, or release path.

Runtime maintenance complexity decreases. The added test complexity is justified by the page-scroll regression it covers.

Validation and risks

The tests check viewport geometry, page overflow, chat-container overflow, onboarding containment, minimum-height behavior, internal onboarding scrolling, and bottom-of-content visibility.

The PR reports Biome checks, typechecking, renderer build, Playwright tests, and real Electron visual inspection. Direct check output is not available. The final required-check status is therefore unverified.

Review-relevant risks

The CSS changes affect onboarding height, overflow, spacing, and scrolling. These changes can alter user-visible behavior. Material changes in these areas require independent human review under repository policy.

The fixture adds a test-only public field. No security, licensing, release, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

The changes constrain the onboarding surface to the chat viewport and add end-to-end coverage for normal and minimum-height windows. The tests use a visible, unseeded Chinese-locale onboarding window and verify internal scrolling.

Changes

Onboarding viewport

Layer / File(s)Summary
Constrain onboarding layout
apps/desktop/src/renderer/styles/onboarding.css
The onboarding chat layout hides excess overflow, removes spacing, and hides the empty message-list spacer. The onboarding surface fills its container, allows zero minimum height, and provides contained vertical scrolling.
Validate onboarding viewport
apps/desktop/e2e/fixtures.ts, apps/desktop/e2e/onboarding-viewport.spec.ts
The Playwright fixture exposes a visible, unseeded Chinese-locale onboarding window. The tests check required elements, viewport bounds, and internal scrolling at minimum height.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to dd33c

This localized viewport and regression-test change is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and concisely describes the main change: containing the first-run onboarding viewport in the desktop app.
Description check✅ PassedThe description explains the problem, root cause, solution, verification commands, AI use, and checklist status.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Ai Use Disclosure✅ PassedThe PR selects substantive generative use, names Codex and its scope, and the sole introduced commit contains the standalone trailer Generated-by: Codex.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@ARE404
ARE404 marked this pull request as ready for review August 18, 2026 08:13
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Contain first-run onboarding within the desktop chat viewport

🐞 Bug fix🧪 Tests🕐 10-20 Minutes

Grey Divider

AI Description

• Constrains first-run onboarding to ChatLayout’s available height and suppresses outer scrolling.
• Removes onboarding-only transcript spacing and composer dock padding without affecting normal
chats.
• Adds an unseeded Electron fixture and viewport geometry regression coverage.
Diagram

graph TD
A["Viewport Spec"] --> B["Onboarding Fixture"] --> C["Electron Window"] --> D["Chat Layout"] --> E["Message List"] --> F["Onboarding Surface"] --> G["Onboarding Card"]
H["Scoped CSS"] --> D
H --> E
H --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an explicit onboarding layout mode
  • ➕ Avoids relational selectors tied to the rendered DOM structure.
  • ➕ Makes spacer and dock suppression explicit component behavior.
  • ➖ Requires threading onboarding state through shared layout and message-list APIs.
  • ➖ Expands a desktop-specific fix into reusable UI components.
2. Render onboarding outside the transcript layout
  • ➕ Separates full-screen onboarding semantics from transcript empty-state behavior.
  • ➕ Eliminates interaction with message-list spacers and composer docking.
  • ➖ Requires broader renderer restructuring and duplicated shell placement logic.
  • ➖ Introduces more regression risk for onboarding transitions and shared chat framing.

Recommendation: Keep the PR’s scoped CSS approach. It derives the mode from the mounted onboarding surface, avoids duplicating state or changing shared UI APIs, and the Electron geometry test protects the DOM-dependent contract; an explicit layout mode is preferable only if more full-viewport chat states emerge.

Files changed (3) +61 / -1

Bug fix (1) +22 / -1
onboarding.cssContain onboarding within ChatLayout’s available height+22/-1

Contain onboarding within ChatLayout’s available height

• Scopes overflow suppression, transcript spacer removal, and dock padding removal to layouts containing onboarding. Replaces the viewport-derived minimum height with parent-relative sizing while preserving internal provider-list scrolling.

apps/desktop/src/renderer/styles/onboarding.css

Tests (2) +39 / -0
fixtures.tsAdd a real first-run Electron window fixture+9/-0

Add a real first-run Electron window fixture

• Adds an unseeded, visible Electron fixture that waits for the onboarding card before running tests. This provides a stable first-run environment for compositor-dependent geometry assertions.

apps/desktop/e2e/fixtures.ts

onboarding-viewport.spec.tsVerify onboarding remains inside the chat viewport+30/-0

Verify onboarding remains inside the chat viewport

• Adds an Electron regression test that compares scroll, surface, card, and viewport geometry. It asserts that the chat container has no overflow and that both onboarding elements remain within its bounds.

apps/desktop/e2e/onboarding-viewport.spec.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fe71bfef-a504-40d5-9992-579098550ee8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ccf0b and c5c43de.

📒 Files selected for processing (3)
  • apps/desktop/e2e/fixtures.ts
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts
@qodo-code-review

qodo-code-reviewBot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (0)📜 Skill insights (0)

Grey Divider


Action required

1. Short windows clip onboarding✓ Resolved🐞 Bug≡ Correctness
Description
Disposition: fix-now. At the supported 320px minimum window height, the fixed-height onboarding
surface and both hidden-overflow ancestors clip the card’s provider actions and skip control without
offering a user-scrollable path to reach them.
Code

apps/desktop/src/renderer/styles/onboarding.css[R84-87]

+ height: 100%;+ min-height: 0;
padding: var(--space-8) var(--space-6);
+ overflow: hidden;
Relevance

●●● Strong

Accepted precedents favor concrete viewport clipping and geometry regressions; this directly
contradicts the PR’s stated provider-list scrolling goal.

PR-#3175
PR-#2176

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The runtime explicitly supports a 320px minimum window, while the surface hides overflow and the
short-height rule only changes alignment. The card renders four provider rows plus fixed headers,
actions, and an optional skip button, so its intrinsic content cannot fit in the resulting sub-320px
chat area; the new fixture uses the default 1240×820 bounds and therefore does not cover this
supported case.

apps/desktop/src/main/window-state.ts[31-37]
apps/desktop/src/main/main-window.ts[313-320]
apps/desktop/src/renderer/styles/onboarding.css[80-100]
apps/desktop/src/renderer/onboarding-hero.tsx[129-174]
apps/desktop/src/renderer/onboarding-hero.tsx[294-325]
apps/desktop/src/renderer/onboarding-provider-types.ts[3-8]
apps/desktop/src/main/main-window.ts[210-218]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The onboarding surface is constrained to the available height but also hides overflow. At short supported window heights, the card is taller than the chat area and its lower actions become unreachable.
## Issue Context
The BrowserWindow permits heights down to 320px. The onboarding card contains a wordmark, header, four-provider list, action buttons, and an optional skip button; the short-height media query only top-aligns this content. Use the smallest local correction: retain the outer chat-layout containment while making the onboarding surface internally vertically scrollable when its content cannot fit. No new state or public API is needed.
## Fix Focus Areas
- apps/desktop/src/renderer/styles/onboarding.css[41-49]
- apps/desktop/src/renderer/styles/onboarding.css[80-100]
- apps/desktop/e2e/onboarding-viewport.spec.ts[3-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
Review mode: ⚖️ Balanced: This behavioral CSS/layout change alters onboarding viewport ownership, flex sizing, overflow, and scroll semantics across ChatLayout, with a new E2E contract; it is localized but not clearly trivial enough for lite, and lacks the defect density warranting extended.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment threadapps/desktop/src/renderer/styles/onboarding.css Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from c5c43de to f764b54CompareAugust 18, 2026 08:26

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 20f5e681-d9c8-40d1-bfc6-7d278c25a3a6

📥 Commits

Reviewing files that changed from the base of the PR and between c5c43de and f764b54.

📒 Files selected for processing (2)
  • apps/desktop/e2e/onboarding-viewport.spec.ts
  • apps/desktop/src/renderer/styles/onboarding.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/styles/onboarding.css

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment threadapps/desktop/e2e/onboarding-viewport.spec.ts Outdated
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from f764b54 to dd33cc1CompareAugust 18, 2026 08:34

@hqhq1025hqhq1025 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.

Re-reviewed head dd33cc1 against current main. No actionable findings.

The root cause is real: the transcript-only flex spacer and the onboarding surface's viewport-derived minimum height combined to expand ChatLayout beyond its available block size. The final patch keeps outer scroll ownership with ChatLayout, preserves user-reachable internal scrolling at the supported minimum height, and scopes the behavior to the mounted onboarding surface.

Independent verification on a clean detached worktree:

  • Biome check passed for all three changed files.
  • npm --workspace @maka/desktop run build:with-deps passed.
  • npm --workspace @maka/desktop run typecheck passed.
  • Targeted real Electron Playwright suite passed: 2/2, including wheel-driven scrolling at 320px height.
  • All required GitHub checks are green; the PR is mergeable and clean.

Optimality: this is the smallest maintainable correction for the current ownership boundary. It adds no runtime state, public API, configuration, dependency, or parallel layout path. I do not recommend deleting any production code or either regression test, and a deeper component refactor is not warranted unless more full-viewport chat states appear.

Residual risk: the scoped CSS necessarily depends on Astryx ChatMessageList/ChatLayout DOM structure. The real Electron geometry and user-scroll assertions provide appropriate regression coverage for that contract.

Ready to merge.

@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the fix — the phantom scrollbar is real (the empty-state flex spacer in ChatMessageList pushes onboarding content down, and the surface's min-height self-sizing combined with the spacer means content that fits still scrolls at 952px → 1159px), and the scoping via :has(.maka-onboarding-surface) is clean (no pollution of normal conversations; the spacer selector > div > [aria-hidden]:has(+ :last-child) precisely matches and can't hit the sentinel's sibling). At default sizes (1240×820) the e2e assertion scrollHeight == clientHeight holds and there's no regression. CI is green.

Conclusion: PASS with one P2 (reached at the repo's supported minimum window) plus P3s.

P2 — at the supported minimum height (480×320) the onboarding content is hard-clipped and unreachable — an accessibility regression relative to before. The three-layer overflow chain (root overflow-y: hidden → first child overflow: hidden → surface height:100%; min-height:0; overflow:hidden) leaves no scroll path anywhere, but the card is ~590-660px tall (onboarding-hero.tsx four-row provider list + buttons, wordmark + card + skip) while a 320px window leaves only ~240-260px of chat viewport — the lower half (Browse providers / connect / Skip) is cut off with no way to reach it. Before this PR the root scrollbar could reach the clipped content (surface had no overflow constraint, messageArea flex: 1 0 auto doesn't shrink), so this PR introduces the regression. @media (max-height: 720px) only changes align-items: start, providing no internal scrolling fallback. The repo explicitly maintains 320px as a tested contract (window-state.ts:31-37SAFE_MIN_HEIGHT, main-window.ts:311-318 minHeight clamp) — Qodo flagged the same point. Suggested fix: keep the outer containment, change the surface to overflow-y: auto (scroll internally when content doesn't fit), and add a 480×320 e2e (the fixture's size env is only read when a scenario is set — main-window.ts:600-616); the existing cardBottom <= viewportBottom assertion is already the right test, it just lacks size coverage.

P3 (optional): the commit's Generated-by: Codex trailer is escaped as a literal \n in the commit message (not a real trailer line) — the repo's Ai Use Disclosure check warns on this; worth rewriting the trailer properly at squash; the e2e only covers the default 1240×820 (which is why the P2 slipped through); the structural selector depends on Astryx DOM ordering (the spacer being last-child's previous sibling) — commented and e2e-guarded, fine, but fragile to upstream empty-state restructuring.


AI-assisted review disclosure: this review was produced with AI assistance (pi review subagent on opencode-go/deepseek-v4-flash). The subagent traced the spacer/ChatLayout geometry and the three-layer overflow chain from the PR head source; the P2 is a geometry calculation (590-660px card vs 240-260px viewport), not an observed render. Please weigh these findings with your own judgment.

中文摘要(AI 辅助审查)

结论:PASS(1 个 P2 + P3)。问题真实(ChatMessageList 空态前恒有 aria-hidden flex spacer 把内容推到底部,onboarding surface 的 min-height 自撑与其叠加——内容放得下却有页面滚动条,952px 视口→1159px 滚动范围);:has(.maka-onboarding-surface) 作用域干净不污染普通对话,spacer 选择器精确匹配不会误伤 sentinel。默认尺寸(1240×820)下 e2e 断言 scrollHeight==clientHeight 成立无回归。CI 全绿。P2:仓库支持的最小高度(480×320)下 onboarding 内容被三层 overflow hidden 链硬裁剪且不可达——卡片固有 ~590-660px(onboarding-hero 四行 provider 列表+双按钮、wordmark+Card+skip),320px 窗口聊天视口仅 ~240-260px,下半部分(Browse providers/连接/Skip)被裁掉且全链无任何滚动路径;PR 之前 root 滚动能到达被裁内容(surface 无 overflow 约束、messageArea flex:1 0 auto 不收缩),所以这是本 PR 引入的可达性回归。@media (max-height:720px) 只改 align-items:start 无内部滚动兜底。仓库显式把 320px 维护为受测契约(window-state.ts:31-37 SAFE_MIN_HEIGHT)。建议:保留外层 contain、surface 改 overflow-y:auto(放不下时内部滚动),并补 480×320 e2e(fixture 尺寸 env 只在设 scenario 时读取,main-window.ts:600-616);现有 cardBottom<=viewportBottom 断言正好是现成测试,缺的只是尺寸覆盖。P3(可选):commit 的 Generated-by: Codex trailer 被写成字面 \n 转义(非真实 trailer 行,Ai Use Disclosure 检查已 warning,squash 时应重写);e2e 只覆盖默认 1240×820(正因如此 P2 得以通过 CI);结构性选择器依赖 Astryx DOM 顺序(spacer 需是 last-child 前一兄弟),已注释+e2e 兜底但脆弱。

Keep the onboarding surface inside ChatLayout's available height, preserve internal scrolling at the supported minimum window height, and cover both document and onboarding scroll geometry with Electron E2E.
Generated-by: Codex
@ARE404
ARE404force-pushed the codex/fix-first-run-viewport branch from dd33cc1 to ba16360CompareAugust 18, 2026 09:06

@Astro-HanAstro-Han 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.

LGTM

@Astro-Han
Astro-Han merged commit c0dc41c into apache:mainAug 18, 2026
12 checks passed

@Astro-HanAstro-Han 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.

Thanks for carrying the short-viewport fix through to the final head. I reviewed exact head ba16360dd791e8952eab5d43be7ecb57a3b14723.

The problem definition is correct: the onboarding empty-state spacer and viewport-sized surface created an outer scroll authority that did not belong in the chat layout. The current solution stays at the nearest existing seam: onboarding-scoped CSS removes the spacer/dock contribution, keeps the outer layout contained, and gives the onboarding surface its own overflow-y: auto fallback. That is simpler than threading a second layout mode through shared UI components.

The final 480×320 regression now proves that the content remains reachable through internal scrolling, while the normal-size test protects the original phantom-scrollbar fix. Current-head checks are green, and the PR includes visual-inspection evidence.

Conclusion: APPROVE — no P0–P2 findings.

Unverified, non-blocking gap: the minimum-height case uses Playwright viewport sizing rather than a separate native BrowserWindow resize/zoom matrix; the current Electron coverage and geometry assertions are sufficient for this localized change.

AI-assisted review disclosure: Codex coordinated an independent @reviewer pass and a read-only ollama-cloud/deepseek-v4-flash:high pass. The review traced the ChatLayout/ChatMessageList DOM and overflow chain, checked the final short-viewport fix and regression tests, and refreshed current-head CI/review state. No local Electron run was performed in this final pass. A human contributor remains responsible for the final merge decision.

中文摘要

已复评最终 head。问题根因是 onboarding 空态 spacer 与视口高度共同制造了不应存在的外层滚动;当前方案在 onboarding 现有 CSS seam 内解决,没有新增并行布局状态。最终版本使用 surface 内部滚动,480×320 回归测试证明最小高度下内容仍可达,正常尺寸测试继续保护 phantom scrollbar 修复;当前 checks 全绿且 PR 已提供视觉检查证据。没有 P0–P2,结论:APPROVE。

非阻断缺口:最小高度用的是 Playwright viewport,而不是额外的原生窗口 resize/zoom 矩阵。

Sign up for freeto 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.

3 participants

@ARE404@Astro-Han@hqhq1025