feat(desktop): honest, unified dictation popups with Esc to cancel

Wave 3 of the 2026-09-28 design overhaul.

- Esc (no modifiers) cancels an in-progress dictation, recording or
  processing: VoiceModeService.requestEscape() queues the dead 'escape'
  action. Clicking the capsule cancels only while recording, so a stray
  click during processing no longer throws the text away.
- Errors show in the user's language: bootstrap now passes error.code to
  the tip (the translated branch never ran), and one core classifier
  (voice-error-message) feeds both the tip and the main-window alert.
- Capsule: bars stay flat without input (no fake "alive" wobble before the
  mic opens), an indeterminate bar replaces the made-up percentage, the
  partial transcript stays visible while processing, an Esc hint, and a
  brief "Inserted" state so success is visible.
- All six popups share popups/_shared (Pretendard, one panel radius,
  selection, kbd hints, reduced motion). History/command popups get
  titles, listbox roles and window sizes from popup-list-geometry (empty
  states were clipped); the command popup's "0" key is registered;
  result popup explains why it appeared and can be closed; captions keep
  a theme-independent dark backing on purpose.
- Popup themes follow the OS when set to system and the document lang
  follows the app language.
- Site hero demo mirrors the new capsule (done state, indeterminate bar,
  Esc hint; 10 locales).
This commit is contained in:
Yun Chan 2026-09-28 20:46:24 +09:00
parent f064c93197
commit 7b1210b5d1
41 changed files with 1565 additions and 1143 deletions

View file

@ -8,12 +8,14 @@
</head>
<body>
<div id="root">
<div id="container" class="history-popup">
<div id="items" class="items"></div>
<div class="hints">
<span data-i18n="hintsSelectEn">↑↓ Select</span>
<span data-i18n="hintsPaste">⏎ Paste</span>
<span data-i18n="hintsClose">ESC ×</span>
<div id="container" class="list-popup d3-panel">
<div id="title" class="list-title" data-i18n="historyTitle"></div>
<div id="items" class="list-items" role="listbox" aria-labelledby="title"></div>
<div class="d3-hints" aria-hidden="true">
<span><kbd>↑</kbd><kbd>↓</kbd><b data-i18n="hintMove"></b></span>
<span><kbd>Enter</kbd><b data-i18n="hintPaste"></b></span>
<span><kbd>1–9</kbd><b data-i18n="hintPick"></b></span>
<span><kbd>Esc</kbd><b data-i18n="hintClose"></b></span>
</div>
</div>
</div>