Merge pull request #73 from ing-bank/chore/overlayOverview
chore(overlays): outline doc for all overlay occurrences
This commit is contained in:
commit
aa30efcf75
5 changed files with 522 additions and 30 deletions
|
|
@ -5,16 +5,17 @@
|
||||||
Supports different types of overlays like dialogs, toasts, tooltips, dropdown, etc...
|
Supports different types of overlays like dialogs, toasts, tooltips, dropdown, etc...
|
||||||
Manages their position on the screen relative to other elements, including other overlays.
|
Manages their position on the screen relative to other elements, including other overlays.
|
||||||
|
|
||||||
## Overlays manager
|
## Features
|
||||||
|
- [**Overlays Manager**](./docs/OverlaysManager.md), a global repository keeping track of all different types of overlays.
|
||||||
This is a global singleton needed to manage positions of multiple dialogs next to each other on the entire page.
|
- [**Overlays Occurrences**](./docs/OverlayOccurrences.md), outline of all possible occurrences of overlays. Divided into two main types:
|
||||||
It does the job automatically, but you need to add every newly created overlay to it using the code provided below:
|
- [**Global Overlay Controller**](./docs/GlobalOverlayController.md), controller for overlays relative to the viewport.
|
||||||
|
- [**Local Overlay Controller**](./docs/LocalOverlayController.md), controller for overlays positioned next to invokers they are related to.
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
```sh
|
```sh
|
||||||
npm i --save @lion/ajax
|
npm i --save @lion/overlays
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
@ -29,28 +30,3 @@ const myCtrl = overlays.add(
|
||||||
// name OverlayTypeController is for illustration purpose only
|
// name OverlayTypeController is for illustration purpose only
|
||||||
// please read below about existing classes for different types of overlays
|
// please read below about existing classes for different types of overlays
|
||||||
```
|
```
|
||||||
|
|
||||||
## GlobalOverlayController
|
|
||||||
|
|
||||||
This is a base class for different global overlays (e.g. a dialog) - the ones positioned relatively to the viewport.
|
|
||||||
You should not use this controller directly unless you want to create a unique type of global overlays which is not supported out of the box.
|
|
||||||
|
|
||||||
All supported types of global overlays are described below.
|
|
||||||
|
|
||||||
### ModalDialogController
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ModalDialogController } from '@lion/overlays';
|
|
||||||
```
|
|
||||||
|
|
||||||
This is an extension of GlobalOverlayController configured to create accessible modal dialogs.
|
|
||||||
|
|
||||||
## LocalOverlayController
|
|
||||||
|
|
||||||
This is a base class for different local overlays (e.g. a tooltip) - the ones positioned next to invokers they are related to.
|
|
||||||
You should not use this controller directly unless you want to create a unique type of local overlays which is not supported out of the box.
|
|
||||||
|
|
||||||
All supported types of local overlays are described below.
|
|
||||||
|
|
||||||
This is currently WIP.
|
|
||||||
Stay tuned for updates on new types of overlays.
|
|
||||||
|
|
|
||||||
31
packages/overlays/docs/GlobalOverlayController.md
Normal file
31
packages/overlays/docs/GlobalOverlayController.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# GlobalOverlayController
|
||||||
|
|
||||||
|
This is a base class for different global overlays (e.g. a dialog, see [Overlay Occurrences](./OverlayOccurrences.md) - the ones positioned relatively to the viewport.
|
||||||
|
You should not use this controller directly unless you want to create a unique type of global overlays which is not supported out of the box.
|
||||||
|
|
||||||
|
All supported types of global overlays are described below.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
```sh
|
||||||
|
npm i --save @lion/overlays
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```js
|
||||||
|
import { overlays } from '@lion/overlays';
|
||||||
|
|
||||||
|
const myCtrl = overlays.add(
|
||||||
|
new GlobalOverlayController({
|
||||||
|
/* options */
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### ModalDialogController
|
||||||
|
A specific extension of GlobalOverlayController configured to create accessible modal dialogs.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { ModalDialogController } from '@lion/overlays';
|
||||||
|
```
|
||||||
28
packages/overlays/docs/LocalOverlayController.md
Normal file
28
packages/overlays/docs/LocalOverlayController.md
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# LocalOverlayController
|
||||||
|
|
||||||
|
This is a base class for different local overlays (e.g. a [tooltip](../../tooltip/), see [Overlay System Implementation](./OverlaySystemImplementation.md) - the ones positioned next to invokers they are related to.
|
||||||
|
You should not use this controller directly unless you want to create a unique type of local overlays which is not supported out of the box.
|
||||||
|
|
||||||
|
All supported types of local overlays are described below.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
```sh
|
||||||
|
npm i --save @lion/overlays
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```js
|
||||||
|
import { overlays } from '@lion/overlays';
|
||||||
|
|
||||||
|
const myCtrl = overlays.add(
|
||||||
|
new LocalOverlayController({
|
||||||
|
/* options */
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
This is currently WIP.
|
||||||
|
Stay tuned for updates on new types of overlays.
|
||||||
240
packages/overlays/docs/OverlaySystemImplementation.md
Normal file
240
packages/overlays/docs/OverlaySystemImplementation.md
Normal file
|
|
@ -0,0 +1,240 @@
|
||||||
|
# Overlay System: Implementation
|
||||||
|
This document provides an outline of all possible occurrences of overlays found in applications in
|
||||||
|
general and thus provided by Lion.
|
||||||
|
For all concepts referred to in this document, please read [Overlay System Scope](./OverlaySystemScope.md).
|
||||||
|
|
||||||
|
## Local and global overlay controllers
|
||||||
|
Currently, we have a global and a local overlay controller, as two separate entities.
|
||||||
|
Based on provided config, they handle all positioning logic, accessibility and interaction patterns.
|
||||||
|
All of their configuration options will be described below as part of the _Responsive overlay_ section.
|
||||||
|
|
||||||
|
### Connection points and placement contexts
|
||||||
|
It's currently not clear where the border between global and local overlays lie. They seem to be
|
||||||
|
separated based on their 'dom connection point' (body vs 'page cursor'(usually invoker sibling)).
|
||||||
|
However, there is no required relationship here: we can create a modal dialog from
|
||||||
|
local context('page cursor') as well.
|
||||||
|
|
||||||
|
Only, we would have a few concerns when creating global overlays from a local connection point:
|
||||||
|
- Accessibility will be harder to implement. When wai-aria 1.0 needs to be supported, all siblings
|
||||||
|
need to have aria-hidden="true" and all parents role="presentation". Not always straightforward
|
||||||
|
in shadow dom. If we only need to support wai-aria 1.1, we could use aria-modal="true" on the
|
||||||
|
element with role="dialog". (we basically need to test our supported browsers and screen readers
|
||||||
|
for compatibility with aria-modal).
|
||||||
|
- Stacking context need to be managed: the whole 'z-index chain' should win (it's a battle between
|
||||||
|
parents in the hierarchy). This would require some complex code to cover all edge cases.
|
||||||
|
- Side effects of parents adding transforms or clipping become a risk. This is hard to detect and
|
||||||
|
'counter'.
|
||||||
|
|
||||||
|
When the dom connection point is 'body', content projection will not work, but a template that
|
||||||
|
can be rendered without being dependent on its context will be required.
|
||||||
|
|
||||||
|
There usually also is a correllation with their relative positioning context: invoker/other
|
||||||
|
relative element for local(tooltip/popover/dropdown) vs. 'window/viewport level' for global
|
||||||
|
(dialog/toast/sheet).
|
||||||
|
|
||||||
|
For responsive overlays (see below for an elaborate explanation), we need to switch from global to
|
||||||
|
local. When we switch the dom connection point, (think of rotating a mobile or tablet), we
|
||||||
|
will loose the current focus, which can be an a11y concern. This can eventually be 'catched' by
|
||||||
|
syncing the activeElement (we would only loose the screenreader active element (for instance,
|
||||||
|
focused cell in table mode))
|
||||||
|
|
||||||
|
For maximum flexibility, it should be up to the developer to decide how overlays should be rendered,
|
||||||
|
per instance of an overlay.
|
||||||
|
|
||||||
|
## Responsive overlay
|
||||||
|
Based on screen size, we might want to switch the appearance of an overlay.
|
||||||
|
For instance: an application menu can be displayed as a dropdown on desktop,
|
||||||
|
but as a bottom sheet on mobile.
|
||||||
|
Similarly, a dialog can be displayed as a popover on desktop, but as a (global) dialog on mobile.
|
||||||
|
|
||||||
|
To implement such a flexible overlay, we need an 'umbrella' layer that allows for switching between
|
||||||
|
different configuration options, also between the connection point in dom (global and local).
|
||||||
|
|
||||||
|
Luckily, interfaces of Global and OverlayControllers are very similar.
|
||||||
|
Therefore we can make a wrapping ResponsiveOverlayController.
|
||||||
|
|
||||||
|
### Configuration options for local and global overlays
|
||||||
|
|
||||||
|
In total, we should end up with configuration options as depicted below, for all possible overlays.
|
||||||
|
All boolean flags default to 'false'.
|
||||||
|
Some options are mutually exclusive, in which case their dependent options and requirement will be
|
||||||
|
mentioned.
|
||||||
|
Note: a more generic and precise term for all mentionings of `invoker` below would actually be
|
||||||
|
`relative positioning element`.
|
||||||
|
```
|
||||||
|
- {Element} elementToFocusAfterHide - the element that should be called `.focus()` on after dialog closes
|
||||||
|
- {Boolean} hasBackdrop - whether it should have a backdrop (currently exclusive to globalOverlayController)
|
||||||
|
- {Boolean} isBlocking - hides other overlays when mutiple are opened (currently exclusive to globalOverlayController)
|
||||||
|
- {Boolean} preventsScroll - prevents scrolling body content when overlay opened (currently exclusive to globalOverlayController)
|
||||||
|
- {Boolean} trapsKeyboardFocus - rotates tab, implicitly set when 'isModal'
|
||||||
|
- {Boolean} hidesOnEsc - hides the overlay when pressing [esc]
|
||||||
|
- {Boolean} hidesOnOutsideClick - hides the overlay when clicking next to it, exluding invoker. (currently exclusive to localOverlayController)
|
||||||
|
- {String} cssPosition - 'absolute' or 'fixed'. TODO: choose name that cannot be mistaken for placement like cssPosition or positioningTechnique: https://github.com/ing-bank/lion/pull/61
|
||||||
|
- {TemplateResult} contentTemplate
|
||||||
|
- {TemplateResult} invokerTemplate (currently exclusive to LocalOverlayController)
|
||||||
|
- {Element} invokerNode (currently exclusive to LocalOverlayController)
|
||||||
|
- {Element} contentNode (currently exclusive to LocalOverlayController)
|
||||||
|
```
|
||||||
|
|
||||||
|
These options are suggested to be added to the current ones:
|
||||||
|
```
|
||||||
|
- {Boolean} isModal - sets aria-modal and/or aria-hidden="true" on siblings
|
||||||
|
- {Boolean} isGlobal - determines the connection point in DOM (body vs handled by user) TODO: rename to renderToBody?
|
||||||
|
- {Boolean} isTooltip - has a totally different interaction - and accessibility pattern from all
|
||||||
|
other overlays, so needed for internals.
|
||||||
|
- {Boolean} handlesUserInteraction - sets toggle on click, or hover when `isTooltip`
|
||||||
|
- {Boolean} handlesAccessibility -
|
||||||
|
- For non `isTooltip`:
|
||||||
|
- sets aria-expanded="true/false" and aria-haspopup="true" on invokerNode
|
||||||
|
- sets aria-controls on invokerNode
|
||||||
|
- returns focus to invokerNode on hide
|
||||||
|
- sets focus to overlay content(?)
|
||||||
|
- For `isTooltip`:
|
||||||
|
- sets role="tooltip" and aria-labelledby/aria-describedby on the content
|
||||||
|
- {Object} placementConfig
|
||||||
|
- {String} placement - vertical/horizontal position to be supplied to `managePosition`. See https://github.com/ing-bank/lion/pull/61 for current api. Consists of a primary part (where the overlay is located relative from invoker) and secondary alignnment part (how the overlay 'snaps' to the perpendicular boundary of the invoker), separated via '-'.
|
||||||
|
- primary : 'bottom' | 'top' | 'left' | 'right' | 'over' (this means the overlay will be positioned on top of the invoker. Think for instance of a select dropdown that opens a selected option on top of the invoker (default behavior of `<select>` on iOS))
|
||||||
|
- secondary : 'start' | 'end' | 'fill' (occupies width of invoker) | 'middle' (implicit option that will be choosen by default when none of the previous are specified)
|
||||||
|
- all other configuration as described by [Popper.js](https://popper.js.org/)
|
||||||
|
```
|
||||||
|
|
||||||
|
What we should think about more properly is a global placement option (positioned relative to window instead of invoker)
|
||||||
|
```
|
||||||
|
// TODO: namings very much under construction (we should also reconsider 'placement' names, see: https://github.com/ing-bank/lion/pull/61)
|
||||||
|
// Something like the drawing Joren made: https://github.com/ing-bank/lion/issues/36#issuecomment-491855381
|
||||||
|
- {String} viewportPlacement - consists of a vertical alignment part and an horizontal alignment part,
|
||||||
|
separated via '-'
|
||||||
|
- vertical align : 'center' | 'bottom' | 'top' | 'left' | 'right' | 'fullheight'
|
||||||
|
- horizontal align: 'middle' | 'start' | 'end' | 'fullwidth'
|
||||||
|
Examples: 'center-middle' (dialog, alertdialog), 'top-fullwidth' (top sheet)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Controllers/behaviors
|
||||||
|
Controllers/behaviors provide preconfigured configuration objects for the global/local
|
||||||
|
overlay controllers.
|
||||||
|
They provide an imperative and very flexible api for creating overlays and should be used by
|
||||||
|
Subclassers, inside webcomponents.
|
||||||
|
|
||||||
|
#### Dialog
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
isGlobal: true,
|
||||||
|
isModal: true,
|
||||||
|
hasBackdrop: true,
|
||||||
|
preventsScroll: true,
|
||||||
|
trapsKeyboardFocus: true,
|
||||||
|
hidesOnEsc: true,
|
||||||
|
handlesUserInteraction: true,
|
||||||
|
handlesAccessibility: true,
|
||||||
|
viewportPlacement: 'center-middle',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Tooltip
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
isTooltip: true,
|
||||||
|
handlesUserInteraction: true,
|
||||||
|
handlesAccessibility: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Popover
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
handlesUserInteraction: true,
|
||||||
|
handlesAccessibility: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### Dropdown
|
||||||
|
It will be quite common to override placement to 'bottom-fullwidth'.
|
||||||
|
Also, it would be quite common to add a pointerNode.
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
placement: 'bottom',
|
||||||
|
handlesUserInteraction: true,
|
||||||
|
handlesAccessibility: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### Toast
|
||||||
|
TODO:
|
||||||
|
- add an option for role="alertdialog" ?
|
||||||
|
- add an option for a 'hide timer' and belonging a11y features for this
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
...Dialog,
|
||||||
|
viewportPlacement: 'top-right', (?)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### Sheet (bottom, top, left, right)
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
...Dialog,
|
||||||
|
viewportPlacement: '{top|bottom|left|right}-fullwidth', (?)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### Select
|
||||||
|
No need for a config, will probably invoke ResponsiveOverlayCtrl and switches
|
||||||
|
config based on media query from Dropdown to BottomSheet/CenteredDialog
|
||||||
|
|
||||||
|
#### Combobox/autocomplete
|
||||||
|
No need for a config, will probably invoke ResponsiveOverlayCtrl and switches
|
||||||
|
config based on media query from Dropdown to BottomSheet/CenteredDialog
|
||||||
|
|
||||||
|
#### Application menu
|
||||||
|
No need for cfg, will probably invoke ResponsiveOverlayCtrl and switches
|
||||||
|
config based on media query from Dropdown to BottomSheet/CenteredDialog
|
||||||
|
|
||||||
|
|
||||||
|
## Web components
|
||||||
|
Web components provide a declaritive, developer friendly interface with a prewconfigured styling
|
||||||
|
that fits the Design System and makes it really easy for Application Developers to build
|
||||||
|
user interfaces.
|
||||||
|
Web components should use
|
||||||
|
The ground layers for the webcomponents in Lion are the following:
|
||||||
|
|
||||||
|
#### Dialog
|
||||||
|
|
||||||
|
Imperative might be better here? We can add a web component later if needed.
|
||||||
|
|
||||||
|
#### Tooltip
|
||||||
|
```html
|
||||||
|
<lion-tooltip>
|
||||||
|
<button slot="invoker">hover/focus</button>
|
||||||
|
<div slot="content">This will be shown</div>
|
||||||
|
</lion-tooltip>
|
||||||
|
```
|
||||||
|
#### Popover
|
||||||
|
```html
|
||||||
|
<lion-popover>
|
||||||
|
<button slot="invoker">click/space/enter</button>
|
||||||
|
<div slot="content">This will be shown</div>
|
||||||
|
</lion-popover>
|
||||||
|
```
|
||||||
|
#### Dropdown
|
||||||
|
Like the name suggests, the default placement will be button
|
||||||
|
```html
|
||||||
|
<lion-dropdown>
|
||||||
|
<button slot="invoker">click/space/enter</button>
|
||||||
|
<ul slot="content">
|
||||||
|
<li>This</li>
|
||||||
|
<li>will be</li>
|
||||||
|
<li>shown</li>
|
||||||
|
</ul>
|
||||||
|
</lion-dropdown>
|
||||||
|
```
|
||||||
|
#### Toast
|
||||||
|
|
||||||
|
Imperative might be better here?
|
||||||
|
#### Sheet (bottom, top, left, right)
|
||||||
|
|
||||||
|
Imperative might be better here?
|
||||||
|
|
||||||
|
|
||||||
|
### Web components implementing generic overlays
|
||||||
|
|
||||||
|
#### Select, Combobox/autocomplete, Application menu
|
||||||
|
|
||||||
|
Those will be separate web components with a lot of form and a11y logic that will be described
|
||||||
|
in detail in different sections.
|
||||||
|
They will imoplement the Overlay configuration as described above under 'Controllers/behaviors'.
|
||||||
217
packages/overlays/docs/OverlaySystemScope.md
Normal file
217
packages/overlays/docs/OverlaySystemScope.md
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
# Overlay System: Scope
|
||||||
|
|
||||||
|
The goal of this document is to specify the goal and duties of the overlay system, mainly by
|
||||||
|
identifying all different appearances and types of overlays.
|
||||||
|
|
||||||
|
## What is an overlay manager?
|
||||||
|
|
||||||
|
An overlay is a visual element that is painted on top of a page, breaking out of the regular
|
||||||
|
document flow.
|
||||||
|
An overlay manager is a global repository keeping track of all different types of overlays.
|
||||||
|
The need for a global housekeeping mainly arises when multiple overlays are opened simultaneously.
|
||||||
|
As opposed to a single overlay, the overlay manager stores knowledge about:
|
||||||
|
- whether the scroll behaviour of the body element can be manipulated
|
||||||
|
- what space is available in the window for drawing new overlays
|
||||||
|
|
||||||
|
The manager is in charge of rendering an overlay to the DOM. Therefore, a developer should be able
|
||||||
|
to control:
|
||||||
|
- It’s ‘physical position’ (where the dialog is attached). This can either be:
|
||||||
|
- globally: at root level of the DOM. This guarantees a total control over its painting, since
|
||||||
|
the stacking context can be controlled from here and interfering parents (that set overflow
|
||||||
|
values or transforms) can’t be apparent. Additionally, making a modal dialog requiring
|
||||||
|
all surroundings to have aria-hidden="true", will be easier when the overlay is attached on
|
||||||
|
body level.
|
||||||
|
- locally: next to the invoking element. This gives advantages for accessibility and
|
||||||
|
(performant) rendering of an overlay next to its invoker on scroll and window resizes
|
||||||
|
- Toggling of the ‘shown’ state of the overlay
|
||||||
|
- Positioning preferences(for instance ‘bottom-left’) and strategies (ordered fallback preferences)
|
||||||
|
|
||||||
|
Presentation/styling of the overlay is out of the scope of the manager, except for its positioning
|
||||||
|
in its context.
|
||||||
|
|
||||||
|
Accessibility is usually dependent on the type of overlay, its specific implementation and its
|
||||||
|
browser/screen reader support (aria 1.0 vs 1.1). We strive for an optimum here by supporting
|
||||||
|
1.0 as a bare minimum and add 1.1 enrichments on top.
|
||||||
|
|
||||||
|
For every overlay, the manager has access to the overlay element and the invoker (and possible
|
||||||
|
other elements that are needed for focus delegation as described in
|
||||||
|
https://www.w3.org/TR/wai-aria-practices/#dialog_modal (notes).
|
||||||
|
|
||||||
|
## Defining different types of overlays
|
||||||
|
|
||||||
|
When browsing through the average ui library, one can encounter multiple names for occurrences of
|
||||||
|
overlays. Here is a list of names encountered throughout the years:
|
||||||
|
- dialog
|
||||||
|
- modal
|
||||||
|
- popover
|
||||||
|
- popup
|
||||||
|
- popdown
|
||||||
|
- popper
|
||||||
|
- bubble
|
||||||
|
- balloon
|
||||||
|
- dropdown
|
||||||
|
- dropup
|
||||||
|
- tooltip
|
||||||
|
- layover
|
||||||
|
- overlay
|
||||||
|
- toast
|
||||||
|
- snackbar
|
||||||
|
- sheet (bottom, top, left, right)
|
||||||
|
- etc..
|
||||||
|
|
||||||
|
The problem with most of those terms is their lack of clear definition: what might be considered a
|
||||||
|
tooltip in UI framework A, can be considered a popover in framework B. What can be called a modal
|
||||||
|
in framework C, might actually be just a dialog. Etc etc…
|
||||||
|
|
||||||
|
### Official specifications
|
||||||
|
|
||||||
|
In order to avoid confusion and be as specification compliant as possible, it’s always a good idea
|
||||||
|
to consult the W3C. This website shows a full list with specifications of accessible web widgets:
|
||||||
|
https://www.w3.org/TR/wai-aria-practices/.
|
||||||
|
A great overview of all widget-, structure- and role relations can be found in the ontology diagram
|
||||||
|
below:
|
||||||
|

|
||||||
|
https://www.w3.org/WAI/PF/aria-1.1/rdf_model.svg
|
||||||
|
|
||||||
|
Out of all the overlay names mentioned above, we can only identify the dialog and the tooltip as
|
||||||
|
official roles.
|
||||||
|
Let’s take a closer look at their definitions...
|
||||||
|
|
||||||
|
### Dialog
|
||||||
|
|
||||||
|
The dialog is described as follows by the W3C:
|
||||||
|
> “A dialog is a window overlaid on either the primary window or another dialog window. Windows
|
||||||
|
under a modal dialog are inert. That is, users cannot interact with content outside an active
|
||||||
|
dialog window. Inert content outside an active dialog is typically visually obscured or dimmed so
|
||||||
|
it is difficult to discern, and in some implementations, attempts to interact with the inert
|
||||||
|
content cause the dialog to close.
|
||||||
|
Like non-modal dialogs, modal dialogs contain their tab sequence. That is, Tab and Shift + Tab do
|
||||||
|
not move focus outside the dialog. However, unlike most non-modal dialogs, modal dialogs do not
|
||||||
|
provide means for moving keyboard focus outside the dialog window without closing the dialog.”
|
||||||
|
|
||||||
|
- specification: https://www.w3.org/TR/wai-aria-1.1/#dialog
|
||||||
|
- widget description: https://www.w3.org/TR/wai-aria-practices/#dialog_modal
|
||||||
|
|
||||||
|
### Tooltip
|
||||||
|
|
||||||
|
According to W3C, a tooltip is described by the following:
|
||||||
|
> “A tooltip is a popup that displays information related to an element when the element receives
|
||||||
|
keyboard focus or the mouse hovers over it. It typically appears after a small delay and disappears
|
||||||
|
when Escape is pressed or on mouse out.
|
||||||
|
> Tooltip widgets do not receive focus. A hover that contains focusable elements can be made using
|
||||||
|
a non-modal dialog.”
|
||||||
|
|
||||||
|
- specification: https://www.w3.org/TR/wai-aria-1.1/#tooltip
|
||||||
|
- widget description: https://www.w3.org/TR/wai-aria-practices/#tooltip
|
||||||
|
|
||||||
|
What needs to be mentioned is that the W3C taskforce didn’t reach consensus yet about the above
|
||||||
|
tooltip description. A good alternative resource:
|
||||||
|
https://inclusive-components.design/tooltips-toggletips/
|
||||||
|
|
||||||
|
### Dialog vs tooltip
|
||||||
|
|
||||||
|
Summarizing, the main differences between dialogs and tooltips are:
|
||||||
|
- Dialogs have a modal option, tooltips don’t
|
||||||
|
- Dialogs have interactive content, tooltips don’t
|
||||||
|
- Dialogs are opened via regular buttons (click/space/enter), tooltips act on focus/mouseover
|
||||||
|
|
||||||
|
|
||||||
|
### Other roles and concepts
|
||||||
|
|
||||||
|
Other roles worth mentioning are *alertdialog* (a specific instance of the dialog for system
|
||||||
|
alerts), select (an abstract role), *combobox* and *menu*.
|
||||||
|
|
||||||
|
Also, the W3C document often refers to *popup*. This term is mentioned in the context of *combobox*,
|
||||||
|
*listbox*, *grid*, *tree*, *dialog* and *tooltip*. Therefore, one could say it could be a term
|
||||||
|
|
||||||
|
*aria-haspopup* attribute needs to be mentioned: it can have values ‘menu’, ‘listbox’, ‘grid’,
|
||||||
|
’tree’ and ‘dialog’.
|
||||||
|
|
||||||
|
|
||||||
|
## Common Overlay Components
|
||||||
|
|
||||||
|
In our component library, we want to have the following overlay ‘child’ components:
|
||||||
|
- Dialog
|
||||||
|
- Tooltip
|
||||||
|
- Popover
|
||||||
|
- Dropdown
|
||||||
|
- Toast
|
||||||
|
- Sheet (bottom, top, left, right)
|
||||||
|
- Select
|
||||||
|
- Combobox/autocomplete
|
||||||
|
- Application menu
|
||||||
|
|
||||||
|
### Dialog
|
||||||
|
|
||||||
|
The dialog is pretty much the dialog as described in the W3C spec, having the modal option applied
|
||||||
|
by default.
|
||||||
|
The flexibility in focus delegation (see https://www.w3.org/TR/wai-aria-practices/#dialog_modal
|
||||||
|
notes) is not implemented, however.
|
||||||
|
Addressing these:
|
||||||
|
- The first focusable element in the content: although delegate this focus management to the
|
||||||
|
implementing developer is highly preferred, since this is highly dependent on the moment the dialog
|
||||||
|
content has finished rendering. This is something the overlay manager or dialog widget should not
|
||||||
|
be aware of in order to provide.a clean and reliable component.
|
||||||
|
- The focusable element after a close: by default, this is the invoker. For different behaviour, a
|
||||||
|
reference should be supplied to a more logical element in the particular workflow.
|
||||||
|
|
||||||
|
|
||||||
|
### Tooltip
|
||||||
|
|
||||||
|
The tooltip is always invoked on hover and has no interactive content. See
|
||||||
|
https://inclusive-components.design/tooltips-toggletips/ (the tooltip example, not the toggle tip).
|
||||||
|
|
||||||
|
|
||||||
|
### Popover
|
||||||
|
|
||||||
|
The popover looks like a crossover between the dialog and the tooltip. Popovers are invoked on
|
||||||
|
click. For non interactive content, the https://inclusive-components.design/tooltips-toggletips/
|
||||||
|
toggletip could be applied.
|
||||||
|
Whenever there would be a close button present, the ‘non interactiveness’ wouldn’t apply.
|
||||||
|
|
||||||
|
An alternative implementation: https://whatsock.com/tsg/Coding%20Arena/Popups/Popup%20(Internal%20Content)/demo.htm
|
||||||
|
This looks more like a small dialog, except that the page flow is respected (no rotating tab)
|
||||||
|
|
||||||
|
|
||||||
|
### Dropdown
|
||||||
|
|
||||||
|
The dropdown is not an official aria-widget and thus can’t be tied to a specific role. It exists
|
||||||
|
in a lot of UI libraries and most of them share these properties:
|
||||||
|
- Preferred position is ‘down’
|
||||||
|
- When no space at bottom, they show ‘up’ (in which. Case it behaves a as a dropup)
|
||||||
|
- Unlike popovers and tooltips, it will never be positioned horizontally
|
||||||
|
|
||||||
|
Aliases are ‘popdown’, ‘pulldown’ and many others.
|
||||||
|
|
||||||
|
|
||||||
|
### Select
|
||||||
|
|
||||||
|
Implemented as a dropdown listbox with invoker button. Depending on the content of the options,
|
||||||
|
the child list can either be of type listbox or grid.
|
||||||
|
See: https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html
|
||||||
|
|
||||||
|
|
||||||
|
### Combobox
|
||||||
|
|
||||||
|
Implemented as a dropdown combobox with invoker input. Input is used as search filter
|
||||||
|
and can contain autocomplete or autosuggest functionality:
|
||||||
|
See: https://www.w3.org/TR/wai-aria-practices/#combobox
|
||||||
|
|
||||||
|
|
||||||
|
### (Application) menu
|
||||||
|
|
||||||
|
Or sometimes called context-menu. Uses a dropdown to position its content.
|
||||||
|
See: https://www.w3.org/WAI/tutorials/menus/flyout/
|
||||||
|
Be aware not to use role=“menu”: https://www.w3.org/WAI/tutorials/menus/application-menus/
|
||||||
|
|
||||||
|
|
||||||
|
### Toast
|
||||||
|
|
||||||
|
See: https://www.webcomponents.org/element/@polymer/paper-toast. Should probably be implemented as
|
||||||
|
an alertdialog.
|
||||||
|
|
||||||
|
|
||||||
|
### Sheet
|
||||||
|
|
||||||
|
See: https://material.io/design/components/sheets-bottom.html. Should probably be a
|
||||||
|
global(modal) dialog.
|
||||||
Loading…
Reference in a new issue