-
Notifications
You must be signed in to change notification settings - Fork 43
Description
Issues and Motivations:
-
It is very useful to 'pop' items out of overflow to the top of the visual stack but current top-layer / popover mechanics invite global-scope-pollution-like problems that will continue to manifest as minimal adoption by UI libraries in favor existing limited portal-like solutions plus continued challenges expressing the kinds of bespoke visual stacking that modestly complex web-apps need.
-
Current showModal's behavior presumes user activity is only ever at a 'page' level of granularity, but even modestly complex pages support multiple layers of activity that may each become independently blocked on user input in ways that don't preclude user activity elsewhere on the page. e.g. if a user purchase is blocked by missing details, and the system presents a form to collect this information via a modal popover, the user should still be able to interact with an already-open chat popover to ask questions about the process.
-
The ability to specify non-top-layer, non-document presentation buckets presents compelling opportunities across numerous use cases including element image capture, PWA chrome, XR/VR, control over view-transition appearance, etc.
Additional elaboration follows the proposal.
Overview:
This proposal proposes a generic form of top-layer, presentation-layer, and related mechanics, that would allow authors to express bespoke visual presentation and activity buckets outside of the normal document or within elements. The proposal is crafted to avoid changes to existing top-layer, popover, and modal behaviors.
A core premise is that developers requesting the ability to keep things 'on top' of top-layer content, actually need a way of expressing presentation layering below top-layer, so long as it is still above the document, i.e. if a dev knows enough to say 'toasts of kind X always need to appear on top of modals of kind Y' then they know enough to build layering buckets behind top-layer, they just need a mechanism for it.
A secondary premise is that the need for modality is not page-level buy user-activity-level and that there are frequently multiple layers of user activity in a page, such that modal mechanisms would be useful to have anywhere in the document.
A final premise is that current top-layer behavior is good and valuable as is, but is very similar to !important in both utility and foot-guns, and would benefit from a similar alternative/solution. Though !important provides a useful escape hatch it is poorly suited for regular use because it only allows authors to express two priorities, when they need multiple, and so the defect standard was to avoid !important in favor of a single reference frame where you could create arbitrary levels of ordering. Top-layer is the same -- an author can have document priority or top-layer priority but in reality needs arbitrary levels of priority. A likely outcome may be a best practice of avoiding top-layer in favor of approaches that allow for arbitrary priorities in the same reference frame (i.e. portals). But a solution now exists the these !important problems -- @layer. @layer allows authors to express the levels of priority that they need. The same mechanisms should similarly address the similar limitations of top-layer.
Presentation-Layers
Elements with a presentation-layer:<name> rule would be displayed in an ad-hoc container behind top-layer but above the document.
The reserved name Top would refer to what is now top-layer and be the default value for popovers such that current popover/top-layer behavior would persist as is.
The ordering of named presentation layers would be controllable via an at-rule @presentation-layer <name>,.... Occurrences of Top in the declaration would be ignored.
e.g.
@presentation-layer toasts, modals, emphasis;...
button.BookStay{
anchor-name:stay-button;
.focus-ring{
presentation-layer:emphasis;
anchor-name:stay-button;
anchor-position:center;
inset:-8px;
border:1px solid blue;
}
}
.Confirmation[popover]{
presentation-layer:modals;
}
@media (min-width:5000px){
.Confirmation[popover]{
presentation-layer:Document;
}
}
.HostMessageToast{
presentation-layer:toasts;
CustomSelect CustomDropdown{
presentation-layer:Top;
}
}Elements with a presentation-layer name not included in an @presentation-layer declaration would be inserted into a new named presentation-layer just below Top , in the order encountered in the document.
The names Bottom and Document would also be reserved for a 'back-most' presentation-layer, behind the document, and for default / normal display in the document, respectively. Document could be used in the @-rule to specify presentation-layers below Document. Bottom is ignored in the @-rule.
eg.
@presentation-layer modals, Document, ambience;
.ReservationConfirmation[popover]{
presentation-layer:modals;
.destination-preview{
presentation-layer:ambience;
position:fixed;
inset:0;
background-image: url(skyline.jpg);
filter:blur(72px);
}
}container : presentation
presentation-layer behavior would be mimicked at an element-container level via container-type: presentation; presentation-layers: <name>... in order to allow elements to 'bust out' of their container's overflow and into an author-controlled level rather than all the way out of the document.
For example, in the a scrollable article below, our button focus ring would sit atop other content but still be cropped to the scrolling container.
eg.
.ScrollableArticle{
container: presentation;
presentation-layers:emphasis;
overflow:scroll;
...
button .focus-ring{
presentation-layer:emphasis;
}
}Similar to @presentation-layer, the reserved names Top, Document, and Bottom would be ignored in a presentation-layers rule, and as such, elements will never 'capture' popovers destined for Top but could capture popover items an author has opted-into being capturable.
Additional names like Container-Top,Container,Container-Bottom might be reserved for referencing a relative equivalent of Top, normal, and Bottom in the nearest container, which may be the root document's Top, Document, Bottom if the element is in no other container.
It may be extremely useful for containers to be able to remap presentation layers such that, e.g. a component or library would not need to insist on using the global top-layer.
For presentation containers the container box would determine the bounds of the presentation-layer.
Nesting
With the exception of Top and Bottom, @presentation-layer declarations could be nested.
/* Ok */
@presentation-layer activity{
@presentation-layer emphasis;
}
/* No effect; 'Top' ignored */
@presentation-layer Top{
@presentation-layer tipy-top
}
.PeekView{
container: activity
/** No effect; 'Top' ignored */
presentation-layers: Top, emphasis;
}
/** Equivalent to document{container:presentation; presentation-layers:high-up;} */
@presentation-layer Document{
@presentation-layer high-up
}Nesting with element / container-based presentation-layers may need to rely on nested element-containers.
Ordering within presentation layers
The ordering of elements within a presentation-layer:<name> rule follows document order with the following exception: elements for which showModal(), showPopover(), togglePopover() etc. has been invoked always display on top of elements that are only in the same presentation-layer by virtue of their presentation-layer rule.
The order of such 'imperatively promoted elements' amongst themselves should follow the current behaviors for top layer. In this way current popover / top-layer behavior persists while additional elements may be promoted into the top layer through, e.g. media queries, as necessary. (If an author decides they need imperatively promoted elements below rule-promoted elements, they'll likely benefit from organizing around their own named presentation-layers.)
Generally though, authors should not need to understand the nuances of these ordering behaviors to achieve their ordering needs, as they can express their ordering needs via presentation-layers.
Modality
Items displayed in a presentation layer via showModal() would make inert any lower element in the same presentation-layer and any element in a lower presentation-layer.
The modal-ness of modal elements in element-containers would apply to that element-containers presentation-layers.
Authors who need some category of alerts to be assuredly interactive with respect to some category of modals without worrying about order of showModal() and showPopover() invocation could just utilize separate presentation layers.
Motivation (elaboration)
-
Managing alert/popover priorities:
- ex. A CRUD-action-completed alert should not appear on top of an already displayed non-modal you-will-be-logged-out-soon alert; A tool tip for an item in the partially obscured CRUD alert may or may not need to show on top of both.
- ex. During a drag-and-drop operation using a bespoke drag-and-drop implementation, a drag-preview should always show on top of any items that might normally appear above all else.
- ex. Action in a popover that transforms data in the background might be well accompanied by a 'change' indicator that sits above the affected content but below the popover controls.
-
Switching between in-flow and 'on-top' presentation contingent on space / screen size while maintaining desired ordering.
-
Separate 'where' in a stack an element is displayed (e.g. top-layer) from how (e.g.
display:...) / ensure an element transitioning to or fromdisplay:nonestays above the document. -
Improved ergonomics for organizing complex UIs with persistent divisions between e.g. artboard, selection-indicators, tool pallets, etc.
-
Styling visual focus/emphasis/decoration to be outside a clipped element, visually above its neighboring elements, and potentially within a further removed cropped ancestor.
-
Ability to author components / libraries that don't insist on using a global territory (top layer) but are built in such a way that consumers can permit them access to spaces they themselves are responsible for.
Additional Opportunities:
- Improved ability to isolate elements for screen-capture.
- Possible base for semantics for referring to future specialty presentation destinations, even 'beyond-top-layer' ones, e.g. a window title bar in a PWA, custom cursor, custom drag preview, scroll bars, off-screen, etc.
- Possible mechanism for granular control over view-transition presentation / layering.
- User-controlled ordering of alternatively-rendered content via providing the renderer a presentation-layer name?
- Semantics for referencing presentation layers in front or behind of the client window??? (In only the most secure contexts of course 😉.)