Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have some way of opening `<dialog>` elements without JavaScript #3567

Open
keithamus opened this Issue Mar 14, 2018 · 18 comments

Comments

10 participants
@keithamus
Copy link

keithamus commented Mar 14, 2018

dialog elements are a great addition and I'm glad they're getting implemented, but a key part of their functionality relies on JavaScript: to open a <dialog> you need to use JavaScript to set the open attribute.

It'd be great if there was a way to make a <a> or a <button> elements capable of opening dialogs.

Precident already exists for page interactivity baked into HTML - for example <a href="#.."> can already scroll the page, and <details> elements are capable of hiding elements behind interactivity, so I think it stands to reason <dialog> elements could be opened by other page elements.

@annevk

This comment has been minimized.

Copy link
Member

annevk commented Mar 14, 2018

Yeah, it's somewhat weird you can close them via <form method=dialog>, but not open them in any way.

@guest271314

This comment has been minimized.

Copy link
Contributor

guest271314 commented Mar 17, 2018

One workaround would be to utilize <input type="checkbox"> with an associated <label> element styled as a button and toggle display of the <dialog> element

<!DOCTYPE html>
<html>
<head>
  <style>
    #dialogInput, #dialogInput:checked ~ #dialog {
      display: none;
    }
    [for="dialogInput"] {
      appearance: button;
      -webkit-appearance: button;
      -moz-appearance: button;
      padding: 2px;
    }
  </style>
</head>
<body>
  <label for="dialogInput">Dialog</label>
  <input type="checkbox" id="dialogInput">
  <dialog id="dialog" open>
    <p>Hello universe</p>
  </dialog>
</body>
</html>

or to include <dialog> element as child of <details> element at HTML.

@domenic

This comment has been minimized.

Copy link
Member

domenic commented Mar 17, 2018

I don't think there's a very significant difference between e.g. <button opendialog="mydialog"> and <button onclick="mydialog.open()">. That is, I think HTML already has the ability to open dialogs.

@keithamus

This comment has been minimized.

Copy link
Author

keithamus commented Mar 17, 2018

IMO there are very specific and quite substantial differences with those two examples. For one, the latter cannot be used in combination with CSP headers that disable inline JavaScript. Secondly the latter example cannot be easily statically analysed - this leads to plenty of problems such as no way for accessibility tools to determine which dialog that button will open.

@Malvoz

This comment has been minimized.

Copy link

Malvoz commented May 15, 2018

Could we have a toggle attribute? The toggle attribute could specify 2 states to toggle between.

<button type="toggle" toggle="inert|open" for="content">
  Wow, a toggle!
</button>

<div id="content" inert>
  ...
</div>

Dialog

For things like dialogs however, we could specify only 1 value for the toggle attribute to open it and another within the dialog to close it.

State: Hidden

<button type="toggle" toggle="open" for="dialog">Open dialog</button>

<dialog id="dialog" hidden>
  <!-- Natively accessible content -->
  <button type="toggle" toggle="hidden" for="dialog">
    Close dialog
  </button>
</dialog>

Would be equivalent of:

<button class="js-button-open" aria-expanded="false" aria-controls="dialog">Open dialog</button>

<dialog id="dialog" hidden>
  <!-- Let's hope the author cares about accessibility so everyone can access this content -->
  <button class="js-button-close" aria-expanded="true" aria-controls="dialog">
    Close dialog
  </button>
</dialog>

State: Open

<button type="toggle" toggle="open" for="dialog">Open dialog</button>

<dialog id="content" open>
  <!-- Natively accessible content -->
  <button type="toggle" toggle="hidden" for="dialog">
    Close dialog
  </button>
</dialog>

Would be equivalent of:

<button class="js-button-open" aria-expanded="true" aria-controls="dialog">Open dialog</button>

<dialog id="content" open>
  <!-- Let's hope the author cares about accessibility so everyone can access this content -->
  <button class="js-button-close" aria-expanded="true" aria-controls="dialog">
    Close dialog
  </button>
</dialog>
@muan

This comment has been minimized.

Copy link

muan commented Sep 6, 2018

FWIW, we ended up creating <details-dialog>. Which as the name suggests, is a dialog dependent on details. It is now used across github.com. This was prompted by two reasons:

  1. Needing a way for dialog to be opened without JavaScript as Keith mentioned
  2. Current state of (the lack of) browser support for <dialog>

It does still need JavaScript to be fully accessible, but it is interactive without. Having a native way to achieve the stacking context would definitely be much preferred, whatever it end up being.

@Link2Twenty

This comment has been minimized.

Copy link

Link2Twenty commented Jan 3, 2019

@Malvoz a toggle would be helpful but I think it's also worth being able to choose the state you're aiming for.

I think it's worth noting the <dialog> actually has 3 states.

  • open
  • openModal
  • close

though you could argue modal should be an attribute of the dialog and not a method of opening it.

@Link2Twenty

This comment has been minimized.

Copy link

Link2Twenty commented Jan 3, 2019

Currently, I do something like this

<button data-for-dialog="testDialog" open>Open dialog</button>
<dialog id="testDialog">
  <h1>An example of a native Dialog element</h1>
  <p>This is a dialog box and, believe it or not, it's built into HTML, sure we needed some javascript to open it but hey, it's a start.</p>
  <button data-for-dialog="testDialog" close>Close dialog</button>
