privateboard 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -226,18 +226,6 @@
226
226
  </div>
227
227
  </div>
228
228
 
229
- <div class="us-row">
230
- <div class="us-row-label">Typing sound</div>
231
- <div class="us-row-field">
232
- <div class="us-toggle-row">
233
- <button type="button" class="us-toggle-pill" data-us-sfx-typing aria-pressed="false">
234
- <span class="us-toggle-dot"></span>
235
- <span class="us-toggle-label" data-us-sfx-typing-label>off</span>
236
- </button>
237
- <span class="us-toggle-deck">a soft keyboard click as directors stream their replies. Persists locally.</span>
238
- </div>
239
- </div>
240
- </div>
241
229
  </div>
242
230
  `;
243
231
  }
@@ -268,6 +256,66 @@
268
256
  `;
269
257
  }
270
258
 
259
+ /* ── Other settings · misc per-user toggles that don't fit a
260
+ dedicated section. Currently just the typing-sound effect; a
261
+ natural home for future small ambient / UX preferences (sound
262
+ cues, animations, etc.) without growing the nav for each one. */
263
+ function otherSettingsSectionHTML() {
264
+ return `
265
+ <div class="us-pane-head">
266
+ <div class="us-pane-tag">▸ Other settings</div>
267
+ <div class="us-pane-deck">small UX preferences that don't fit elsewhere. All persisted locally.</div>
268
+ </div>
269
+
270
+ <div class="us-pane-body">
271
+ <div class="us-row">
272
+ <div class="us-row-label">Typing sound</div>
273
+ <div class="us-row-field">
274
+ <div class="us-toggle-row">
275
+ <button type="button" class="us-switch" data-us-sfx-typing role="switch" aria-checked="false">
276
+ <span class="us-switch-track" aria-hidden="true">
277
+ <span class="us-switch-thumb"></span>
278
+ </span>
279
+ <span class="us-switch-label" data-us-sfx-typing-label>off</span>
280
+ </button>
281
+ <span class="us-toggle-deck">a soft keyboard click as directors stream their replies in chat. Brief generation stays silent regardless of this setting.</span>
282
+ </div>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ `;
287
+ }
288
+
289
+ function wireOtherSettingsSection() {
290
+ if (!paneEl) return;
291
+ // Typing-sound toggle · the persistence + audio context lives in
292
+ // window.boardroomTypingSfx (typing-sfx.js); this row only mirrors
293
+ // the current state and proxies clicks. Reading inside wire-up
294
+ // (not at HTML build time) means the pill always reflects the
295
+ // LATEST stored state when the section re-mounts.
296
+ const sfxBtn = paneEl.querySelector("[data-us-sfx-typing]");
297
+ const sfxLabel = paneEl.querySelector("[data-us-sfx-typing-label]");
298
+ if (sfxBtn && sfxLabel && window.boardroomTypingSfx) {
299
+ const paint = () => {
300
+ const on = window.boardroomTypingSfx.isEnabled();
301
+ sfxBtn.classList.toggle("on", on);
302
+ // role="switch" wants `aria-checked`, not `aria-pressed`.
303
+ sfxBtn.setAttribute("aria-checked", on ? "true" : "false");
304
+ sfxLabel.textContent = on ? "on" : "off";
305
+ };
306
+ paint();
307
+ sfxBtn.addEventListener("click", () => {
308
+ const next = !window.boardroomTypingSfx.isEnabled();
309
+ window.boardroomTypingSfx.setEnabled(next);
310
+ paint();
311
+ // Audible confirmation when turning ON · the click that just
312
+ // toggled also serves as the gesture the AudioContext needs,
313
+ // so this tick is actually heard.
314
+ if (next) window.boardroomTypingSfx.tick();
315
+ });
316
+ }
317
+ }
318
+
271
319
  /* ── Usage section ────────────────────────────────────────── */
272
320
  // Provider → CSS-variable color slot. Lets each model bar/swatch
273
321
  // pick up the right accent from the active theme without baking
@@ -404,11 +452,20 @@
404
452
  if (isToday) cls.push("today");
405
453
  if (isSelected) cls.push("active");
406
454
  if (total === 0) cls.push("empty");
