huntabyte / vaul-svelte

An unstyled drawer component for Svelte.
https://vaul-svelte.com
MIT License
467 stars 19 forks source link

Drawer singleton / registry #101

Closed mustafa0x closed 3 weeks ago

mustafa0x commented 3 weeks ago

Thanks for vaul. We have a list of items, each that can open a drawer to configure. This caused perf to take a hit.

We want to move to a singleton/registry approach. Any prior art on this?

matteron commented 3 weeks ago

I don't have a public repo up for it yet, but I just implemented something like this for a right click menu on desktop / using a drawer to select options on mobile.

I have a store that maintains a centralized context menu state:

class ContextMenuStore {
   #data = $state<DataType | null>(null);
   get data(){
      return this.#data;
   }

   set data(val: DataType | null) {
      this.#data = val;
   }
}
export const contextMenu = new ContextMenuStore();

Then I created a drawer component that gets added to the centralized location you wish to access it from. (My case it's in the root layout, but presumably you'd just have it on the page that configurations happen.)

<Drawer.Root
    open={!!contextMenu.data}
    controlledOpen
    onOpenChange={() => contextMenu.data = null}
>...</Drawer.Root>

Alternatively you can just mimic this idea inside the configuration page itself. Where the page component just maintains a state variable and the drawer listens to that.

<script>
    let configureTarget = $state<DataType | null>(null);
</script>
<Drawer.Root
    open={!! configureTarget}
    controlledOpen
    onOpenChange={() => configureTarget = null}
>...</Drawer.Root>

In either case, on the list of items you'd have something where on click you'd set the state variable to the data to populate the configuration form.

huntabyte commented 3 weeks ago

@matteron this is essentially how I handle this as well!

mustafa0x commented 3 weeks ago

Thanks a ton, @matteron!