t u o b a e r a s r e v o p o p w o h t o l e l o h w a e m o to bec d l i u b o t easier Hidde de Vries 1 September 2023 Front Conference, Zurich
Slide 2
& f e i h c s i Modal m
g o l a di s a m m dile
Hidde de Vries 1 September 2023 Front Conference, Zurich
Slide 3
@hdv@front-end.social
In the beginning, content was linear…
Slide 4
@hdv@front-end.social
Today, it can overlap in all sorts of ways
Slide 5
@hdv@front-end.social
Polaroids of development of overlapping window management Photos: Bill Atkinson (‘“Mr User Interface” at Apple’), from: Designing interactions by Bill Moggridge, 93.
Slide 6
Slide 7
g o l a i <d HTML element ∙ wide browser support ∙ (as of recently) good accessibility support
popover New attribute / API in HTML ∙ supported in Chrome stable / Safari Tech Preview / Firefox (⚑)
Slide 8
g o l a i <d
@hdv@front-end.social
UI considerations
HTML element with wide browser support and (as of recently) good accessibility support
Semantics
popover
Positioning
New attribute / API in HTML, v1 supported in Chrome stable, coming to other browsers too
Slide 9
@hdv@front-end.social
Hi, I’m Hidde developer relations + accessibility at NL Design System participant at Open UI CG hidde.blog
LIKE & SUBSCRIBE
Slide 10
The Economist: a popover to teach how the UI works
@hdv@front-end.social
Slide 11
@hdv@front-end.social
Slide 12
Teams: a timed popover to ask for feedback
@hdv@front-end.social
Slide 13
@hdv@front-end.social
Teams: a popover to teach about an Excel integration
Slide 14
@hdv@front-end.social
Teams: a popover to urge me to be my expressive self
Slide 15
@hdv@front-end.social
Slack Huddles: a popover to tell the user they look nice today
Slide 16
Online banking: a popover to autocomplete search query
@hdv@front-end.social
Slide 17
Online banking: a popover to autocomplete search query
Online banking: a popover to select a transfer date
@hdv@front-end.social
Slide 18
@hdv@front-end.social
dialog What is it
Additional window to your main window. a.k.a. “descendant window” or “subwindow”
Slide 19
@hdv@front-end.social
dialog What is it
Usually contains an action or task for the user, sometimes has critical information
Slide 20
@hdv@front-end.social
dialog What is it
‘a “conversation” between the system and the user’
https://carbondesignsystem.com/patterns/dialog-pattern/
Slide 21
@hdv@front-end.social
fi
fi
dialog What is it (typically)
Do you want to continue, yes or no If you want to open a new le, what shall we do with your current le? How do you want to crop this image, where is the hot spot?
Slide 22
@hdv@front-end.social
<dialog> What is it
HTML element to build dialogs <dialog>… </dialog>
html.spec.whatwg.org/dev/interactive-elements.html#the-dialog-element
Slide 23
@hdv@front-end.social
// show as modal element.showModal();
<dialog> Open/close with script
// show as non-modal element.show();
Slide 24
@hdv@front-end.social
// dialog element <dialog>…</dialog>
comes with role, modal setting, closeon-Esc etc
Slide 25
@hdv@front-end.social
// dialog element <dialog>…</dialog> just the semantics, no behaviour
comes with semantics, top layer, inertness, close-on-Esc etc
// an element with // dialog semantics <div role=”dialog”>… </div>
Slide 26
@hdv@front-end.social
// dialog element <dialog>…</dialog> just the semantics, no behaviour
comes with semantics, top layer, inertness, close-on-Esc etc
// an element with // dialog semantics <div role=”dialog”>… </div>
“dialog” just the word
Slide 27
@hdv@front-end.social
current status: <dialog>
Slide 28
@hdv@front-end.social scottohara.me/blog/2023/01/26/use-the-dialog-element.html
more on using <dialog> accessibly
Slide 29
@hdv@front-end.social
popover What is it
a loating piece of UI with supplemental or contextual content “non-modal dialog” “transient content”
f
“supplemental” from Dell DS, “contextual” + “non-modal dialog” from Lightning DS, “transient content” from Spectrum
Slide 30
@hdv@front-end.social
[popover] What is it
an attribute that adds a set of behaviours to any element <div popover>… </div>
html.spec.whatwg.org/dev/popover.html#the-popover-attribute
Slide 31
light dismiss keyboard
(depending on mode)
top layer presence auto-closure of other popovers
Slide 32
@hdv@front-end.social
[popover] What is it
For elements that are: - on top of other page content - not always visible
(ephemeral, short-lived)
usually displayed one at a time
html.spec.whatwg.org/dev/popover.html#the-popover-attribute
@hdv@front-end.social
[popover] No JavaScript required
<button> Toggle popover </button> <div popover> … </div>
make it a popover
Slide 37
@hdv@front-end.social
[popover] No JavaScript required
<button> Toggle popover </button> <div popover id=”p”> … </div> add a unique ID
Slide 38
@hdv@front-end.social
point button to ID
[popover] No JavaScript required
<button popovertarget=”p”> Toggle popover </button> <div popover id=”p”> … </div>
Slide 39
@hdv@front-end.social
opening dialogs (and more) without js github.com/whatwg/html/issues/9625
Slide 40
@hdv@front-end.social
[popover] Can open, close or toggle
<button popovertarget=”p” popovertargetaction=”show”> Open popover </button> <div popover id=”p”> … </div>
Slide 41
@hdv@front-end.social
[popover] Has auto and manual modes
// Closes other popovers // when opened; has // light dismiss. <div popover=”auto”> … </div>
Slide 42
@hdv@front-end.social
[popover] Has auto and manual modes
// Closes other popovers // when opened; has // light dismiss. <div popover=”auto”> … </div> // No closing of others, // no light dismiss <div popover=”manual”> … </div>
Slide 43
@hdv@front-end.social
// show as popover element.showPopover();
[popover] Open/close with script
Slide 44
@hdv@front-end.social
current status: popover attribute/api
in Chrome >114
Tech Preview >167, Safari 17 (fall 2023)
Firefox > 114
dom.element.popover.enabled
Slide 45
@hdv@front-end.social
🤔 How are these patterns different?
Slide 46
@hdv@front-end.social
modal vs non-modal
Slide 47
The Economist: a modal overlay for privacy consent
@hdv@front-end.social
Slide 48
Dutch government: a modal to extend the DigiD session
@hdv@front-end.social
Slide 49
A “game over” screen
@hdv@front-end.social
Slide 50
The Economist: popover with options
@hdv@front-end.social
Slide 51
Social network: a non-modal alternative text dialog
@hdv@front-end.social
Slide 52
CMS: a non-modal menu for image options
@hdv@front-end.social
Slide 53
Booking website: a non-modal chat widget
@hdv@front-end.social
Slide 54
@hdv@front-end.social
Making an element modal is a drastic measure, the user can do nothing else. Use it sparingly!
Slide 55
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss
Slide 56
New message: explicit dismiss
@hdv@front-end.social
Slide 57
Font chooser: light dismiss
@hdv@front-end.social
Slide 58
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss z-index vs top layer
Slide 59
@hdv@front-end.social
fi
fi
With z-index, you can stack elements on top of each other.
The element that is rst in the DOM is painted rst, each subsequent element on top of the previous and
Slide 60
@hdv@front-end.social
fi
fi
With z-index, you can stack elements on top of each other.
The element that is rst in the DOM is painted rst, each subsequent element on top of the previous and
z-index: 1;
Slide 61
@hdv@front-end.social
With z-index, you can stack elements on top of each other.
The element that is rst in the DOM is painted rst, The element that each subsequent rstofin the DOM element onistop is painted rst, the previous and each subsequent element on top of the previous and
fi
fi
fi
fi
z-index: 2;
Slide 62
@hdv@front-end.social
The top layer is above everything else, its own layer above the main document
fi
fi
fi
fi
drafts.csswg.org/css-position-4/#top-layer
The element that is rst in the DOM is painted rst, The element that each subsequent rstofin the DOM element onistop is painted rst, the previous and each subsequent element on top of the previous and
Slide 63
@hdv@front-end.social
The top layer is above everything else, its own layer above the main document drafts.csswg.org/css-position-4/#top-layer
Slide 64
@hdv@front-end.social
Layered based on order of top layer addition, not z-index
fi
fi
fi
fi
drafts.csswg.org/css-position-4/#top-layer
The element that is rst in the DOM is painted rst, The element that each subsequent rstofin the DOM element onistop is painted rst, the previous and each subsequent element on top of the previous and
top layer, top layer, top layer, top layer, top layer, top layer
Slide 65
@hdv@front-end.social
Layered based on order of top layer addition, not z-index
fi
fi
fi
fi
drafts.csswg.org/css-position-4/#top-layer
The element that is rst in the DOM is painted rst, The element that each subsequent top layer, top rstofin the DOM element onistop layer, top layer, is painted rst, the previous and top layer, top each subsequent layer, top layer also top layer, element on top of also top layer, the previous and also top layer, also top layer,
Slide 66
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss z-index vs top layer backdrop
Slide 67
@hdv@front-end.social
Sometimes elements have a backdrop. Top layer elements have a built-in styleable backdrop (::backdrop) fullscreen.spec.whatwg.org/#::backdrop-pseudo-element
Slide 68
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss z-index vs top layer backdrop keyboard focus trap
Slide 69
@hdv@front-end.social
keyboard focus trap Sometimes you want to prevent users from exiting a component with their Tab key. This is always temporary.
Slide 70
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss z-index vs top layer backdrop keyboard focus trap
Slide 71
@hdv@front-end.social
modal vs non-modal <dialog>
<dialog> with showModal()
dismiss light dismiss vs explicit with show() popover vs top layer z-index
backdrop keyboard focus trap
Slide 72
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss popover=”auto”
popover=”manual”
z-index vs top layer backdrop
any <dialog>
keyboard focus trap
Slide 73
@hdv@front-end.social
modal vs <dialog>
popover non-modal <dialog> with showModal()
vs explicit dismiss light dismiss with show() z-index vs top layer backdrop keyboard focus trap
Slide 74
@hdv@front-end.social
modal vs non-modal w/ ::backdrop browser provided
light dismiss vs
consider if modal <dialog> not better
popover explicit dismiss <dialog> with showModal()
z-index vs top layer backdrop
keyboard focus trap
Slide 75
@hdv@front-end.social
modal vs non-modal w/ ::backdrop browser provided
light dismiss vs
consider if modal <dialog> not better
popover explicit dismiss <dialog> with showModal()
z-index vs top layer backdrop
keyboard focus trap
Slide 76
@hdv@front-end.social
modal vs non-modal light dismiss vs explicit dismiss browser provided vs top layer z-index <dialog> with showModal()
backdrop
keyboard focus trap
Slide 77
@hdv@front-end.social
semantics
Slide 78
“What is this thing?” — philosophers
@hdv@front-end.social
Slide 79
“What is this thing in this page/app?” —web developers
@hdv@front-end.social
Slide 80
@hdv@front-end.social
<h1> heading
Slide 81
@hdv@front-end.social
<h1> heading
Slide 82
@hdv@front-end.social
<a> link
Slide 83
@hdv@front-end.social
<li> list item
Slide 84
@hdv@front-end.social
<dialog> dialog
Slide 85
@hdv@front-end.social
<div> [no role]
Slide 86
@hdv@front-end.social
<div role=”link”> link
Slide 87
@hdv@front-end.social
<div popover> [no role]
Slide 88
@hdv@front-end.social
The popover attribute adds behaviour, not semantics (you choose a role based on the situation)
Slide 89
@hdv@front-end.social
For components that are like a smaller window / subwindow on top of the main page
dialogs <dialog> or role=”dialog”
Slide 90
@hdv@front-end.social
For components that are like a smaller window / subwindow on top of the main page
Slide 91
@hdv@front-end.social
For components that are like a smaller window / subwindow on top of the main page
Slide 92
@hdv@front-end.social
For components that let the user choose from a list, the listbox wraps the choices
listbox role=”listbox”
Slide 93
@hdv@front-end.social
For components that let the user choose from a list, the listbox wraps the choices
listbox role=”listbox”
listbox role=”listbox”
Slide 94
@hdv@front-end.social
listbox role=”listbox”
Slide 95
@hdv@front-end.social
For components that o fer the user a list of choices that are actions (like in an application).
menus
f
role=”menu”
Slide 96
@hdv@front-end.social
For components that o fer the user a list of choices that are actions (like in an application).
menus
f
role=”menu”
Slide 97
@hdv@front-end.social
For components that o fer the user a list of choices that are actions (like in an application).
menus
f
role=”menu”
Slide 98
@hdv@front-end.social
Plain text suggestions
tooltips role=”tooltip”
Slide 99
tooltips role=”dialog”
More than plain text, maybe better as toggletips
Slide 100
@hdv@front-end.social
dialogs <dialog> or role=”dialog”
tooltips role=”tooltip”
menus role=”menu”
role=”dialog”
Slide 101
@hdv@front-end.social
semantics <dialog>
dialog (implicit)
popover
it depends. You choose an apt role, could be dialog, listbox, menu or tooltip
Slide 102
@hdv@front-end.social
positioning
Slide 103
@hdv@front-end.social
g o l a i d < popover ) ( l a d o M w o h s h t i w
Both are centered by default
Slide 104
@hdv@front-end.social
log.hidde.blog
Slide 105
@hdv@front-end.social
Slide 106
@hdv@front-end.social // concert-list.njk <ol> {% for concert in concerts %} <li> … </li> {% endfor %} </ol>
Slide 107
@hdv@front-end.social
// concert-list.njk <ol> {% for concert in concerts %} <li> … {% if concert.images %} <button type=”button” data-dialogtarget=”{{ dialogID }}” aria-label=”Details for {{ concert.info }}” <svg aria-hidden=”true” focusable=”false”>…></svg> </button> {% endif %} </li> {% endfor %} </ol>
@hdv@front-end.social // book-list.njk … <button type=”button” popovertarget=”filters”> Toggle filters </button> <div popover role=”menu” id=”filters”> <button type=”button”> Show only Dutch authors </button> <button type=”button”> Show only books with blue covers </button> <button type=”button”> Show only books rated > 3 stars </button> </div> …
Slide 120
@hdv@front-end.social // book-list.njk … <button type=”button” popovertarget=”filters”> Show filters </button> <div popover role=”menu” id=”filters”> <button type=”button” role=”menuitem” autofocus> Show only Dutch authors </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books with blue covers </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books rated > 3 stars </button> </div> …
Slide 121
@hdv@front-end.social // book-list.njk … <button type=”button” popovertarget=”filters”> Show filters </button> <div popover role=”menu” id=”filters”> <button type=”button” role=”menuitem” autofocus> Show only Dutch authors </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books with blue covers </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books rated > 3 stars </button> </div> …
Slide 122
@hdv@front-end.social // book-list.njk … <button type=”button” popovertarget=”filters”> Show filters </button> <div popover role=”menu” id=”filters”> <button type=”button” role=”menuitem” autofocus> Show only Dutch authors </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books with blue covers </button> <button type=”button” role=”menuitem” tabindex=”-1”> Show only books rated > 3 stars </button> </div> …
Slide 123
@hdv@front-end.social // book-list.njk … <button type=”button” popovertarget=”filters”> Show filters </button> <div popover role=”menu” id=”filters”> <button type=”button”> Show only Dutch authors </button> <button type=”button”> Show only books with blue covers </button> <button type=”button”> Show only books rated > 3 stars </button> </div> …
Slide 124
@hdv@front-end.social
g o l a i d < ✅ popover ) ( l a d o M w o h s h t i w
✅
Both are centered by default
Slide 125
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) // book-list.njk … <script type=”module”> import { computePosition } from ‘https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.9/+esm’; </script> …
Slide 126
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) // book-list.njk … <script type=”module”> import { computePosition } from ‘https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.9/+esm’; const popover = document.querySelector(‘[popover]’); </script> …
Slide 127
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) // book-list.njk … <script type=”module”> import { computePosition } from ‘https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.9/+esm’; const popover = document.querySelector(‘[popover]’); popover.addEventListener(‘toggle’, function(e) { }); </script> …
Slide 128
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) // book-list.njk … <script type=”module”> import { computePosition } from ‘https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.9/+esm’; const popover = document.querySelector(‘[popover]’); popover.addEventListener(‘toggle’, function(e) { const invoker = document.querySelector([popovertarget="${popover.getAttribute('id')}"); }); </script> …
Slide 129
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) // book-list.njk … <script type=”module”> import { computePosition } from ‘https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.9/+esm’; const popover = document.querySelector(‘[popover]’); popover.addEventListener(‘toggle’, function(e) { const invoker = document.querySelector([popovertarget="${popover.getAttribute('id')}"); if (e.newState === ‘open’) { } }); </script> …
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library)
Slide 132
@hdv@front-end.social
popover positioning Option 1: calculate (yourself or with a library) I did have to override the UA default for the popover’s margin and position
g o l a i <d
@hdv@front-end.social
UI considerations
HTML element with wide browser support and (as of recently) good accessibility support
Semantics
popover
Positioning
New attribute / API in HTML, v1 supported in Chrome stable, coming to other browsers too
Slide 136
thank you!
Questions @hdv on most platforms Slides/resources talks.hiddedevries.nl Thanks Scott O’Hara, Adrian Roselli, Jhey Tompkins