Skip to content

Commit a9f103c

Browse files
authored
Implement dialog initial focus proposal
This implements the changes proposed here: https://github.com/whatwg/html/wiki/dialog--initial-focus,-a-proposal#dialog-draft-text Specifically: 1. Make the dialog focusing steps look at sequentially focusable elements instead of any focusable element. 2. Make the dialog element itself get focus if it has the autofocus="" attribute set. 3. Make the dialog element itself get focus as a fallback instead of focus being reset to the body element. Closes #1929. Closes #2197. Closes #4184. Additional dialog issues remain open at https://github.com/whatwg/html/labels/topic%3A%20dialog.
1 parent e3c56ca commit a9f103c

File tree

1 file changed

+112
-14
lines changed

1 file changed

+112
-14
lines changed

source

+112-14
Original file line numberDiff line numberDiff line change
@@ -59187,8 +59187,88 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
5918759187
<dd w-dev>Uses <code>HTMLDialogElement</code>.</dd>
5918859188
</dl>
5918959189

59190-
<p>The <code>dialog</code> element represents a part of an application that a user interacts with
59191-
to perform a task, for example a dialog box, inspector, or window.</p>
59190+
<p>The <code>dialog</code> element represents a transitory part of an application, in the form of
59191+
a small window ("dialog box"), which the user interacts with to perform a task or gather
59192+
information. Once the user is done, the dialog can be automatically closed by the application, or
59193+
manually closed by the user.</p>
59194+
59195+
<p>Especially for modal dialogs, which are a familiar pattern across all types of applications,
59196+
authors should work to ensure that dialogs in their web applications behave in a way that is
59197+
familiar to users of non-web applications.</p>
59198+
59199+
<p class="note">As with all HTML elements, it is not conforming to use the <code>dialog</code>
59200+
element when attempting to represent another type of control. For example, context menus,
59201+
tooltips, and popup listboxes are not dialog boxes, so abusing the <code>dialog</code> element to
59202+
implement these patterns is incorrect.</p>
59203+
59204+
<p>An important part of user-facing dialog behavior is the placement of initial focus. The
59205+
<span>dialog focusing steps</span> attempt to pick a good candidate for initial focus when a
59206+
dialog is shown, but might not be a substitute for authors carefully thinking through the correct
59207+
choice to match user expectations for a specific dialog. As such, authors should use the <code
59208+
data-x="attr-fe-autofocus">autofocus</code> attribute on the descendant element of the dialog that
59209+
the user is expected to immediately interact with after the dialog opens. If there is no such
59210+
element, then authors should use the <code data-x="attr-fe-autofocus">autofocus</code> attribute
59211+
on the <code>dialog</code> element itself.</p>
59212+
59213+
<div class="example">
59214+
<p>In the following example, a dialog is used for editing the details of a product in an
59215+
inventory management web application.</p>
59216+
59217+
<pre><code class="html">&lt;dialog>
59218+
&lt;label>Product Number &lt;input type="text" readonly>&lt;/label>
59219+
&lt;label>Product Name &lt;input type="text" autofocus>&lt;/label>
59220+
&lt;/dialog></code></pre>
59221+
59222+
<p>If the <code data-x="attr-fe-autofocus">autofocus</code> attribute was not present, the
59223+
Product Number field would have been focused by the dialog focusing steps. Although that is
59224+
reasonable behavior, the author determined that the more relevant field to focus was the Product
59225+
Name field, as the Product Number field is readonly and expects no user input. So, the author
59226+
used autofocus to override the default.</p>
59227+
59228+
<p>Even if the author wants to focus the Product Number field by default, they are best off
59229+
explicitly specifying that by using autofocus on that <code>input</code> element. This makes the
59230+
intent obvious to future readers of the code, and ensures the code stays robust in the face of
59231+
future updates. (For example, if another developer added a close button, and positioned it in the
59232+
node tree before the Product Number field).</p>
59233+
</div>
59234+
59235+
<p>Another important aspect of user behavior is whether dialogs are scrollable or not. In some
59236+
cases, overflow (and thus scrollability) cannot be avoided, e.g., when it is caused by the user's
59237+
high text zoom settings. But in general, scrollable dialogs are not expected by users. Adding
59238+
large text nodes directly to dialog elements is particularly bad as this is likely to cause the
59239+
dialog element itself to overflow. Authors are best off avoiding them.</p>
59240+
59241+
<div class="example">
59242+
<p>The following terms of service dialog respects the above suggestions.</p>
59243+
59244+
<pre><code class="html">&lt;dialog style="height: 80vh;">
59245+
&lt;div style="overflow: auto; height: 60vh;" autofocus>
59246+
&lt;p>By placing an order via this Web site on the first day of the fourth month of the year
59247+
2010 Anno Domini, you agree to grant Us a non-transferable option to claim, for now and for
59248+
ever more, your immortal soul.&lt;/p>
59249+
&lt;p>Should We wish to exercise this option, you agree to surrender your immortal soul,
59250+
and any claim you may have on it, within 5 (five) working days of receiving written
59251+
notification from this site or one of its duly authorized minions.&lt;/p>
59252+
&lt;!-- ... etc., with many more &lt;p> elements ... -->
59253+
&lt;/div>
59254+
&lt;form method="dialog">
59255+
&lt;button type="submit" value="agree">Agree&lt;/button>
59256+
&lt;button type="submit" value="disagree">Disagree&lt;/button>
59257+
&lt;/form>
59258+
&lt;/dialog></code></pre>
59259+
59260+
<p>Note how the <span>dialog focusing steps</span> would have picked the scrollable
59261+
<code>div</code> element by default, but similarly to the previous example, we have placed <code
59262+
data-x="attr-fe-autofocus">autofocus</code> on the <code>div</code> so as to be more explicit and
59263+
robust against future changes.</p>
59264+
59265+
<p>In contrast, if the <code>p</code> elements expressing the terms of service did not have such
59266+
a wrapper <code>div</code> element, then the <code>dialog</code> itself would become scrollable,
59267+
violating the above advice. Furthermore, in the absence of any <code
59268+
data-x="attr-fe-autofocus">autofocus</code> attribute, such a markup pattern would have violated
59269+
the above advice and tripped up the <span>dialog focusing steps</span>'s default behavior, and
59270+
caused focus to jump to the Agree <code>button</code>, which is a bad user experience.</p>
59271+
</div>
5919259272

