Skip to content

Allow notifications and actions to specify a navigable URL #213

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

Merged
merged 7 commits into from
Aug 1, 2025
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
78 changes: 74 additions & 4 deletions notifications.bs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ or "<code>rtl</code>").
<p>A <a for=/>notification</a> has an associated <dfn for=notification id=body>body</dfn> (a
string).

<p>A <a for=/>notification</a> has an associated <dfn export for=notification>navigation URL</dfn>
(null or a <a for=/>URL</a>). It is initially null.

<p>A <a for=/>notification</a> has an associated <dfn for=notification id=tag>tag</dfn> (a string).

<p>A <a for=/>notification</a> has an associated <dfn for=notification id=data>data</dfn> (a
Expand Down Expand Up @@ -137,6 +140,9 @@ support these features might ignore them.
<dt><dfn for="notification action" id=action-title>title</dfn>
<dd>A string.

<dt><dfn export for="notification action">navigation URL</dfn>
<dd>Null or a <a for=/>URL</a>. It is initially null.

<dt><dfn for="notification action" id=action-icon-url>icon URL</dfn>
<dd>Null or a <a for=/>URL</a>. It is initially null.

Expand Down Expand Up @@ -220,6 +226,11 @@ important information through, e.g., loss of color or clipped corners.
<li><p>Set <var>notification</var>'s <a for=notification>body</a> to
<var>options</var>["{{NotificationOptions/body}}"].

<li><p>If <var>options</var>["{{NotificationOptions/navigate}}"] <a for=map>exists</a>, then
<a lt="URL parser">parse</a> it using <var>baseURL</var>, and if that does not return failure, set
<var>notification</var>'s <a for=notification>navigation URL</a> to the return value. (Otherwise
<var>notification</var>'s <a for=notification>navigation URL</a> remains null.)

<li><p>Set <var>notification</var>'s <a for=notification>tag</a> to
<var>options</var>["{{NotificationOptions/tag}}"].

Expand Down Expand Up @@ -270,6 +281,11 @@ important information through, e.g., loss of color or clipped corners.
<li><p>Set <var>action</var>'s <a for="notification action">title</a> to
<var>entry</var>["{{NotificationAction/title}}"].

<li><p>If <var>entry</var>["{{NotificationAction/navigate}}"] <a for=map>exists</a>, then
<a lt="URL parser">parse</a> it using <var>baseURL</var>, and if that does not return failure,
set <var>action</var>'s <a for="notification action">navigation URL</a> to the return value.
(Otherwise <var>action</var>'s <a for="notification action">navigation URL</a> remains null.)

<li><p>If <var>entry</var>["{{NotificationAction/icon}}"] <a for=map>exists</a>, then
<a lt="URL parser">parse</a> it using <var>baseURL</var>, and if that does not return failure,
set <var>action</var>'s <a for="notification action">icon URL</a> to the return value. (Otherwise
Expand Down Expand Up @@ -541,18 +557,53 @@ interpreted as a language tag. Validity or well-formedness are not enforced. [[!
platform supports activation, the user agent must (unless otherwise specified) run these steps:

<ol>
<li><p>Let <var>action</var> be null.

<li><p>If one of <var>notification</var>'s <a for=notification>actions</a> was activated by the end
user, then set <var>action</var> to that <a for=/>notification action</a>.

<li><p>Let <var>navigationURL</var> be <var>notification</var>'s
<a for=notification>navigation URL</a>.

<li>
<p>If <var>action</var> is non-null, then set <var>navigationURL</var> to <var>action</var>'s
<a for="notification action">navigation URL</a>.

<p class=note>This intentionally makes it so that when a <a for=/>notification action</a>'s
<a for="notification action">navigation URL</a> is null, it falls through to the
<code>click</code> event, providing more flexibility to the web developer.

<li>
<p>If <var>navigationURL</var> is non-null:

<ol>
<li>
<p>Select one of the following two options in an <a>implementation-defined</a> manner:

<ul>
<li><p><a for=/>Navigate</a> an existing <a for=/>top-level traversable</a> within the user
agent's <a for="user agent">top-level traversable set</a> to <var>navigationURL</var>.
Copy link
Member

Choose a reason for hiding this comment

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

But does Safari actually focus-and-navigate a tab? I think it just focuses a tab and does not navigate per what I see for the non-push external clicks. But I may be wrong.

Also does this need to say about focusing?

Copy link
Member Author

@annevk annevk Jul 31, 2025

Choose a reason for hiding this comment

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

It definitely navigates for me when I follow a link from a different app or run open https://github.com/whatwg/notifications/pull/213. Just lost my initial comment trying that.

<!-- Should maybe set userInvolvement to "browser UI" here and below. -->

<li><p><a>Create a fresh top-level traversable</a> given <var>navigationURL</var>.
</ul>

<p class=note>User agents are strongly encouraged to match platform conventions.

<li><p>Return.
</ol>

<li>
<p>If <var>notification</var> is a <a>persistent notification</a>, then:

<ol>
<li><p>Let <var>action</var> be the empty string.
<li><p>Let <var>actionName</var> be the empty string.

<li><p>If one of <var>notification</var>'s <a for=notification>actions</a> was activated by the
user, then set <var>action</var> to that <a for=/>notification action</a>'s
<li><p>If <var>action</var> is non-null, then set <var>actionName</var> to <var>action</var>'s
<a for="notification action">name</a>.

<li><a>Fire a service worker notification event</a> named "<code>notificationclick</code>" given
<var>notification</var> and <var>action</var>.
<var>notification</var> and <var>actionName</var>.
</ol>

<li>
Expand Down Expand Up @@ -643,6 +694,7 @@ interface Notification : EventTarget {
readonly attribute NotificationDirection dir;
readonly attribute DOMString lang;
readonly attribute DOMString body;
readonly attribute USVString navigate;
readonly attribute DOMString tag;
readonly attribute USVString image;
readonly attribute USVString icon;
Expand All @@ -662,6 +714,7 @@ dictionary NotificationOptions {
NotificationDirection dir = "auto";
DOMString lang = "";
DOMString body = "";
USVString navigate;
DOMString tag = "";
USVString image;
USVString icon;
Expand Down Expand Up @@ -690,6 +743,7 @@ enum NotificationDirection {
dictionary NotificationAction {
required DOMString action;
required DOMString title;
USVString navigate;
USVString icon;
};

Expand Down Expand Up @@ -853,6 +907,16 @@ return the <a>maximum number of actions</a> supported.
<p>The <dfn attribute for=Notification><code>body</code></dfn> getter steps are to return
<a>this</a>'s <a for=/>notification</a>'s <a for=notification>body</a>.

<p>The <dfn attribute for=Notification><code>navigate</code></dfn> getter steps are:

<ol>
<li><p>If <a>this</a>'s <a>notification</a>'s <a for=notification>navigation URL</a> is null, then
return the empty string.

<li><p>Return <a>this</a>'s <a>notification</a>'s <a for=notification>navigation URL</a>,
<a lt="URL serializer">serialized</a>.
</ol>

<p>The <dfn attribute for=Notification><code>tag</code></dfn> getter steps are to return
<a>this</a>'s <a for=/>notification</a>'s <a for=notification>tag</a>.

Expand Down Expand Up @@ -925,6 +989,10 @@ then return null.
<li><p>Set <var>action</var>["{{NotificationAction/title}}"] to <var>entry</var>'s
<a for="notification action">title</a>.

<li><p>If <var>entry</var>'s <a for="notification action">navigation URL</a> is non-null, then
set <var>action</var>["{{NotificationAction/navigate}}"] to <var>entry</var>'s
<a for="notification action">navigation URL</a>, <a lt="URL serializer">serialized</a>.

<li><p>If <var>entry</var>'s <a for="notification action">icon URL</a> is non-null, then set
<var>action</var>["{{NotificationAction/icon}}"] to <var>entry</var>'s
<a for="notification action">icon URL</a>, <a lt="URL serializer">serialized</a>.
Expand Down Expand Up @@ -1211,6 +1279,7 @@ Alex Russell,
Anssi Kostiainen,
Arkadiusz Michalski,
Boris Zbarsky,
Brady Eidson,
David Håsäther,
Doug Turner,
Drew Wilson,
Expand All @@ -1222,6 +1291,7 @@ James Graham,
John Mellor,
Jon Lee,
Jonas Sicking,
Kagami Sascha Rosylight<!-- saschanaz; GitHub -->,
Michael Cooper,
Michael Henretty,
Michael™ Smith,
Expand Down