Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Next] Binding to prop ref is broken for Command.Input in ShadowRoot #1120

Closed
MichaelBrunn3r opened this issue Feb 8, 2025 · 7 comments
Closed
Labels
triage A maintainer needs to review this issue and label it appropriately

Comments

@MichaelBrunn3r
Copy link
Contributor

Describe the bug

I wanted to auto-focus the command menu input when toggling it, but the autofocus prop did not seem to work. So instead I tried out focusing the <input> element manually, using the ref prop. In my project, binding to ref only ever initialised the value to null.

I guess I could circumvent the issue by querying for the <input>, but ref returning null does not seem to be intended behavior.

On Stackblitz I created 3 variants:

  1. normal: Mount the command menu component normally: <Menu />
  2. nonShadowTargetEl: Mount the component programmatically using the mount function
  3. shadowTargetEl: Mount the component programmatically inside a ShadowRoot

Each variant binds to the ref prop and uses $inspect to log changes to the console:

[normal]: inputEl init null
[normal]: inputEl update <input ...>
[nonShadowTargetEl]: inputEl init null
[shadowTargetEl]: inputEl init null
[nonShadowTargetEl]: inputEl update <input ... >

As you can see, 1 & 2 work as expected, both log the <input> element. 3, which is inside a ShadowRoot, does not work.

My guess is that ref is updated using something like document.querySelector? Despite having 3 <input> elements on screen, document.querySelectorAll("input").length return 2.

Reproduction

https://stackblitz.com/edit/vitejs-vite-szvvwd4b?file=src%2FApp.svelte

Logs

System Info

System:
  OS: Linux 6.13 cpe:/o:nixos:nixos:24.11 24.11 (Vicuna)
  CPU: (16) x64 12th Gen Intel(R) Core(TM) i5-1240P
  Memory: 23.54 GB / 31.06 GB
  Container: Yes
  Shell: 5.2.37 - /nix/store/gwgqdl0242ymlikq9s9s62gkp5cvyal3-bash-5.2p37/bin/bash
Binaries:
  Node: 22.12.0 - /nix/store/iyfkmhwfcbmn8rrnzzpdv5g1l7l72fla-nodejs-22.12.0/bin/node
  npm: 10.9.0 - /nix/store/iyfkmhwfcbmn8rrnzzpdv5g1l7l72fla-nodejs-22.12.0/bin/npm
  pnpm: 9.15.3 - /nix/store/aik0qrmx9wxy1q480lfwqv1wqsrhcsl8-pnpm-9.15.3/bin/pnpm
Browsers:
  Firefox: 134.0.1
npmPackages:
  bits-ui: ^1.0.0-next.87 => 1.0.0-next.87 
  svelte: ^5.19.6 => 5.19.6

Severity

annoyance

@MichaelBrunn3r MichaelBrunn3r added the triage A maintainer needs to review this issue and label it appropriately label Feb 8, 2025
@MichaelBrunn3r
Copy link
Contributor Author

Related to #828 it seems

@MichaelBrunn3r
Copy link
Contributor Author

If I understand the code correctly, ref is handled by this useRefById helper function from svelte-toolbelt?

@MichaelBrunn3r
Copy link
Contributor Author

MichaelBrunn3r commented Feb 8, 2025

Ok, if I have a reference to the shadow DOM in question, passing getRootNode to useRefById should resolve the issue.

So I would have to pass getRootNode to opts in the CommandInputState constructor

readonly opts: CommandInputStateProps,

Which need to be passed in props to useCommandInput

export function useCommandInput(props: CommandInputStateProps) {

I don't know yet how that prop can be passed

Ok, useCommandInput gets used by the Input component

This seems to be the root of the problem. There is no way that we can pass a custom root node (getRootNode) into the Command.Input component.

As far as I understand the code, simply adding a getRootNode would fix that? Very hacky fix, but at least I won't have to wait for the Svelte pull-request

@huntabyte
Copy link
Owner

Yes, I'm hesitant to expose it because then I have to expose that prop everywhere or create a global config provider that will be useless but still require me to maintain as soon as attachments (sveltejs/svelte#15000) land in Svelte, so there would need to be a breaking change possibly right after launching 1.0 or be stuck with a subpar solution until its time for a new major :/

 

@huntabyte
Copy link
Owner

The ideal state is that we don't need you to tell us what the root node is because we can get it from the node reference, via an anonymous attachment rather than using the id and doing a document.getElementById lookup.

@huntabyte
Copy link
Owner

Going to close this as we're tracking full shadow DOM support over at #828

@MichaelBrunn3r
Copy link
Contributor Author

MichaelBrunn3r commented Feb 8, 2025

Thanks. Good to know that there will be a fix soon-ish. The attachments approach seems like a good solution. Still, for me waiting isn't a solution, so I will probably manually query or create a pnpm patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage A maintainer needs to review this issue and label it appropriately
Projects
None yet
Development

No branches or pull requests

2 participants