5919359273
<p>The <dfn element-attr for="dialog"><code data-x="attr-dialog-open">open</code></dfn> attribute
5919459274
is a <span>boolean attribute</span>. When specified, it indicates that the <code>dialog</code>
@@ -59276,7 +59356,8 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
5927659356
<li><p>Set the <code>dialog</code> element's <span>previously focused element</span> to the
5927759357
<span>focused</span> element.</p></li>
5927859358

59279-
<li><p>Run the <span>dialog focusing steps</span> for the <code>dialog</code> element.</p></li>
59359+
<li><p>Run the <span>dialog focusing steps</span> given the <code>dialog</code> element and
59360+
false.</p></li>
5928059361
</ol>
5928159362

5928259363
<p>When the <dfn method for="HTMLDialogElement"><code
@@ -59318,22 +59399,32 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
5931859399
<li><p>Set the <var>subject</var>'s <span>previously focused element</span> to the
5931959400
<span>focused</span> element.</p></li>
5932059401

59321-
<li><p>Run the <span>dialog focusing steps</span> for <var>subject</var>.</p></li>
59402+
<li><p>Run the <span>dialog focusing steps</span> given <var>subject</var> and true.</p></li>
5932259403
</ol>
5932359404

59324-
<p>The <dfn>dialog focusing steps</dfn> for a <code>dialog</code> element <var>subject</var> are as follows:</p>
59405+
<p>The <dfn>dialog focusing steps</dfn>, given a <code>dialog</code> element <var>subject</var>
59406+
and a boolean <var>isModal</var>, are as follows:</p>
5932559407

