From bc36c125ab2b10fce6683056f6a844d59dfda4b7 Mon Sep 17 00:00:00 2001
From: ll-nick <68419636+ll-nick@users.noreply.github.com>
Date: Thu, 17 Sep 2026 17:06:45 +0200
Subject: [PATCH 1/5] Add tooltips to buttons
---
src/inkflow/presenter.html | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/inkflow/presenter.html b/src/inkflow/presenter.html
index 916a179..cb22a5d 100644
--- a/src/inkflow/presenter.html
+++ b/src/inkflow/presenter.html
@@ -140,7 +140,7 @@
KEYBINDINGS
-
-
+
@@ -239,7 +239,7 @@ KEYBINDINGS
|
step –
-
+
From 50944162484b250ac28a7d5f322f6e11a482b41b Mon Sep 17 00:00:00 2001
From: ll-nick <68419636+ll-nick@users.noreply.github.com>
Date: Thu, 17 Sep 2026 17:06:59 +0200
Subject: [PATCH 2/5] Add current state to sync menu tooltip
---
src/ts/presenter/syncmenu.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ts/presenter/syncmenu.ts b/src/ts/presenter/syncmenu.ts
index 8d870ba..7afe0ea 100644
--- a/src/ts/presenter/syncmenu.ts
+++ b/src/ts/presenter/syncmenu.ts
@@ -20,7 +20,7 @@ const SYNC_LABELS: Record = {
function renderSyncButton(): void {
btnSync.dataset.mode = state.syncMode;
const label = SYNC_LABELS[state.syncMode];
- btnSync.title = `Sync: ${label} (s)`;
+ btnSync.dataset.tooltip = `Sync: ${label} (s)`;
btnSync.setAttribute("aria-label", `Sync mode: ${label}`);
for (const row of syncMenu.querySelectorAll(".sync-row")) {
const active = row.dataset.mode === state.syncMode;
From b1796db2f463cf3bbd02a776b052028ebeef76b5 Mon Sep 17 00:00:00 2001
From: ll-nick <68419636+ll-nick@users.noreply.github.com>
Date: Thu, 17 Sep 2026 17:07:06 +0200
Subject: [PATCH 3/5] Style tooltips
---
src/css/presenter/base.css | 45 ++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/src/css/presenter/base.css b/src/css/presenter/base.css
index 05d4e61..f2b0254 100644
--- a/src/css/presenter/base.css
+++ b/src/css/presenter/base.css
@@ -96,6 +96,51 @@ body {
background: rgba(0, 0, 0, 0.08);
}
+/* ── Status-bar tooltips: driven by data-tooltip (not title) so the slow, unstyled
+ native browser tooltip never doubles up with this one. Anchored above the bar,
+ since #statusbar sits at the bottom of the viewport. ── */
+.hud-btn[data-tooltip] {
+ position: relative;
+}
+.hud-btn[data-tooltip]::after {
+ content: attr(data-tooltip);
+ position: absolute;
+ bottom: calc(100% + 8px);
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--surface);
+ color: var(--text);
+ border: 1px solid var(--overlay);
+ border-radius: 4px;
+ padding: 0.3rem 0.5rem;
+ font-size: 0.72rem;
+ white-space: nowrap;
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
+ pointer-events: none;
+ opacity: 0;
+ transition: opacity 0.1s ease;
+ z-index: 40;
+}
+.hud-btn[data-tooltip]:hover::after,
+.hud-btn[data-tooltip]:focus-visible::after {
+ opacity: 1;
+ transition-delay: 0.35s;
+}
+/* Suppress while the sync dropdown is open — the tooltip would sit under the menu. */
+#btn-sync[aria-expanded="true"]:hover::after {
+ opacity: 0;
+ transition-delay: 0s;
+}
+/* Edge buttons: keep the bubble on-screen instead of centering off the bar. */
+#btn-theme[data-tooltip]::after {
+ left: 0;
+ transform: none;
+}
+#log-indicator[data-tooltip]::after {
+ left: auto;
+ right: 0;
+}
+
.hud-sep {
width: 1px;
height: 16px;
From 2af1c3aa02251a7b9caf37baea967e3c2b806209 Mon Sep 17 00:00:00 2001
From: ll-nick <68419636+ll-nick@users.noreply.github.com>
Date: Thu, 17 Sep 2026 17:07:17 +0200
Subject: [PATCH 4/5] Rebuild bundles
---
src/inkflow/bundles/presenter.css | 39 +++++++++++++++++++++++++++++++
src/inkflow/bundles/presenter.js | 2 +-
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/src/inkflow/bundles/presenter.css b/src/inkflow/bundles/presenter.css
index 83f1a63..ba91d24 100644
--- a/src/inkflow/bundles/presenter.css
+++ b/src/inkflow/bundles/presenter.css
@@ -116,6 +116,45 @@ body {
[data-theme=light] .hud-btn:hover {
background: rgba(0, 0, 0, 0.08);
}
+.hud-btn[data-tooltip] {
+ position: relative;
+}
+.hud-btn[data-tooltip]::after {
+ content: attr(data-tooltip);
+ position: absolute;
+ bottom: calc(100% + 8px);
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--surface);
+ color: var(--text);
+ border: 1px solid var(--overlay);
+ border-radius: 4px;
+ padding: 0.3rem 0.5rem;
+ font-size: 0.72rem;
+ white-space: nowrap;
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
+ pointer-events: none;
+ opacity: 0;
+ transition: opacity 0.1s ease;
+ z-index: 40;
+}
+.hud-btn[data-tooltip]:hover::after,
+.hud-btn[data-tooltip]:focus-visible::after {
+ opacity: 1;
+ transition-delay: 0.35s;
+}
+#btn-sync[aria-expanded=true]:hover::after {
+ opacity: 0;
+ transition-delay: 0s;
+}
+#btn-theme[data-tooltip]::after {
+ left: 0;
+ transform: none;
+}
+#log-indicator[data-tooltip]::after {
+ left: auto;
+ right: 0;
+}
.hud-sep {
width: 1px;
height: 16px;
diff --git a/src/inkflow/bundles/presenter.js b/src/inkflow/bundles/presenter.js
index 711bc28..c7a10bc 100644
--- a/src/inkflow/bundles/presenter.js
+++ b/src/inkflow/bundles/presenter.js
@@ -2858,7 +2858,7 @@
function renderSyncButton() {
btnSync.dataset.mode = state.syncMode;
const label = SYNC_LABELS[state.syncMode];
- btnSync.title = `Sync: ${label} (s)`;
+ btnSync.dataset.tooltip = `Sync: ${label} (s)`;
btnSync.setAttribute("aria-label", `Sync mode: ${label}`);
for (const row of syncMenu.querySelectorAll(".sync-row")) {
const active = row.dataset.mode === state.syncMode;
From 395be13054155dbe2eafd48b9a3c89326c361d55 Mon Sep 17 00:00:00 2001
From: ll-nick <68419636+ll-nick@users.noreply.github.com>
Date: Thu, 17 Sep 2026 17:07:54 +0200
Subject: [PATCH 5/5] Update docs
---
docs/guides/presenter-view.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/guides/presenter-view.md b/docs/guides/presenter-view.md
index d3d15d8..92f25bc 100644
--- a/docs/guides/presenter-view.md
+++ b/docs/guides/presenter-view.md
@@ -71,8 +71,8 @@ See [Authoring slides](slides.md#speaker-notes) and
## Using a second screen
To present on a projector while keeping the panel on your laptop screen,
-click the "Open presenter view" button in the status bar.
-It opens a second window at the same position
+click the "Open a synced window" button in the status bar.
+It opens another window at the same position
(see [Multi-window sync](#multi-window-sync) for what makes this work in a static build).
In the window on your laptop screen, press p to open the panel.
Leave the other window full-screen on the projector.
@@ -90,7 +90,7 @@ How position sync reaches other windows depends on how the deck is running:
- **`inkflow build` output** (including a bare `file://` double-click, with no server at all)
has no WebSocket to relay over,
so it syncs exactly **two** windows directly:
- the one you launch "Open presenter view" from, and the window it opens.
+ the one you launch "Open a synced window" from, and the window it opens.
They talk to each other over a direct browser-to-browser link
that only exists between opener and opened window,
so a second window opened independently