diff --git a/README.md b/README.md
index a754e909..471d5bbf 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,8 @@ Do not specify supported browsers and their versions in code comments or prose,
- The "insert-adjacent" directory contains basic demos for [insertAdjacentElement](https://mdn.github.io/dom-examples/insert-adjacent/insertAdjacentElement.html) and [insertAdjacentText](https://mdn.github.io/dom-examples/insert-adjacent/insertAdjacentText.html).
+- The "interest-invokers" directory is for [interest invoker](https://developer.mozilla.org/docs/Web/API/Popover_API/Interest_invokers) examples. Go to the [Interest invoker examples index](https://mdn.github.io/dom-examples/interest-invokers/) to see what's available.
+
- The "launch-handler" directory contains a demo for the [Launch Handler API](https://developer.mozilla.org/en-US/docs/Web/API/Launch_Handler_API). [View the demo live](https://mdn.github.io/dom-examples/launch-handler/). This example was originally published on Glitch by [Thomas Steiner](https://front-end.social/@tomayac@toot.cafe).
- The "local-font-access" directory contains a demo for the [Local Font Access API](https://developer.mozilla.org/en-US/docs/Web/API/Local_Font_Access_API). [View the demo live](https://mdn.github.io/dom-examples/local-font-access/).
@@ -123,7 +125,6 @@ Do not specify supported browsers and their versions in code comments or prose,
- Another example of view transitions in a [simple multiple-page app](https://mdn.github.io/dom-examples/view-transitions/mpa-homepage/)
- [The `match-element` value](https://mdn.github.io/dom-examples/view-transitions/match-element/) for the `view-transition-name` property
-
- The "web-share" directory contains a basic demo to show usage of the [Web Share API](https://developer.mozilla.org/docs/Web/API/Navigator/share). [View the demo live](https://mdn.github.io/dom-examples/web-share/).
- The "web-workers" directory contains several demos that show how [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) operate. For example, view the live [simple web worker demo](https://mdn.github.io/dom-examples/web-workers/simple-web-worker/).
diff --git a/interest-invokers/index.html b/interest-invokers/index.html
new file mode 100644
index 00000000..81817ef8
--- /dev/null
+++ b/interest-invokers/index.html
@@ -0,0 +1,41 @@
+
+
+
+ Popover examples: Demonstrates a couple
+ of examples of displaying popovers via interest invokers, including a
+ typical link preview popover.
+
+
+ Style preview: Demonstrates non-popover
+ usage of interest invokers. In this example, several buttons can be
+ pressed to apply different style themes to a style preview pane.
+ Interest invokers have been used to progressively enhance the demo,
+ making it so that hovering/focusing the buttons previews the styles on
+ the pane without having to click to apply each one.
+
+
+ Stock tracking example: A more complex
+ example that shows a greengrocer's stock represented by buttons in
+ different columns. You can hover/focus a stock button to start
+ incrementing a number of items to move, and then click the butotn to
+ move them over to the other column.
+
+
+
+
diff --git a/interest-invokers/popover-examples/chris-mills.jpg b/interest-invokers/popover-examples/chris-mills.jpg
new file mode 100644
index 00000000..0f9fdf37
Binary files /dev/null and b/interest-invokers/popover-examples/chris-mills.jpg differ
diff --git a/interest-invokers/popover-examples/index.html b/interest-invokers/popover-examples/index.html
new file mode 100644
index 00000000..516e59c2
--- /dev/null
+++ b/interest-invokers/popover-examples/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+ interestfor example
+
+
+
+
+
+
+ Independent tech writer and web technology tinkerer, working on MDN
+ on behalf of Google and Mozilla. A11y and open standards advocate.
+ Heavy metal drummer.
+
+
+
diff --git a/interest-invokers/stock-moving/index.js b/interest-invokers/stock-moving/index.js
new file mode 100644
index 00000000..c3251abc
--- /dev/null
+++ b/interest-invokers/stock-moving/index.js
@@ -0,0 +1,102 @@
+// Feature detection
+
+const supported =
+ HTMLButtonElement.prototype.hasOwnProperty("interestForElement");
+if (!supported) {
+ document.querySelector("html").classList.add("no-interest-invokers");
+}
+
+// Variable and handler definition
+
+const interestBtns = document.querySelectorAll("button");
+const btnTooltip = document.getElementById("button-tooltip");
+const keepList = document.querySelector(".keep");
+const sellList = document.querySelector(".sell");
+
+let interval;
+let stockToMove = 0;
+
+btnTooltip.addEventListener("interest", incrementStock);
+btnTooltip.addEventListener("loseinterest", resetStock);
+interestBtns.forEach((btn) => btn.addEventListener("click", moveStock));
+
+// Increment the amount of stock to move when interest is shown
+function incrementStock(e) {
+ const sourceElem = e.source;
+ stockToMove = 0;
+
+ function updateStockCount() {
+ // Only increment stockToMove if it is smaler than the entire available stock
+ let stock = Number(sourceElem.getAttribute("data-stock"));
+ if (stockToMove < stock) {
+ stockToMove++;
+ btnTooltip.textContent = `Stock to move: ${stockToMove}`;
+ }
+ }
+
+ // Immediately increment stock to move, and then do it repeated every 250ms
+ updateStockCount();
+ interval = setInterval(updateStockCount, 250);
+}
+
+// Reset the amount of stock to move when interest is lost
+function resetStock(e) {
+ // Clear the interval and the tooltip's text content, ready for next time
+ clearInterval(interval);
+ btnTooltip.textContent = "";
+}
+
+// Move the stock when the button is actually clicked
+function moveStock(e) {
+ // Determine which list we are moving the stock item to
+ let targetList;
+ if (e.target.parentNode === keepList) {
+ targetList = sellList;
+ } else {
+ targetList = keepList;
+ }
+
+ // number of items and product to move
+ const newStock = stockToMove;
+ const newProduct = e.target.getAttribute("data-product");
+
+ // Determine whether a stack of that item already
+ // exists at the place to move the item to
+ const targetProductsList = Array.from(targetList.children);
+ const existingNewProduct = targetProductsList.find(
+ (element) => element.getAttribute("data-product") === newProduct
+ );
+
+ // If so, just add the items to the existing stack
+ if (existingNewProduct) {
+ const totalStock =
+ Number(existingNewProduct.getAttribute("data-stock")) + newStock;
+ existingNewProduct.setAttribute("data-stock", totalStock);
+ existingNewProduct.textContent = `${newProduct} (${totalStock})`;
+ } else {
+ // If not, create a new stack and append it to the list
+ const newBtn = document.createElement("button");
+ newBtn.setAttribute("interestFor", "button-tooltip");
+ newBtn.setAttribute("data-stock", newStock);
+ newBtn.setAttribute("data-product", newProduct);
+ newBtn.textContent = `${newProduct} (${newStock})`;
+ newBtn.addEventListener("click", moveStock);
+ targetList.appendChild(newBtn);
+ }
+
+ // Update the stack the stock was moved FROM to show the remaining items
+ const oldStock = Number(e.target.getAttribute("data-stock")) - stockToMove;
+ e.target.setAttribute("data-stock", oldStock);
+ e.target.textContent = `${newProduct} (${oldStock})`;
+
+ // Unfocus the button interest was being shown in. If you don't do this, you get weird behavior
+ // when it was focused via the keyboard — the interestfor target element starts incrementing again
+ // immediately, and if the stack goes to 0 and disappears (see next block), the focus shifts to the
+ // body and you get the interestfor target appearing at the top of the viewport!
+ e.target.blur();
+
+ // If the stack the stock was moved from has no remaining items, remove it from the DOM
+ if (e.target.getAttribute("data-stock") === "0") {
+ e.target.remove();
+ }
+}
diff --git a/interest-invokers/stock-moving/styles.css b/interest-invokers/stock-moving/styles.css
new file mode 100644
index 00000000..e9f4a4b2
--- /dev/null
+++ b/interest-invokers/stock-moving/styles.css
@@ -0,0 +1,58 @@
+html {
+ font-family: sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+/* Browser support banner */
+
+.no-interest-invokers body::before {
+ content: "Your browser doesn't support interest invokers.";
+ background-color: wheat;
+ display: block;
+ padding: 10px 0;
+ width: 100%;
+ text-align: center;
+}
+
+/* Layout styles */
+
+.wrapper {
+ max-width: 640px;
+ margin: 0 auto;
+ display: flex;
+}
+
+.wrapper section {
+ flex: 1;
+}
+
+/* interestfor styles */
+
+h1,
+h2 {
+ text-align: center;
+}
+
+button[interestfor] {
+ display: block;
+ padding: 10px;
+ border-radius: 5px;
+ border: 1px solid lightgray;
+ width: 50%;
+ margin: 10px auto;
+ /* Needs to be set on the interest invoker element (with interestfor set on it), not the popover */
+ interest-delay: 1s 0s;
+}
+
+#button-tooltip {
+ border: 1px solid lightgray;
+ border-radius: 5px;
+ padding: 10px;
+ margin: 1px;
+ background-color: white;
+ font-size: 0.8rem;
+ position-area: bottom;
+}
diff --git a/interest-invokers/style-preview/index.html b/interest-invokers/style-preview/index.html
new file mode 100644
index 00000000..f02a11d8
--- /dev/null
+++ b/interest-invokers/style-preview/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+ interestfor without popover
+
+
+
+
+
+