Skip to content

Forward focus and scrollIntoView to the host - #627

Open
airhorns wants to merge 1 commit into
Shopify:mainfrom
airhorns:polyfill-imperative-element-methods
Open

Forward focus and scrollIntoView to the host#627
airhorns wants to merge 1 commit into
Shopify:mainfrom
airhorns:polyfill-imperative-element-methods

Conversation

@airhorns

Copy link
Copy Markdown

What changed

focus() and scrollIntoView() are missing from polyfilled elements, even though Remote DOM already has a method-call channel and both operations can be performed by the rendered host element. Remote code type-checked against lib.dom therefore fails at runtime before it can use that channel.

This adds a general imperative-method hook to @remote-dom/polyfill, implements focus() and scrollIntoView() on the polyfill's shared Element abstraction, and wires the core polyfill hook to the connected RemoteConnection. Options are forwarded unchanged. Standalone or disconnected polyfilled elements keep browser-like no-op behavior when no host hook is available.

The core regression test connects a real RemoteRootElement and RemoteReceiver, registers the host implementation, and verifies both method calls end to end.

These methods live on the shared Element class because that is the current concrete class returned for ordinary and custom HTML elements on main. #626 separately proposes concrete HTML constructor identity.

getBoundingClientRect() is deliberately not included: it is synchronous and returns host layout data, which cannot be faithfully implemented over an asynchronous remote connection.

Validation

  • pnpm exec vitest run (178 tests)
  • pnpm lint
  • pnpm type-check
  • mise exec node@20.20.0 -- pnpm --filter @remote-dom/polyfill --filter @remote-dom/core build

@airhorns
airhorns force-pushed the polyfill-imperative-element-methods branch from f499904 to a9eef6d Compare July 28, 2026 14:17
Assisted-By: devx/ca2f43ab-bbf9-4273-b1bc-0b06f8c90a57
@airhorns
airhorns force-pushed the polyfill-imperative-element-methods branch from a9eef6d to 11971c2 Compare July 28, 2026 14:19
Comment on lines +79 to +83
if (arg === undefined) {
this.callHostMethod('scrollIntoView');
} else {
this.callHostMethod('scrollIntoView', arg);
}

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.

Suggested change
if (arg === undefined) {
this.callHostMethod('scrollIntoView');
} else {
this.callHostMethod('scrollIntoView', arg);
}
this[HOOKS].callMethod?.(this as any, 'scrollIntoView', arg);

Comment on lines +71 to +75
if (options === undefined) {
this.callHostMethod('focus');
} else {
this.callHostMethod('focus', options);
}

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.

Suggested change
if (options === undefined) {
this.callHostMethod('focus');
} else {
this.callHostMethod('focus', options);
}
this[HOOKS].callMethod?.(this as any, 'focus', arg);

Comment on lines +39 to +42
protected callHostMethod(method: string, ...args: unknown[]) {
this[HOOKS].callMethod?.(this as any, method, ...args);
}

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.

This makes the method callable from userland. Callsites must just use this[HOOKS].callMethod?.(this as any, 'scrollIntoView', arg) directly (see other suggestion comments).

Suggested change
protected callHostMethod(method: string, ...args: unknown[]) {
this[HOOKS].callMethod?.(this as any, method, ...args);
}

Sign up for free to 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