Help via ? key, not per-name button #7

Merged
ilia merged 1 commits from fix/help-keyboard-shortcut into main 2026-08-07 15:06:41 -05:00
+77 -30
View File
@@ -266,32 +266,33 @@
font-size: 0.95rem; line-height: 1;
}
.play.playing { background: var(--ink); color: var(--paper); }
.say-row .card-help { margin-left: auto; }
.card-help {
position: relative;
}
.card-help > summary {
list-style: none;
width: 2rem; height: 2rem;
display: inline-grid; place-items: center;
border: 1px solid var(--rule);
color: var(--muted);
cursor: pointer;
font-family: "Source Sans 3", sans-serif;
font-size: 0.95rem; font-weight: 600;
}
.card-help > summary::-webkit-details-marker { display: none; }
.card-help[open] > summary { color: var(--ink); border-color: var(--ink); }
.card-help .help-body {
position: absolute; right: 0; top: calc(100% + 0.35rem);
z-index: 2; width: min(16rem, 70vw);
margin: 0; padding: 0.55rem 0.65rem;
background: var(--sheet); color: var(--muted);
border: 1px solid var(--rule);
font-size: 0.8rem; line-height: 1.35;
box-shadow: 0 4px 14px rgba(20, 20, 20, 0.08);
}
.empty { color: var(--muted); font-size: 0.92rem; padding: 0.35rem 0; }
.help-dialog {
border: 1px solid var(--rule);
background: var(--sheet);
color: var(--ink);
padding: 0;
max-width: min(22rem, calc(100vw - 2rem));
box-shadow: 0 10px 36px rgba(20, 20, 20, 0.18);
}
.help-dialog::backdrop { background: rgba(20, 18, 14, 0.35); }
.help-dialog .help-inner { padding: 1rem 1.1rem 1.05rem; }
.help-dialog h2 {
font-family: "Libre Baskerville", Georgia, serif;
font-size: 1.05rem; margin: 0 0 0.55rem;
}
.help-dialog p { margin: 0 0 0.55rem; color: var(--muted); font-size: 0.9rem; line-height: 1.4; }
.help-dialog ul {
margin: 0 0 0.85rem; padding-left: 1.1rem;
color: var(--muted); font-size: 0.88rem; line-height: 1.45;
}
.help-dialog kbd {
font-family: "Source Sans 3", sans-serif;
font-size: 0.85rem; font-weight: 600;
border: 1px solid var(--rule); padding: 0.05rem 0.35rem;
background: var(--input-bg); color: var(--ink);
}
.help-dialog .row { margin-top: 0.25rem; }
.hidden { display: none !important; }
.compose-head {
display: flex; justify-content: space-between; gap: 0.75rem;
@@ -318,6 +319,12 @@
color: var(--muted); font-size: 0.85rem;
}
.foot a { color: var(--ink); }
.foot kbd, .hint kbd {
font-family: "Source Sans 3", sans-serif;
font-size: 0.8rem; font-weight: 600;
border: 1px solid var(--rule); padding: 0.05rem 0.3rem;
background: var(--input-bg); color: var(--ink);
}
</style>
</head>
<body>
@@ -423,8 +430,25 @@
</div>
</section>
<p class="foot">Paper board · <a href="/v1">classic layout</a> · mark is logo concept 1</p>
<p class="foot">Paper board · press <kbd>?</kbd> for help · <a href="/v1">classic layout</a></p>
</main>
<dialog id="help-dialog" class="help-dialog" aria-labelledby="help-title">
<div class="help-inner">
<h2 id="help-title">Board tips</h2>
<p>Open a name to vote, play pronunciation, and leave notes.</p>
<ul>
<li><strong></strong> play — AI speech until you record</li>
<li><strong></strong> record / <strong></strong> stop — your clip replaces AI</li>
<li><strong></strong> clear recording and use AI again</li>
<li><strong></strong> edit spoken form, origin, meaning · <strong></strong> save</li>
<li>Swipe columns sideways on phone</li>
</ul>
<div class="row">
<button type="button" id="help-close">Close</button>
<span class="hint" style="margin:0">Esc or <kbd>?</kbd> again</span>
</div>
</div>
</dialog>
<script>
const MAX_COLUMNS = 4;
const SPEECH_LANG = { en: "en-US", ru: "ru-RU", he: "he-IL" };
@@ -443,6 +467,33 @@
let speakingBtn = null;
let audioEl = null;
function isTypingTarget(el) {
if (!el || !(el instanceof Element)) return false;
const tag = el.tagName;
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable;
}
function toggleHelp() {
const dlg = document.getElementById("help-dialog");
if (!dlg) return;
if (dlg.open) dlg.close();
else dlg.showModal();
}
document.getElementById("help-close").addEventListener("click", () => {
document.getElementById("help-dialog").close();
});
document.getElementById("help-dialog").addEventListener("click", (e) => {
if (e.target === e.currentTarget) e.currentTarget.close();
});
document.addEventListener("keydown", (e) => {
if (e.key === "?" || (e.key === "/" && e.shiftKey)) {
if (isTypingTarget(e.target)) return;
e.preventDefault();
toggleHelp();
}
});
function colLabel(col) {
const label = (col && col.label || "").trim();
return label || "Untitled";
@@ -647,10 +698,6 @@
<div class="pills">${pills}</div>
<button type="button" class="play" data-play aria-label="Play pronunciation" title="Play">▶</button>
<span class="voice-status">${hasRec ? "<strong>Your voice</strong>" : "AI speech"}</span>
<details class="card-help">
<summary aria-label="How voice and notes work" title="Help">?</summary>
<p class="help-body">Play uses AI speech until you record your own. Re-record replaces the clip. The reset icon returns to AI. Pencil edits spoken form, origin, and meaning.</p>
</details>
</div>
${editing || !hasNotes ? notesEdit : notesView}
<div class="voice-row">