beercss / beercss

Build material design interfaces in record time... without stress for devs... πŸΊπŸ’›
https://www.beercss.com
MIT License
940 stars 47 forks source link

Dialog close on navigation #266

Closed crypnull closed 1 month ago

crypnull commented 3 months ago

When clicking the browser back button, or the phones back button, an option to close the last opened dialog instead of navigating back a page should be available.

https://v10.material.angular.io/components/dialog/api

closeOnNavigation: boolean Whether the dialog should close when the user goes backwards/forwards in history. Note that this usually doesn't include clicking on links (unless the user is using the HashLocationStrategy).

I tried to hack together a solution using: https://developer.mozilla.org/en-US/docs/Web/API/History/pushState

acroyear commented 2 months ago

When dealing with back buttons (especially in mobile) this is a problem with a router solution, and so is out of scope of BeerCSS I should think.

I just managed that myself in my app. Basically, my routing (I'm just using hash-routing as it works, I don't use SSR, and it saves trouble writing the rewrite rules on apache2) will have the path, then a | with additional things, like "dialog=...".

So my player's current URL is https://_domain_/demo5/#/search|dialog=playQueue&player=default

So instead of relying on the #selector approach or direct calls to ui(), I have my components look at dialog= (only one is allowed at a time) and render that dialog (add the 'active' class) if they have it. Then close dialog is a 'history.popState()' rather than actively taking any action. route changes, renders re-run, dialog not in url so it goes away.

now some kind of assistance methods might help to better automate this against the dialog IDs so the old ui() and data- approaches could be coded (e.g., global callbacks to indicate that a dialog was opened/closed with its ID). but BeerCSS really shouldn't set/force a policy on routing because it could interfere with the routing systems of libraries that are using it (like react-router-dom) or home-grown routing systems like my own.

crypnull commented 2 months ago

When dealing with back buttons (especially in mobile) this is a problem with a router solution, and so is out of scope of BeerCSS I should think.

I just managed that myself in my app. Basically, my routing (I'm just using hash-routing as it works, I don't use SSR, and it saves trouble writing the rewrite rules on apache2) will have the path, then a | with additional things, like "dialog=...".

So my player's current URL is https://_domain_/demo5/#/search|dialog=playQueue&player=default

So instead of relying on the #selector approach or direct calls to ui(), I have my components look at dialog= (only one is allowed at a time) and render that dialog (add the 'active' class) if they have it. Then close dialog is a 'history.popState()' rather than actively taking any action. route changes, renders re-run, dialog not in url so it goes away.

now some kind of assistance methods might help to better automate this against the dialog IDs so the old ui() and data- approaches could be coded (e.g., global callbacks to indicate that a dialog was opened/closed with its ID). but BeerCSS really shouldn't set/force a policy on routing because it could interfere with the routing systems of libraries that are using it (like react-router-dom) or home-grown routing systems like my own.

This is really interesting, I would like to research this method further, do you have any more reading material on this method? Maybe it's not recommended, but I have some nested dialogs, so expanding this to support that also would be useful for me. I use Nginx and Laravel.

leonardorafael commented 1 month ago

This is a router issue, not Beer CSS itself. You can handle this, with something like that:

// listening to change hash event
window.addEventListener("hashchange", () => {
  closeAllOpenedDialogs();
});

// close all opened dialogs
function closeAllOpenedDialogs() {
  const elements = document.querySelectorAll('dialog.active, dialog[open]');
  for(let i=0; i<elements.length; i++) ui(elements[i]);
}

// added a hash before open a dialog
function openDialog(selector) {
  window.location.hash = "dialog";
  ui(selector);
}