Skip to content

fix(app): restore prompt popover visibility#525

Merged
Astro-Han merged 1 commit into
devfrom
codex/fix-i524-slash-popover
May 10, 2026
Merged

fix(app): restore prompt popover visibility#525
Astro-Han merged 1 commit into
devfrom
codex/fix-i524-slash-popover

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Allow the prompt composer card to show / and @ popovers outside its clipped card bounds.
  • Keep PromptPopover owned and anchored by PromptInput; this is not a new general overlay primitive.
  • Restore visible hover state for slash and @mention rows, and expand regression coverage for visibility, top spacing, topmost hit-testing, and hover paint.

Why

#508 wrapped the composer in DockCard, whose root uses overflow: hidden for joined-card clipping. PromptPopover still rendered inline as an upward absolute child, so typing / or @ could update popover state while the suggestion body was clipped outside the card.

This fix keeps the original prompt popover positioning model and applies a local overflow opt-out only to the prompt composer DockCard. Other DockCard instances keep their clipping contract. The fix deliberately does not introduce a body-level portal, fixed-position overlay system, or Kobalte migration; those would be broader design work for a later slice.

Related Issue

Closes #524

Human Review Status

Pending. AstroHan manually verified the current Electron build: home /, home @, session /, session @, and multi-segment composer states are functionally normal. Remaining feedback about @mention/file popover visual design is a separate DESIGN.md alignment follow-up, not part of this hotfix.

Review Focus

  • DockCard overflow is only opted out on the prompt composer card, not globally.
  • PromptPopover remains anchored inside PromptInput with the original max-h-80 -top-2 -translate-y-full visual constraints.
  • Slash and @mention rows should have a visible hover/active background distinct from the popover surface.
  • The focused E2E should catch clipped, top-edge, covered, and transparent-hover regressions.

Risk Notes

Visible UI change in the prompt composer popover layer. The main risk is prompt-card joined-segment clipping because this card locally opts out of DockCard overflow. The change is scoped to the prompt composer wrapper and does not change the shared DockCard primitive.

No dependency, data, permission, migration, packaging, updater, signing, shell, credential, deletion, generated-content, or local-file behavior changes.

How To Verify

Typecheck: bun --cwd packages/app typecheck -> ok
Focused E2E: bun --cwd packages/app test:e2e -- e2e/prompt/prompt-slash-open.spec.ts -> 3 passed
Diff check: git diff --check -> ok
Manual Electron: AstroHan verified home /, home @, session /, session @, and multi-segment composer states -> normal

The focused E2E covers session /open, bare / in the home composer, and @mention suggestions. It asserts visible popovers/items, topmost hit-testing via elementFromPoint, top viewport gap, and non-transparent hover paint.

Screenshots or Recordings

Manual Electron check was done against the corrected i524 worktree dev environment. Earlier false negatives came from node_modules symlinks resolving @opencode-ai/app back to the main checkout; this was corrected locally before final manual verification.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, primary area, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

@Astro-Han Astro-Han added bug Something isn't working P1 High priority app Application behavior and product flows ui Design system and user interface labels May 10, 2026
@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 51 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 437df51b-ae25-431d-b80a-373c9f4973a5

📥 Commits

Reviewing files that changed from the base of the PR and between d207013 and 9bd16a9.

📒 Files selected for processing (3)
  • packages/app/e2e/prompt/prompt-slash-open.spec.ts
  • packages/app/src/components/prompt-input/slash-popover.tsx
  • packages/app/src/pages/session/composer/session-composer-region.tsx
📝 Walkthrough

Walkthrough

This PR resolves the slash-command popover clipping regression from PR #508 by moving PromptPopover outside the DockCard via Portal, computing fixed positioning based on ResizeObserver-tracked dock segment changes, and verifying visibility with E2E tests that assert elements remain topmost and interactable.

Changes

Slash Popover Portal & ResizeObserver Positioning