407
- const tooltip = total > 0
408
- ? `${fmtDayLong(d.day)} · ${fmtTokens(total)} tokens`
409
- : `${fmtDayLong(d.day)} · no usage`;
455
+ // Custom hover tooltip · two lines (day + token count) rendered
456
+ // via CSS `::before` from `data-tip-day` / `data-tip-num`. We
457
+ // use `aria-label` (not `title`) so screen readers still get
458
+ // the info but the native browser tooltip with its ~500ms
459
+ // delay doesn't fight with the instant custom one.
460
+ const dayLabel = fmtDayLong(d.day);
461
+ const numLabel = total > 0 ? `${fmtTokens(total)} tokens` : "no usage";
462
+ const aria = `${dayLabel} · ${numLabel}`;
410
463
  return `
411
- <button type="button" class="${cls.join(' ')}" data-usage-day="${escape(d.day)}" title="${escape(tooltip)}">
464
+ <button type="button" class="${cls.join(' ')}"
465
+ data-usage-day="${escape(d.day)}"
466
+ data-tip-day="${escape(dayLabel)}"
467
+ data-tip-num="${escape(numLabel)}"
468
+ aria-label="${escape(aria)}">
412
469
  <span class="us-chart-stack" style="height:${heightPct.toFixed(2)}%">${segHtml}</span>
413
470
  <span class="us-chart-tick">${escape(fmtDayLabel(d.day))}</span>
414
471
  </button>
@@ -943,6 +1000,7 @@
943
1000
  <a href="#" class="us-nav-item" data-section="usage" role="tab" aria-selected="false">Usage</a>
944
1001
  <a href="#" class="us-nav-item" data-section="keys" role="tab" aria-selected="false">API Key</a>
945
1002
  <a href="#" class="us-nav-item" data-section="default" role="tab" aria-selected="false">Default Model</a>
1003
+ <a href="#" class="us-nav-item" data-section="other" role="tab" aria-selected="false">Other settings</a>
946
1004
  <div class="us-nav-foot" data-us-version aria-label="App version">
947
1005
  <span class="us-nav-foot-label">version</span>
948
1006
  <span class="us-nav-foot-value" data-us-version-value>·</span>
@@ -975,12 +1033,14 @@
975
1033
  else if (id === "usage") paneEl.innerHTML = usageSectionHTML();
976
1034
  else if (id === "keys") paneEl.innerHTML = keysSectionHTML();
977
1035
  else if (id === "default") paneEl.innerHTML = defaultModelSectionHTML();
1036
+ else if (id === "other") paneEl.innerHTML = otherSettingsSectionHTML();
978
1037
 
979
1038
  // Section-specific wiring
980
1039
  if (id === "user") wireUserSection();
981
1040
  if (id === "keys") wireKeysSection();
982
1041
  if (id === "usage") wireUsageSection();
983
1042
  if (id === "default") wireDefaultModelSection();
1043
+ if (id === "other") wireOtherSettingsSection();
984
1044
 
985
1045
  // Active rail item
986
1046
  modal.querySelectorAll(".us-nav-item").forEach((el) => {
@@ -1035,32 +1095,6 @@
1035
1095
  });
1036
1096
  introCount.textContent = introInput.value.length;
1037
1097
 
1038
- // Typing-sound toggle · the persistence + audio context lives in
1039
- // window.boardroomTypingSfx (typing-sfx.js), so this row only
1040
- // mirrors the current state and proxies clicks. Reading inside the
1041
- // wire-up call (not at HTML build time) means the pill always
1042
- // reflects the LATEST stored state when the User pane re-mounts.
1043
- const sfxBtn = paneEl.querySelector("[data-us-sfx-typing]");
1044
- const sfxLabel = paneEl.querySelector("[data-us-sfx-typing-label]");
1045
- if (sfxBtn && sfxLabel && window.boardroomTypingSfx) {
1046
- const paint = () => {
1047
- const on = window.boardroomTypingSfx.isEnabled();
1048
- sfxBtn.classList.toggle("on", on);
1049
- sfxBtn.setAttribute("aria-pressed", on ? "true" : "false");
1050
- sfxLabel.textContent = on ? "on" : "off";
1051
- };
1052
- paint();
1053
- sfxBtn.addEventListener("click", () => {
1054
- const next = !window.boardroomTypingSfx.isEnabled();
1055
- window.boardroomTypingSfx.setEnabled(next);
1056
- paint();
1057
- // Audible confirmation when turning ON · the click that just
1058
- // toggled also serves as the gesture the AudioContext needs,
1059
- // so this tick will actually be heard.
1060
- if (next) window.boardroomTypingSfx.tick();
1061
- });
1062
- }
1063
-
1064
1098
  // Regenerate avatar · same pattern as agent-profile's
1065
1099
  // regenerateProfileAvatar: pull a fresh randomSeed, persist it to
1066
1100
  // the user prefs, repaint. No counter, no name/intro composition —