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:
parent
f064c93197
commit
7b1210b5d1
41 changed files with 1565 additions and 1143 deletions
|
|
@ -147,28 +147,23 @@
|
|||
transform: none;
|
||||
}
|
||||
|
||||
/* ── 녹음 캡슐 — 앱 recording-tip/style.css 와 같은 값 ─── */
|
||||
/* ── 녹음 캡슐 — 앱 popups/recording-tip/style.css(v4, 2026-09-28)와 같은 값 ───
|
||||
* 판 모양(radius 10)·단색 막대·입력 없으면 막대 정지·처리 중 무한 막대·완료 "입력함".
|
||||
* 색은 앱 다크 테마 원시값(packages/ui/src/theme-raw.ts)과 같다 — 값이 바뀌면 함께 고친다. */
|
||||
.capsule {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(15, 17, 22, 0.88);
|
||||
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(28px);
|
||||
-webkit-backdrop-filter: blur(28px);
|
||||
}
|
||||
.capsule:has(.capsule-partial) {
|
||||
border-radius: 18px;
|
||||
}
|
||||
.capsule-recording {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
min-width: 160px;
|
||||
max-width: 320px;
|
||||
min-width: 168px;
|
||||
max-width: 300px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(148, 180, 255, 0.12);
|
||||
background: #111a30;
|
||||
box-shadow: 0 12px 32px rgba(3, 7, 18, 0.55);
|
||||
}
|
||||
.capsule.is-listening {
|
||||
border-color: rgba(148, 180, 255, 0.2);
|
||||
}
|
||||
.capsule-row {
|
||||
display: flex;
|
||||
|
|
@ -179,66 +174,88 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
height: 28px;
|
||||
height: 22px;
|
||||
}
|
||||
.capsule-bar {
|
||||
display: block;
|
||||
width: 3px;
|
||||
min-height: 3px;
|
||||
min-height: 2px;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
border-radius: 2px;
|
||||
background: #3b82f6;
|
||||
transition: height 80ms ease-out;
|
||||
}
|
||||
.capsule-bar:nth-child(1) { background: #93c5fd; opacity: 0.85; }
|
||||
.capsule-bar:nth-child(2) { background: #60a5fa; opacity: 0.9; }
|
||||
.capsule-bar:nth-child(3) { background: #4f8dfa; opacity: 0.95; }
|
||||
.capsule-bar:nth-child(4) { background: #3b82f6; }
|
||||
.capsule-bar:nth-child(5) { background: #3b82f6; }
|
||||
.capsule-bar:nth-child(6) { background: #5b75f7; }
|
||||
.capsule-bar:nth-child(7) { background: #6e71f7; opacity: 0.95; }
|
||||
.capsule-bar:nth-child(8) { background: #818cf8; opacity: 0.9; }
|
||||
.capsule-bar:nth-child(9) { background: #a78bfa; opacity: 0.85; }
|
||||
.capsule.is-thinking .capsule-bar {
|
||||
background: #7e8eb0;
|
||||
}
|
||||
.capsule-duration {
|
||||
min-width: 34px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
min-width: 32px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.02em;
|
||||
color: #f4f4f5;
|
||||
}
|
||||
.capsule-partial {
|
||||
display: -webkit-box;
|
||||
max-height: 38px;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding-top: 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: #f4f4f5;
|
||||
}
|
||||
.capsule-progress {
|
||||
display: block;
|
||||
width: 120px;
|
||||
height: 4px;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.capsule-progress-bar {
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
border-radius: 999px;
|
||||
background: #3b82f6;
|
||||
transition: width 100ms linear;
|
||||
color: #eef2fb;
|
||||
}
|
||||
.capsule-thinking {
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #a1a1aa;
|
||||
color: #93a4c8;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.capsule-cancel {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 18px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid rgba(148, 180, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
color: #7e8eb0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.capsule-progress {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 2px;
|
||||
overflow: hidden;
|
||||
border-radius: 1px;
|
||||
background: rgba(148, 180, 255, 0.12);
|
||||
}
|
||||
.capsule-progress-bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 36%;
|
||||
border-radius: 1px;
|
||||
background: #3b82f6;
|
||||
animation: capsule-indeterminate 1.1s cubic-bezier(0.22, 1, 0.36, 1) infinite;
|
||||
}
|
||||
@keyframes capsule-indeterminate {
|
||||
from { left: -36%; }
|
||||
to { left: 100%; }
|
||||
}
|
||||
.capsule-partial {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
max-height: 38px;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid rgba(148, 180, 255, 0.07);
|
||||
padding-top: 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1.55;
|
||||
color: #eef2fb;
|
||||
}
|
||||
.capsule.is-thinking .capsule-partial {
|
||||
color: #7e8eb0;
|
||||
}
|
||||
.capsule-done {
|
||||
font-size: 12px;
|
||||
color: #eef2fb;
|
||||
}
|
||||
.capsule-done-icon {
|
||||
color: #34d399;
|
||||
}
|
||||
|
||||
/* ── Grid Background Pattern (히어로) ─────────────────── */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue