Skip to content

Conversation

@TarunAdobe
Copy link
Contributor

@TarunAdobe TarunAdobe commented Nov 11, 2025

Description

Sets this.listenerHost = this.target in overlay-trigger-directive’s overridden update() when a listenerHost is not already defined, mirroring the parent directive’s behavior. This prevents type errors during the reconnected flow when listenerHost is required but unset.

Motivation and context

When an overlay trigger directive’s reconnected hook runs with no listenerHost set in its overridden update(), we see type/runtime errors. Aligning with the parent directive and setting this.listenerHost = this.target prevents these errors and keeps typing consistent with expectations when slottable-request-directive executes. The parent directive already uses this pattern; this brings overlay-trigger-directive in line.

Related issue(s)

Screenshots (if appropriate)


Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

@changeset-bot
Copy link

changeset-bot bot commented Nov 11, 2025

🦋 Changeset detected

Latest commit: 0477afd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 78 packages
Name Type
@spectrum-web-components/overlay Patch
@spectrum-web-components/combobox Patch
@spectrum-web-components/contextual-help Patch
@spectrum-web-components/menu Patch
@spectrum-web-components/picker Patch
@spectrum-web-components/popover Patch
@spectrum-web-components/tooltip Patch
@spectrum-web-components/bundle Patch
@spectrum-web-components/truncated Patch
@spectrum-web-components/breadcrumbs Patch
@spectrum-web-components/action-menu Patch
@spectrum-web-components/action-bar Patch
@spectrum-web-components/card Patch
@spectrum-web-components/accordion Patch
@spectrum-web-components/action-button Patch
@spectrum-web-components/action-group Patch
@spectrum-web-components/alert-banner Patch
@spectrum-web-components/alert-dialog Patch
@spectrum-web-components/asset Patch
@spectrum-web-components/avatar Patch
@spectrum-web-components/badge Patch
@spectrum-web-components/button-group Patch
@spectrum-web-components/button Patch
@spectrum-web-components/checkbox Patch
@spectrum-web-components/clear-button Patch
@spectrum-web-components/close-button Patch
@spectrum-web-components/coachmark Patch
@spectrum-web-components/color-area Patch
@spectrum-web-components/color-field Patch
@spectrum-web-components/color-handle Patch
@spectrum-web-components/color-loupe Patch
@spectrum-web-components/color-slider Patch
@spectrum-web-components/color-wheel Patch
@spectrum-web-components/dialog Patch
@spectrum-web-components/divider Patch
@spectrum-web-components/dropzone Patch
@spectrum-web-components/field-group Patch
@spectrum-web-components/field-label Patch
@spectrum-web-components/help-text Patch
@spectrum-web-components/icon Patch
@spectrum-web-components/icons-ui Patch
@spectrum-web-components/icons-workflow Patch
@spectrum-web-components/icons Patch
@spectrum-web-components/iconset Patch
@spectrum-web-components/illustrated-message Patch
@spectrum-web-components/infield-button Patch
@spectrum-web-components/link Patch
@spectrum-web-components/meter Patch
@spectrum-web-components/modal Patch
@spectrum-web-components/number-field Patch
@spectrum-web-components/picker-button Patch
@spectrum-web-components/progress-bar Patch
@spectrum-web-components/progress-circle Patch
@spectrum-web-components/radio Patch
@spectrum-web-components/search Patch
@spectrum-web-components/sidenav Patch
@spectrum-web-components/slider Patch
@spectrum-web-components/split-view Patch
@spectrum-web-components/status-light Patch
@spectrum-web-components/swatch Patch
@spectrum-web-components/switch Patch
@spectrum-web-components/table Patch
@spectrum-web-components/tabs Patch
@spectrum-web-components/tags Patch
@spectrum-web-components/textfield Patch
@spectrum-web-components/thumbnail Patch
@spectrum-web-components/toast Patch
@spectrum-web-components/top-nav Patch
@spectrum-web-components/tray Patch
@spectrum-web-components/underlay Patch
@spectrum-web-components/base Patch
@spectrum-web-components/grid Patch
@spectrum-web-components/opacity-checkerboard Patch
@spectrum-web-components/reactive-controllers Patch
@spectrum-web-components/shared Patch
@spectrum-web-components/styles Patch
@spectrum-web-components/theme Patch
@spectrum-web-components/eslint-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Nov 11, 2025

📚 Branch Preview

🔍 Visual Regression Test Results

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

Deployed to Azure Blob Storage: pr-5873

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

@TarunAdobe TarunAdobe force-pushed the ttomar/trigger-directive branch from b089a7b to 678b431 Compare November 11, 2025 10:00
@TarunAdobe TarunAdobe marked this pull request as ready for review November 11, 2025 10:01
@TarunAdobe TarunAdobe requested a review from a team as a code owner November 11, 2025 10:01
Rajdeepc
Rajdeepc previously approved these changes Nov 11, 2025
Copy link
Contributor

@Rajdeepc Rajdeepc left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for bringing this in!

@Rajdeepc Rajdeepc added the Status: Ready for review PR ready for review or re-review. label Nov 11, 2025
// Now click the cached trigger to open the overlay.
const opened = oneEvent(cachedTrigger, 'sp-opened');
cachedTrigger.click();
await opened;
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add some assertions after this to confirm the popover is rendered?

this.target = part.element as HTMLElement;
newTarget = true;
}
this.listenerHost = this.target;
Copy link
Contributor

Choose a reason for hiding this comment

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

are we sure this is the correct default? im trying to understand the override but the strategies and controller complexity is making my brain warp. can we chat about this in our team meeting thursday?

Copy link
Contributor

@Rajdeepc Rajdeepc Nov 13, 2025

Choose a reason for hiding this comment

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

The type error occurs because this.listenerHost is undefined when reconnected() → init() runs before the overlay is ready.
This happens because the parent class sets this.listenerHost = this.target in update(), child class overrides update() but only sets this.listenerHost inside the async handleOverlayReady callback. If reconnection happens before the overlay exists → this.listenerHost is undefined and it will error out.

this.listenerHost = this.target is not architecturally correct coz the slottable-request event is dispatched from the overlay element with bubbles: false.

Attaching the listener to this.target (the trigger button) means it will never receive the event since it doesn't bubble. This breaks the lazy content loading mechanism entirely.

We can override the reconnected() in the child class to guard against premature initialization, its cleaner since it's specific to the child's async overlay setup pattern.

override reconnected(): void {
    // Only call init() if the overlay is ready
    if (this.listenerHost) {
        this.init();
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good job finding a solution @Rajdeepc !!! I updated the change.

@Rajdeepc Rajdeepc dismissed their stale review November 13, 2025 09:05

Revisiting coz i see the events don't bubble from parent 'slottable-requestand the listener needs to be on the overlay. there are two ways to do this, we can wait for the overlay to exist before attaching the listener or guard against callinginit()` method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: listenerHost can be uninitialized in overlay-trigger-directive

4 participants