Layer / File(s) Summary
Popover Type Contract
packages/app/src/components/prompt-input/slash-popover.tsx
PromptPopover now accepts optional style?: JSX.CSSProperties prop for dynamic CSS properties.
ResizeObserver Positioning Logic
packages/app/src/components/prompt-input.tsx
PromptInput introduces popoverStyle signal and createEffect that uses ResizeObserver to detect dock segment size/position changes, computes fixed-position CSS coordinates and z-index, and recalculates on window resize and scroll.
Portal Rendering & Styling
packages/app/src/components/prompt-input.tsx, packages/app/src/components/prompt-input/slash-popover.tsx
PromptPopover is wrapped in Portal with computed popoverStyle applied; popover container class updated from -top-2 -translate-y-full transforms to origin-bottom-left pointer-events-auto positioning.
Session Composer Stacking Context
packages/app/src/pages/session/composer/session-composer-region.tsx
Fallback DockCard content wrapped in div with relative z-30 to establish stacking context; DockSegment ref assignment updated with type cast.
E2E Tests & Verification
packages/app/e2e/prompt/prompt-slash-open.spec.ts
New expectOnTop helper polls document.elementFromPoint to assert popover elements are visible and topmost; updated existing /open test and added tests for home composer slash commands and @mention file suggestions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Astro-Han/pawwork#508: Introduced the DockCard overflow: hidden that caused the slash popover clipping regression now being fixed by this PR.
  • Astro-Han/pawwork#375: Both PRs add/adjust ResizeObserver usage to track dock segment changes and keep UI layout in sync with dynamic positioning.
  • Astro-Han/pawwork#456: Both PRs modify session-composer-region.tsx for layout and z-index stacking adjustments.

Poem

🐰 A popover once trapped in a card,
Clipped by overflow—oh, how hard!
But Portal and ResizeObserver to the rescue,
Now it floats above, fresh and new,
Slash commands dance where you can see 'em,
Free as a bunny—come believe 'em!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(app): restore prompt popover visibility' clearly and concisely summarizes the main change: restoring the visibility of the prompt popover (slash and mention suggestions) after it was clipped by DockCard changes.
Linked Issues check ✅ Passed The PR directly addresses all coding objectives from issue #524: restores visible/interactable slash-command and @mention popovers by portaling them outside the clipped DockCard, preserves popover state and keyboard navigation, implements positioning via ResizeObserver, and includes E2E regression tests for popover visibility and hoverability.
Out of Scope Changes check ✅ Passed All changes are in scope: test additions for popover visibility regression, PromptInput portal/positioning implementation, PromptPopover style prop addition, and session composer wrapper adjustment—all directly supporting the issue #524 fix objective without unrelated refactors or dependencies.
Description check ✅ Passed The pull request description is thorough and follows the template structure with all required sections completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-i524-slash-popover

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request implements a portaled popover system for the prompt input to ensure that @mention and slash command suggestions remain visible above the composer. The changes include introducing a popover container in the session composer, using SolidJS Portals for rendering, and dynamically calculating the popover's position. Feedback was provided regarding the positioning logic in PromptInput, specifically suggesting that the createEffect should not depend on the popover's visibility state to prevent flickering and should align with SolidJS best practices for observer instantiation.

Comment thread packages/app/src/components/prompt-input.tsx Outdated
@Astro-Han Astro-Han force-pushed the codex/fix-i524-slash-popover branch 3 times, most recently from 6faa59c to d207013 Compare May 10, 2026 16:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/app/src/components/prompt-input.tsx (1)

314-314: 💤 Low value

Consider extracting positioning constants.

The positioning calculation uses inline numeric literals:

  • -8 for the top offset
  • 80 for minimum popover height
  • 16 for the margin in max-height calculation

Extracting these to named constants (e.g., POPOVER_TOP_OFFSET, POPOVER_MIN_HEIGHT, POPOVER_MARGIN) would improve readability and maintainability if these values need adjustment later.

