emilkowalski / vaul

An unstyled drawer component for React.
https://vaul.emilkowal.ski
MIT License
5.26k stars 169 forks source link

always render content of the drawer to use with getElementById #379

Open robthepaper opened 1 week ago

robthepaper commented 1 week ago

Hi, i'm using OverlayScrollbars library to customize scrollbar of a div and I need the content of the drawer to always be renderered so the html element exist and is treated by OverlayScrollbars.

Is there an prop to always render the content and when we open the draer it just sets visibility to visible ? Right now when the drawer is triggered, it destroy and recreate its content.

HashCookie commented 1 week ago

I also have this issue. Have you solved it yet?

robthepaper commented 1 week ago

nope, tried wrapping it in a component with open always true but it unmount as soon as I click outside to close. In MaterialUi there is a prop named keepmounted that solve that issue I think. would be nice if there could be something similar.

robthepaper commented 1 week ago

the Content component has a prop named forceMount... maybe it can work. will try tonight

https://www.radix-ui.com/primitives/docs/components/dialog#content

robthepaper commented 1 week ago

okay, i found a solution ( i'm using Sveltekit) and used the doc api of bits-ui https://www.bits-ui.com/docs/components/dialog#dialogroot

I use the prop portal to teleport the drawer to a div then onOpenChange to detect when the drawer is opened thus mounted and then I can instantiate my OverlayScrollbars by getting the id of the content ( i have to set a custom id too) :

import * as DrawerShad from "$lib/components/ui/drawer/index.js";
    import { onMount } from 'svelte';

    import 'overlayscrollbars/overlayscrollbars.css';
    import { 
        OverlayScrollbars, 
        ScrollbarsHidingPlugin, 
        SizeObserverPlugin, 
        ClickScrollPlugin 
    } from 'overlayscrollbars';

export let drawerShadOpen = true;
let elementToRender : HTMLDivElement;
let isMounted = false
    onMount(() => {

        elementToRender = document.getElementById('middleContainerContainer')
        isMounted = true

    })

    let osInstanceSidebar;

    function onOpenChange(open: boolean) {

        if(open && isMounted) {

            // simple initialization with an element with 
            let drawerElement;
            setTimeout(()=> {
                drawerElement = document.getElementById('test');

                console.log("onOpenChange called", open, drawerElement);

                if (drawerElement) {
                    console.log('drawerElement', drawerElement);
                    osInstanceSidebar = OverlayScrollbars(drawerElement, 
                        {
                            scrollbars: {
                                visibility: "auto",
                                autoHide: 'scroll',
                                autoHideDelay: 250,
                                theme: 'os-theme-dark',
                            },
                        }, {
                            updated: (osInstance, onUpdatedArgs) => {
                                //console.log('OverlayScrollbars updated', osInstance, onUpdatedArgs);
                                // You can place any code here that should run when the instance is updated
                            }
                        }
                    );
                }
            },0)

        }
    }

</script>
<DrawerShad.Root bind:open={drawerShadOpen} direction="left" portal={elementToRender} onOpenChange={onOpenChange}>

    <DrawerShad.Trigger asChild let:builder>
      <ButtonShad builders={[builder]} variant="outline" class="!relative !z-10">Open Drawer</ButtonShad>
    </DrawerShad.Trigger>

        <DrawerShad.Content id={'test'} style="visibility:{drawerVisible ? 'visible': 'hidden'}; width:{drawerWidth} !important; height: 100vh; width:300px; padding-top: 0rem !important;  padding-left: 0rem !important; border-radius: 0px;">
        <div id="sidebarShadContainer" class="h-full" >

<!-- my content -->

 </DrawerShad.Content>

  </DrawerShad.Root>
HashCookie commented 1 week ago

Thank you for your response. I have decided to use the Ant Design UI framework instead.