Approaching dialog design and reusability
This might seem a bit like a noob question but I 'm trying to figure out a good approach to developing a dialog component that encapsulates the show /hide functionality without having to utilise page variables to set state e .g . dialog shown /hidden . The idea being that I can reuse this component in various places without any prerequisite configuration on the page and just configure the component accordingly . I developed something last year but it still requires capturing the state on the page and I 'm thinking there must be a way to do this in the context of a component , particularly if you have multiple dialogs that need to be shown depending on the action taken . I tried to reverse engineer a couple of examples I 've seen e .g . Andreas ' color -picker panel , Max 's dialog example for Spark , etc . , but not having much luck . I just can 't seem to figure this problem out . I could use the Popover API but that 's not really the best for a dialog where some kind of input is required (better for tooltips , etc . ) and it also means that the page is not inert either , so you can still interact with elements behind the dialog . I could also forego the dialog and opt for a separate page for CRUD operations but some are simple e .g . one field to input , so better suited to a dialog for UX instead of loading a new page . Hi Tom ! Dialogs are easy . Proper dialogs are hard π For my implementation I needed : - Provider context for the whole site (to prevent body scroll ) - A dialog component that does not render anything but holds the context and states - A portal (this is a popover used as a portal so that is always rendered in the top layer ) - The actual dialog content - A trigger button that hooks into the dialog context and opens the dialog Also what is your issue with inputs , im using it for quite a few popovers just fine - perhaps I can be of help for a change π Thanks for sharing . I was aware of the backdrop blur but not the ability to disable it . I know I can do that by setting popover to manual on the target div but that means you have to handle hide logic without the benefit of light dismiss when using auto ; otherwise , I βm not aware of a way to make the rest of the content inert behind the popover . I haven βt had any challenges around using an input with the Popover API ; it was more about best practice choices on when to use it . I βm no expert though so open to discussion on that . It would certainly be simpler if I could use Popover API if I could prevent background interaction and still have the light dismiss on background click , escape , etc . , because you βd just have to specify a target id as an attribute for the component and have that dynamically linked to the div id attribute in the component . Perhaps another way to think about it : is it like such an important criteria to you that you cannot work with the perceived downsides of the popover api ? At least in my opinion it is so much easier that I prefer using it , although I βm still not an expert . Just found out the other week about the backdrop attribute π Yeah , I had a good scour on MDN but no dice . The Popover API (unlike dialog 's showModal() ) does not render background content inert i .e . it 's non -modal as I understand it . It is possible to set the inert property to true on the root element and I have tested that before , but you need a way to unset it and also still handle that in the context of the component without tracking a page variable e .g . isInert for the root element . It is important that other content is not editable for a few reasons e .g . focusing out of the modal , you click something during an API call , some stuff around accessibility that I don 't fully understand yet , etc . @Janis / @Max Okay , so might have identified a simple way to handle this . Dialog component receives an attribute of dialog-id for the popover , which is used to populate an id attribute for the dialog element in the component . Use any normal button on the page where you have your cta and set popovertarget to the id of the popover . In the dialog component , set an event of toggle on the dialog element and trigger one line of custom code : function toggleInert (args, ctx) {
document.getElementById("main").toggleAttribute("inert");
}You just need to ensure that your page root element is not the main div , so serves as a wrapper around the main content so that your dialog component is a sibling to the main , which means that only the main div content is set inert and the dialog is ignored . You need to make sure the main div has an id attribute of "main " though . Seems less complicated but not bulletproof . Any issues with this approach do you think ? Inspiration : https://blog.logrocket.com/developing-modals-using-only-css-popover-api/#making-dialog-toggleable-using-popover-api I did think of an alternative to using App as the id , which is the main wrapper that toddle applies so unlikely to change and would mean set and forget , but then couldn 't figure out how to set the dialog to not be inert as inert descends to all children . Would be cool if there was a reasonably simple toddle -only and no custom action approach .