</dialog>

and then have some JS like so

const dialogTriggers = document.querySelectorAll(`[data-for-dialog]`);

for (let trigger of dialogTriggers) {
  const dialog = document.getElementById(trigger.dataset.forDialog);
  trigger.addEventListener('click', () => {
    trigger.hasAttribute('open') && dialog.showModal();
    trigger.hasAttribute('close') && dialog.close();
  });
}

I think it would be helpful to be able to do something like this and have it work.

<button for-dialog="testDialog" open>Open dialog</button>
<dialog modal id="testDialog">
  <h1>An example of a native Dialog element</h1>
  <p>This is a dialog box and, believe it or not, it's built into HTML, sure we needed some javascript to open it but hey, it's a start.</p>
  <button for-dialog="testDialog" close>Close dialog</button>
</dialog>

Where you have the desired state is an atribute of your controller, or it toggles if nothing if present.
And where the dialog is a modal or not depending on an attribute on the dialog not how it's opened.

@atk

This comment has been minimized.

Copy link

atk commented Jan 4, 2019

I would propose the following addition to the standard: an opens, opensModal and closes attribute that can be added to any HTML element and takes the id of an element to add to or remove from the open/openModal attribute; when both an opening and close attribute are set on the same element, it will perform as a toggle switch.

This will be useful for both existing (details/summary, dialog) as well as future interactive elements that can be opened/closed. A polyfill will also be pretty simple:

if ('opens' in document.createElement('button')) {
    document.addEventListener('click', (ev) => {
        let target = ev.target;
        while (target) {
            if (!target.getAttribute) {
                continue;
            }
            const targetCloses = target.getAttribute('closes');
            const targetOpens = target.getAttribute('opens');
            const targetOpensModal = target.getAttribute('opensModal');
            const targetOpensAny = targetOpens || targetOpensModal;
            const attribute = targetOpensModal ? 'openModal' : 'open';
            if (targetOpensAny && targetOpensAny === targetCloses) {
                const toggle = document.getElementById(targetOpensAny);
                if (toggle.hasAttribute(attribute)) {
                    toggle.removeAttribute(attribute);
                } else {
                    toggle.setAttribute(attribute, true);
                }
            } else {
                if (targetOpensAny) {
                    const open = document.getElementById(targetOpensAny);
                    open.setAttribute(attribute, true);
                }
                if (targetCloses) {
                    const close = document.getElementById(targetCloses);
                    close.removeAttribute('open');
                    close.removeAttribute('openModal')
                }
            }
            target = target.parentElement;
        }
    });
}
@domenic

This comment has been minimized.

Copy link
Member

domenic commented Jan 4, 2019

I appreciate all these proposals; however, I think it's more likely that we'll end up removing the dialog element entirely, as it only has a single implementer and is thus retrospectively failing to meet the criteria of https://whatwg.org/working-mode#additions. Given this, proposals to expand an already-failing feature are unlikely to get much engagement...

@Link2Twenty

This comment has been minimized.

Copy link

Link2Twenty commented Jan 4, 2019

I believe Firefox has the feature behind a flag but were waiting to see how inert progressed before going live.

@domenic

This comment has been minimized.

Copy link
Member

domenic commented Jan 4, 2019

That does't match my understanding, but be that as it may, stalled implementations don't really help a feature make progress either.

@BenLeggiero

This comment has been minimized.

Copy link

BenLeggiero commented Jan 4, 2019

I've had success implementing much of what I need dialog to be by just using CSS, so I don't see much reason to consider this worth abandoning.

@atk

This comment has been minimized.

Copy link

atk commented Jan 22, 2019

Implementing this in CSS is possible, but doing so in an accessible way is really difficult to get right. So a semantic element making this easier would be an improvement over the current state.

While I agree that the proposal for dialog is lacking, the idea of having a semantic element for notifications, modals, etc. should not be dismissed easily.

@kshep92

This comment has been minimized.

Copy link

kshep92 commented Jan 29, 2019

I honestly don't understand what's the delay in implementing this. I have hardly worked on a project where I didn't need to create a dialog and resorted to custom JS/CSS. A dialog with custom HTML content should be part of the spec and should have been part of the spec since 2013.

@domenic

This comment has been minimized.

Copy link
Member

domenic commented Jan 29, 2019

A dialog with HTML content is indeed part of the spec. Putting things in the spec however does not magically compell browsers to implement it. Only Chrome has implemented it so far, and other browsers have shown no movement toward doing so in some time. Your exasperation is probably better directed toward their bug trackers, instead of toward the bug tracker of a specification that you seem to have not read.

@Malvoz

This comment has been minimized.

Copy link

Malvoz commented Mar 1, 2019

FYI; there has been some movement from Firefox in implementing <dialog> quite recently:
https://bugzilla.mozilla.org/show_bug.cgi?id=840640
https://bugzilla.mozilla.org/show_bug.cgi?id=1522094

@domenic

This comment has been minimized.

Copy link
Member

domenic commented Mar 1, 2019

I think you may be over-optimistic there. The last time any code related to dialog landed was a month ago, in which someone added a pref to enable the incomplete implementation, but it was then immediately backed out by bots. The last time someone actually landed implementation code was 2016-12-11, if I am reading correctly. This is not the sort of implementation interest that marks a sustainable feature :(.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.