@qnc/qnc_dialog
v1.0.2
Published
Custom <dialog> wrapper which includes positioning, animation, and auto-closing enhancements.
Readme
Events
We dispatch the following custom events ({bubbles: true, cancelable: false})
qnc-dialog-openingqnc-dialog-openedqnc-dialog-closingqnc-dialog-closed
Note that qnc-dialog-closed MAY be fired without qnc-dialog-closing firing (if the user finds a way to dismiss our dialog with calling close() on us). If you need to attach important "cleanup actions", do so on qnc-dialog-closed rather than qnc-dialog-closing.
We also dispatch qnc-dialog-close-requested ({bubbles: true, cancelable: true}). We dispatch this when the user hits escape or clicks off of the dialog. The default action is to close the dialog. Call preventDefault() if you don't want this (eg. if the dialog contains a complex form, and you don't want user to loose state). If you call preventDefault(), you SHOULD take some action to indicate to the user why the dialog was not closed and what they must do to proceed.
Styling
REQUIRED style, to prevent FOUC
qnc-dialog:not(:defined) {
display: none;
}Visual appearance
You likely want to set:
- background-color
- padding
- border
- box-shadow
- --backdrop-background
- --backdrop-filter
Animation
- animation-timing-function (impacts both the dialog and the backdrop)
- animation-duration (impacts both the dialog and the backdrop)
- --closed-transform
- impacts only the dialog
- accepts either
- an empty string
- valid "transform function" (eg.
translate(12px, 50%)) - a space-separated list of transform functions (eg.
translate(12px, 50%) rotate(0.5turn))
- ie. accepts same thing as
transformgenerally accepts, except MUST NOT BE a keyword/global value (none/inherit/initial/etc) - when calling showNextTo/showAt, this will be APPENDED to any transforms we set in order to position the dialog appropriately
Positioning
The element has position: fixed.
When calling show() you should have top and/or bottom, plus left and/or right defined.
When calling showAt, you need not define anything to determine position.
When calling showNextTo(), you likely want to set:
- --smart-margin: INTEGER;
- --horizontal-preferences: [space separate list of ALIGNMENTS]
- --vertical-preferences: [space separate list of ALIGNMENTS]
These are passed to
@qnc/smart_position, and have the same meaning as defined there.
ALIGNMENT = before|start|center|end|after
- before: pin trailing edge of element to leading edge of target
- start: pin leading edges
- center: pin leading edges, then transform element "backward" by half its size
- end: pin trailing edges
- after: pin leading edge of element to trailing edge of target
Size
When calling show(), we leave size completely unset. When calling showNextTo/showAt we set MAX dimensions.
--close-on-mouse-leave
'true' or 'false', default is 'false' When true, we automatically close the dialog once the mouse enters and then leaves the dialog.
Close on escape
We close the top-most dialog when the escape key is hit. We currently provide no means to opt-out. Browsers automatically close dialog elements when escape is hit. We override the default behaviour so that our exit animation runs before the dialog closes.
TODO: test and document "qnc-dialog-close-requested" behaviour.
DOM Placement
Shouldn't matter.
Nesting/multiple open dialogs
Not explicitly supported, but MIGHT work. Spec seems loose here. We need to test in different browsers, see if behaviour is consistent, and make sure our decisions align with browser decisions (particularly, regarding which dialog is top-most)
Scroll-through blocking
We set "overflow: auto" and "overscroll-behavior: none" on the dialog, which is enough to prevent scroll-through in ONLY the following scenario:
- the dialog actually overflows
- your cursor is over top of the dialog when you scroll
- your cursor is NOT over top of a scrollable descendant when you scroll (unless that descendant also has "overscroll-behavior: none")
We've yet to find an approach that cleanly blocks scroll-through in all scenarios. If you want to fully block scroll-through, we recommend ensuring that the <body> and <html> elements have no scroll bar (while dialogs are open, anyway). You're on your own for achieving this.
TO TEST
- can we really set size/position/border by styles of
- browser support for display: contents;, what happens when not supported
- nesting (check against spec, too; seems that multiple open modal dialogs are not explicitly allowed)
- use of --closed-transform AND transform via smart_position (showNextTo with one preference being "center")
Unbreakable guarantee
We promise never to release breaking changes (ie. a new major version). If your project uses smart_position, you should add it as a PEER dependency. Since we'll never release a new major version, this cannot lead to dependency conflicts. Any package which relies on this should be able to safely use the latest version.
If we want to release changes which would not be backward compatible, we'll release a new/different package instead (and post a notice here, recommending the new package).
