fix: let plugin activities control their own modal height#956
fix: let plugin activities control their own modal height#956
Conversation
Plugin activity host used `height: 100%` which resolved to 0 in Safari when the dialog only had `max-height` (no explicit `height`), collapsing short activities such as URL source to header-only visibility with overflow clipped. Make the host and its inner wrapper `display: contents` so the plugin activity element is effectively a direct layout child of the dialog. Plugin authors now control sizing purely via CSS on their own element (e.g. `:has()` for full-height, or viewport units for self-sizing), with no framework API or attribute coupling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughReplaces the PluginActivityRenderer wrapper layout from a flex/positioned element to Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Adjusts the plugin activity host layout so plugin activities can determine their own modal sizing via their own CSS, fixing Safari cases where the host’s height: 100% effectively collapsed when the <dialog> only had max-height.
Changes:
- Switch
uc-plugin-activity-hostfrom a flex/100%-height wrapper todisplay: contents. - Switch the host’s internal container
<div>todisplay: contentswhile keeping it as the render mount point for plugin activities.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/blocks/PluginActivityRenderer/uc-plugin-activity-host.css |
Makes the host element transparent to layout with display: contents to avoid Safari percentage-height collapse. |
src/blocks/PluginActivityRenderer/PluginActivityRenderer.ts |
Updates the render mount wrapper <div> to display: contents so the plugin activity element participates directly in dialog flex sizing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace arbitrary delay(1000) calls with editor `change` event waits so the mirror operation is guaranteed to commit before Apply is clicked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/validation.e2e.test.tsx`:
- Around line 451-454: The helper waitForEditorChange currently can hang because
document.querySelector('uc-cloud-image-editor') may be null or the change event
might never fire; update waitForEditorChange to attach the event listener only
if the element exists and add a timeout fallback (e.g., setTimeout) that rejects
or resolves with an error after a configurable delay, and ensure any created
listener and timeout are cleaned up when either the event fires or the timeout
triggers; reference the waitForEditorChange function and the
'uc-cloud-image-editor' element and make the timeout clear with a descriptive
Error message so awaiting callers fail fast instead of hanging.
🪄 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
Run ID: a9b8c80f-b7b5-4bfb-b464-948941d60a63
📒 Files selected for processing (1)
tests/validation.e2e.test.tsx
| const waitForEditorChange = () => | ||
| new Promise<void>((resolve) => { | ||
| document.querySelector('uc-cloud-image-editor')?.addEventListener('change', () => resolve(), { once: true }); | ||
| }); |
There was a problem hiding this comment.
Add a timeout/failure path to waitForEditorChange to prevent hanging awaits.
At Line 453, optional chaining can leave the Promise pending forever if the editor is missing (or the awaited event is missed), which makes this test flaky and slow-failing.
Proposed hardening
- const waitForEditorChange = () =>
- new Promise<void>((resolve) => {
- document.querySelector('uc-cloud-image-editor')?.addEventListener('change', () => resolve(), { once: true });
- });
+ const waitForEditorChange = (timeoutMs = 5000) =>
+ new Promise<void>((resolve, reject) => {
+ const editor = document.querySelector('uc-cloud-image-editor');
+ if (!editor) {
+ reject(new Error('uc-cloud-image-editor not found'));
+ return;
+ }
+
+ const timeoutId = window.setTimeout(() => {
+ reject(new Error('Timed out waiting for uc-cloud-image-editor change event'));
+ }, timeoutMs);
+
+ editor.addEventListener(
+ 'change',
+ () => {
+ window.clearTimeout(timeoutId);
+ resolve();
+ },
+ { once: true },
+ );
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const waitForEditorChange = () => | |
| new Promise<void>((resolve) => { | |
| document.querySelector('uc-cloud-image-editor')?.addEventListener('change', () => resolve(), { once: true }); | |
| }); | |
| const waitForEditorChange = (timeoutMs = 5000) => | |
| new Promise<void>((resolve, reject) => { | |
| const editor = document.querySelector('uc-cloud-image-editor'); | |
| if (!editor) { | |
| reject(new Error('uc-cloud-image-editor not found')); | |
| return; | |
| } | |
| const timeoutId = window.setTimeout(() => { | |
| reject(new Error('Timed out waiting for uc-cloud-image-editor change event')); | |
| }, timeoutMs); | |
| editor.addEventListener( | |
| 'change', | |
| () => { | |
| window.clearTimeout(timeoutId); | |
| resolve(); | |
| }, | |
| { once: true }, | |
| ); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/validation.e2e.test.tsx` around lines 451 - 454, The helper
waitForEditorChange currently can hang because
document.querySelector('uc-cloud-image-editor') may be null or the change event
might never fire; update waitForEditorChange to attach the event listener only
if the element exists and add a timeout fallback (e.g., setTimeout) that rejects
or resolves with an error after a configurable delay, and ensure any created
listener and timeout are cleaned up when either the event fires or the timeout
triggers; reference the waitForEditorChange function and the
'uc-cloud-image-editor' element and make the timeout clear with a descriptive
Error message so awaiting callers fail fast instead of hanging.
Summary
height: 100%which resolved to 0 in Safari when the dialog only hadmax-height(no explicitheight). Short activities like URL source collapsed to header-only with content clipped byoverflow: hidden.uc-plugin-activity-host) and its inner wrapper are nowdisplay: contents, so the plugin's activity element is effectively a direct layout child of the<dialog>. Percentage heights, flex sizing, and containing blocks chain through transparently, and:has()/[activity][active]selectors keep matching through the host.:has()-basedheight: 100%rules, unchanged.Test plan
start-fromandupload-listmodals (non-plugin) still size correctly🤖 Generated with Claude Code
Summary by CodeRabbit
Style
Refactor
Tests