♻️ Example refactor
+const POPOVER_TOP_OFFSET = 8
+const POPOVER_MIN_HEIGHT = 80
+const POPOVER_MARGIN = 16
+const POPOVER_Z_INDEX = 1000
+
 createEffect(() => {
   ...
   const update = () => {
     const segmentRect = segment.getBoundingClientRect()
     setPopoverStyle({
       position: "fixed",
-      top: `${segmentRect.top - 8}px`,
+      top: `${segmentRect.top - POPOVER_TOP_OFFSET}px`,
       left: `${segmentRect.left}px`,
       right: "auto",
       bottom: "auto",
       width: `${segmentRect.width}px`,
-      "max-height": `${Math.max(80, segmentRect.top - 16)}px`,
+      "max-height": `${Math.max(POPOVER_MIN_HEIGHT, segmentRect.top - POPOVER_MARGIN)}px`,
       transform: "translateY(-100%)",
-      "z-index": 1000,
+      "z-index": POPOVER_Z_INDEX,
     })
   }
   ...
 })

Also applies to: 319-319

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/src/components/prompt-input.tsx` at line 314, Extract the inline
numeric literals used for popover positioning into named constants (e.g.,
POPOVER_TOP_OFFSET for -8, POPOVER_MIN_HEIGHT for 80, and POPOVER_MARGIN for 16)
and replace the literals in the popover style calculations (the expression using
segmentRect.top, the min-height check, and the max-height calculation) with
those constants; define the constants at module scope near the top of
packages/app/src/components/prompt-input.tsx so they are easy to find and
update, and ensure the computed strings (e.g., `${segmentRect.top -
POPOVER_TOP_OFFSET}px`) and numeric comparisons use the constants consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/app/src/pages/session/composer/session-composer-region.tsx`:
- Line 241: Remove the redundant type assertion on the ref prop: locate the JSX
where DockSegment (accepting ComponentProps<"div">) is given ref={props.inputRef
as (el: HTMLDivElement) => void} and replace it with a direct pass of the
callback by using ref={props.inputRef}; props.inputRef already has the correct
signature so no cast is needed.

---

Nitpick comments:
In `@packages/app/src/components/prompt-input.tsx`:
- Line 314: Extract the inline numeric literals used for popover positioning
into named constants (e.g., POPOVER_TOP_OFFSET for -8, POPOVER_MIN_HEIGHT for
80, and POPOVER_MARGIN for 16) and replace the literals in the popover style
calculations (the expression using segmentRect.top, the min-height check, and
the max-height calculation) with those constants; define the constants at module
scope near the top of packages/app/src/components/prompt-input.tsx so they are
easy to find and update, and ensure the computed strings (e.g.,
`${segmentRect.top - POPOVER_TOP_OFFSET}px`) and numeric comparisons use the
constants consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 75c26f4a-0e24-4122-81d3-efd103c31059

📥 Commits

Reviewing files that changed from the base of the PR and between def9339 and d207013.

📒 Files selected for processing (4)
  • packages/app/e2e/prompt/prompt-slash-open.spec.ts
  • packages/app/src/components/prompt-input.tsx
  • packages/app/src/components/prompt-input/slash-popover.tsx
  • packages/app/src/pages/session/composer/session-composer-region.tsx

Comment thread packages/app/src/pages/session/composer/session-composer-region.tsx Outdated
@Astro-Han Astro-Han force-pushed the codex/fix-i524-slash-popover branch from d207013 to 551e50a Compare May 10, 2026 17:13
@Astro-Han Astro-Han force-pushed the codex/fix-i524-slash-popover branch from 551e50a to 9bd16a9 Compare May 10, 2026 17:19
@Astro-Han

Copy link
Copy Markdown
Owner Author

Review follow-up summary:

  • Gemini inline thread: no longer applies on current head; the Portal / ResizeObserver / fixed-position implementation was removed. Replied and resolved.
  • CodeRabbit inline thread: fixed by removing the redundant DockSegment ref type assertion. Replied and resolved.
  • CodeRabbit direct/nitpick comments about positioning constants apply to the old fixed-position implementation and are obsolete on current head.

Verification after the final amend:

  • bun --cwd packages/app typecheck -> ok
  • bun --cwd packages/app test:e2e -- e2e/prompt/prompt-slash-open.spec.ts -> 3 passed
  • git diff --check -> ok

@Astro-Han Astro-Han merged commit cf7126b into dev May 10, 2026
20 checks passed
@Astro-Han Astro-Han deleted the codex/fix-i524-slash-popover branch May 10, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows bug Something isn't working P1 High priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Slash-command suggestions are clipped by the composer DockCard

1 participant