nolanlawson / emoji-picker-element

A lightweight emoji picker for the modern web
https://nolanlawson.github.io/emoji-picker-element/
Apache License 2.0
1.49k stars 85 forks source link

RFE: Autofocus the search input #470

Open arv opened 1 week ago

arv commented 1 week ago

What is the best way to autofocus the text input today?

In the future it would be nice to have an option to autofocus the input.

arv commented 1 week ago

Here is my current workaround:

// The emoji-picker-element does not allow auto focusing the search input
// when it's first rendered. We can work around this by observing the
// shadow DOM and focusing the search input when it's added to the DOM.
if (el.shadowRoot) {
  const m = new MutationObserver(records => {
    for (const record of records) {
      for (const node of record.addedNodes) {
        if (node.nodeType === Node.ELEMENT_NODE) {
          const search = (node as Element).querySelector('#search');
          if (search) {
            (search as HTMLElement).focus();
            m.disconnect();
          }
          return;
        }
      }
    }
  });

  m.observe(el.shadowRoot, {
    subtree: true,
    childList: true,
  });
}
nolanlawson commented 1 week ago

I don't think you need a MutationObserver. If you are the one rendering the picker, then you can wait a requestAnimationFrame and then focus the input.

Could you describe your usecase and why you'd like it to autofocus?

arv commented 1 week ago

I don't think you need a MutationObserver. If you are the one rendering the picker, then you can wait a requestAnimationFrame and then focus the input.

Maybe, it would be simpler but I do not generally like waiting for things. I think it would still involve a "loop" until the input is found.

Could you describe your usecase and why you'd like it to autofocus?

I'm showing the emoji picker in a popover. When the popover is shown I focus the text input so I can search right away.

https://github.com/user-attachments/assets/a971fa5f-07c1-4282-8585-706df582a7dc

nolanlawson commented 1 week ago

requestAnimationFrame is not really a wait. The browser hasn't rendered anything yet, so it's a good time to do a focus. You could probably also wait a Promise.resolve() tick or two.

arv commented 1 week ago

It is next frame which should be totally fine for focus since it does not need to change the dom.

I'll try it out but I still wish I didn't have to drill into the shadow dom like this.