5932659408
<ol>
59327-
<li><p>Let <var>control</var> be the <span>focus delegate</span> of <var>subject</var>.</p></li>
59409+
<li><p>Let <var>control</var> be null.</p></li>
59410+
59411+
<li><p>If <var>isModal</var> is true and <var>subject</var> has the <code
59412+
data-x="attr-fe-autofocus">autofocus</code> attribute, then set <var>control</var> to
59413+
<var>subject</var>.</p></li>
59414+
59415+
<li><p>If <var>control</var> is null, then set <var>control</var> to the <span>focus
59416+
delegate</span> of <var>subject</var>.</p></li>
5932859417

5932959418
<li><p>If <var>control</var> is null, then set <var>control</var> to <var>subject</var>.</p></li>
5933059419

5933159420
<li>
5933259421
<p>Run the <span>focusing steps</span> for <var>control</var>.</p>
5933359422

59334-
<p class="note">If <var>control</var> is not <span>focusable</span>, this will do nothing. For
59335-
modal dialogs, this means that any <a href="#note-dialog-plus-focus-fixup">earlier
59336-
modifications</a> to the <span>focused area of the document</span> will apply.</p>
59423+
<p class="note">If <var>control</var> is not <span>focusable</span>, this will do nothing. This
59424+
would only happen if subject had no focus delegate, and the user agent decided that
59425+
<code>dialog</code> elements were not generally focusable. In that case, any <a
59426+
href="#note-dialog-plus-focus-fixup">earlier modifications</a> to the <span>focused area of the
59427+
document</span> will apply.</p>
5933759428
</li>
5933859429

5933959430
<li><p>Let <var>topDocument</var> be <var>control</var>'s <span>node navigable</span>'s <span
@@ -76245,9 +76336,9 @@ partial interface <span id="NavigatorUserActivation-partial">Navigator</span> {
7624576336
The element itself.
7624676337
<tr>
7624776338
<td headers="td-fa-1 th-fa-examples" colspan=2>
76248-
<p class="example"><code>iframe</code>, <code data-x="attr-input-type-text">&lt;input
76249-
type=text></code>, sometimes <code data-x="a">&lt;a href=""></code> (depending on platform
76250-
conventions).
76339+
<p class="example"><code>iframe</code>, <code>dialog</code>, <code
76340+
data-x="attr-input-type-text">&lt;input type=text></code>, sometimes <code data-x="a">&lt;a
76341+
href=""></code> (depending on platform conventions).
7625176342

7625276343
<tbody>
7625376344
<tr>
@@ -76864,11 +76955,18 @@ partial interface <span id="NavigatorUserActivation-partial">Navigator</span> {
7686476955
order</span>:</p>
7686576956

7686676957
<ol>
76867-
<li><p>If <var>descendant</var> is a <span>focusable area</span>, then return
76958+
<li><p>Let <var>focusableArea</var> be null.</p></li>
76959+
76960+
<li><p>If <var>focusTarget</var> is a <code>dialog</code> element and <var>descendant</var> is
76961+
<span>sequentially focusable</span>, then set <var>focusableArea</var> to
76962+
<var>descendant</var>.</p></li>
76963+
76964+
<li><p>Otherwise, if <var>focusTarget</var> is not a <code>dialog</code> and
76965+
<var>descendant</var> is a <span>focusable area</span>, set <var>focusableArea</var> to
7686876966
<var>descendant</var>.</p></li>
7686976967

7687076968
<li>
76871-
<p>Let <var>focusableArea</var> be the result of <span data-x="get the focusable
76969+
<p>Otherwise, set <var>focusableArea</var> to the result of <span data-x="get the focusable
7687276970
area">getting the focusable area</span> for <var>descendant</var> given
7687376971
<var>focusTrigger</var>.</p>
7687476972

0 commit comments

Comments
 (0)