Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the focus fixup rule more explicit #8392

Merged
merged 2 commits into from
Jan 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 41 additions & 32 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,18 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<var>removedNode</var> and optionally <var>oldParent</var>, are defined as the following:</p>

<ol>
<li id="node-remove-focus-fixup">
<p>If <var>removedNode</var>'s <span>node document</span>'s <span data-x="focused area of the
document">focused area</span> is <var>removedNode</var>, then set <var>removedNode</var>'s
<span>node document</span>'s <span data-x="focused area of the document">focused area</span> to
<var>removedNode</var>'s <span>node document</span>'s <span>viewport</span>.</p>

<p class="note">This does <em>not</em> perform the <span>unfocusing steps</span>,
<span>focusing steps</span>, or <span>focus update steps</span>, and thus no <code
data-x="event-blur">blur</code> or <code data-x="event-change">change</code> events are
fired.</p>
</li>

<li><p>If <var>removedNode</var> is an element whose <span
data-x="concept-element-namespace">namespace</span> is the <span>HTML namespace</span>, and this
standard defines <span data-x="html element removing steps">HTML element removing steps</span>
Expand Down Expand Up @@ -59283,9 +59295,9 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {

<p class="note" id="note-dialog-plus-focus-fixup">This will cause the <span>focused area of the
document</span> to become <span>inert</span> (unless that currently focused area is a
<span>shadow-including descendant</span> of <var>subject</var>). In such cases, the <span>focus
fixup rule</span> will kick in and reset the <span>focused area of the document</span> to the
<span>viewport</span> for now. In a couple steps we will attempt to find a better candidate to
<span>shadow-including descendant</span> of <var>subject</var>). In such cases, the
<span>focused area of the document</span> will soon be <a href="#focus-fixup-rule">reset</a> to
the <span>viewport</span>. In a couple steps we will attempt to find a better candidate to
focus.</p>
</li>

Expand Down Expand Up @@ -76995,39 +77007,14 @@ partial interface <span id="NavigatorUserActivation-partial">Navigator</span> {
</li>
</ol>

<p>When the <span>currently focused area of a top-level traversable</span> is somehow unfocused
without another element being explicitly focused in its stead, the user agent must
<span>immediately</span> run the <span>unfocusing steps</span> for that object.</p>

<p class="note">The <span>unfocusing steps</span> do not always result in the focus changing,
even when applied to the <span>currently focused area of a top-level traversable</span>. For
<p class="note">The <span>unfocusing steps</span> do not always result in the focus changing, even
when applied to the <span>currently focused area of a top-level traversable</span>. For
example, if the <span>currently focused area of a top-level traversable</span> is a
<span>viewport</span>, then it will usually keep its focus regardless until another
<span>focusable area</span> is explicitly focused with the <span>focusing steps</span>.</p>

<hr>

<p><dfn>Focus fixup rule</dfn>: When the designated <span data-x="focused area of the
document">focused area of the document</span> is removed from that <code>Document</code> in some
way (e.g. it stops being a <span>focusable area</span>, it is removed from the DOM, it becomes
<span>inert</span>, etc.), designate the <code>Document</code>'s <span>viewport</span> to be the
new <span>focused area of the document</span>.</p>

<p class="example">For example, this might happen because an element is removed from its
<code>Document</code>, or has a <code data-x="attr-hidden">hidden</code> attribute added. It might
also happen to an <code>input</code> element when the element gets <span
data-x="concept-fe-disabled">disabled</span>.</p>

<p class="example">In a <code>Document</code> whose <span data-x="focused area of the
document">focused area</span> is a <code>button</code> element, removing, disabling, or hiding
that button would cause the page's new <span data-x="focused area of the document">focused
area</span> to be the <span>viewport</span> of the <code>Document</code>. This would, in turn,
be reflected through the <code
data-x="dom-documentorshadowroot-activeElement">activeElement</code> API as <span>the body
element</span>.</p>

<hr>

<p>The <dfn>focus update steps</dfn>, given an <var>old chain</var>, a <var>new chain</var>, and a <var>new focus target</var> respectively, are as
follows:</p>

Expand Down Expand Up @@ -77074,8 +77061,9 @@ partial interface <span id="NavigatorUserActivation-partial">Navigator</span> {
named <code data-x="event-blur">blur</code> at <var>blur event target</var>, with
<var>related blur target</var> as the related target.</p>

<p class="note">In some cases, e.g. if <var>entry</var> is an <code>area</code>
element's shape, a scrollable region, or a <span>viewport</span>, no event is fired.</p>
<p class="note" id="note-sometimes-no-blur-event">In some cases, e.g., if <var>entry</var> is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p class="note" id="note-sometimes-no-blur-event">In some cases, e.g. if <var>entry</var> is
<p class="note" id="note-sometimes-no-blur-event">In some cases, e.g., if <var>entry</var> is

an <code>area</code> element's shape, a scrollable region, or a <span>viewport</span>, no
event is fired.</p>
</li>
</ol>
</li>
Expand Down Expand Up @@ -99513,6 +99501,27 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
</ol>
</li>

<li id="focus-fixup-rule">
<p>For each <span>fully active</span> <code>Document</code> in <var>docs</var>, if the <span
data-x="focused area of the document">focused area</span> of that <code>Document</code> is
not a <span>focusable area</span>, then run the <span>focusing steps</span> for that
<code>Document</code>'s <span>viewport</span>.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "is no longer" important or can it be "is not a"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be a bit confusing for the reader to see "focused area ... is not a focusable area", so "no longer" makes it a bit clearer what's going on.

But, it can also be confusing for the reader to think "no longer" might involve some sort of extra state-tracking, compared to "is not".

On balance, the latter seems worse, so I'll change it as you suggest.


<p class="example">For example, this might happen because an element has the <code
data-x="attr-hidden">hidden</code> attribute added, causing it to stop <span>being
rendered</span>. It might also happen to an <code>input</code> element when the element gets
<span data-x="concept-fe-disabled">disabled</span>.</p>

<p class="note">This will <a href="#note-sometimes-no-blur-event">usually</a> fire <code
data-x="event-blur">blur</code> events, and possibly <code data-x="event-change">change</code>
events.</p>

<p class="note">In addition to this asynchronous fixup, if the <span>focused area of the
document</span> is removed, there is a <a href="#node-remove-focus-fixup">synchronous
fixup</a>. That one will <em>not</em> fire <code data-x="event-blur">blur</code> or <code
data-x="event-change">change</code> events.</p>
</li>

<li><p>For each <span>fully active</span> <code>Document</code> in <var>docs</var>, <span>run
the update intersection observations steps</span> for that <code>Document</code>, passing in
<var>now</var> as the timestamp. <ref spec=INTERSECTIONOBSERVER></p></li>
Expand Down