feat(speech): add prompt voice input (#249)
## Summary - add server-backed speech capabilities and transcription endpoints plus UI settings for speech configuration - add push-to-talk prompt voice input with microphone controls, transcription insertion, and browser capability gating - keep prompt controls aligned by restoring right-side nav placement and moving the mic beside the expand control
This commit is contained in:
@@ -36,8 +36,8 @@
|
||||
|
||||
.prompt-input {
|
||||
@apply w-full pt-2.5 border text-sm resize-none outline-none transition-colors;
|
||||
padding-inline-start: 2.5rem;
|
||||
padding-inline-end: 0.75rem;
|
||||
padding-inline-start: 0.75rem;
|
||||
padding-inline-end: 5.5rem;
|
||||
font-family: inherit;
|
||||
background-color: var(--surface-base);
|
||||
color: var(--text-primary);
|
||||
@@ -83,21 +83,27 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Navigation buttons container (expand, prev, next).
|
||||
Intentionally at inline-start (left in LTR, right in RTL) so buttons never overlap
|
||||
the scrollbar, which browsers always place at inline-end. */
|
||||
/* Navigation buttons container (expand, prev, next). */
|
||||
.prompt-nav-buttons {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
inset-inline-start: 0.25rem;
|
||||
inset-inline-end: 0.25rem;
|
||||
bottom: 0.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-start;
|
||||
gap: 0.125rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.prompt-nav-top-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 0.125rem;
|
||||
}
|
||||
|
||||
.prompt-expand-button,
|
||||
.prompt-history-button {
|
||||
@apply w-7 h-7 flex items-center justify-center rounded-md;
|
||||
@@ -179,6 +185,53 @@
|
||||
color: var(--button-danger-text, var(--text-inverted, #ffffff));
|
||||
}
|
||||
|
||||
.prompt-voice-button {
|
||||
@apply h-10 rounded-md border-none cursor-pointer flex items-center justify-center transition-all flex-shrink-0;
|
||||
min-width: 2.5rem;
|
||||
background-color: color-mix(in oklab, var(--surface-secondary) 82%, var(--surface-base));
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.prompt-voice-button:hover:not(:disabled) {
|
||||
color: var(--text-primary);
|
||||
background-color: color-mix(in oklab, var(--accent-primary) 12%, var(--surface-secondary));
|
||||
@apply scale-105;
|
||||
}
|
||||
|
||||
.prompt-voice-button:active:not(:disabled) {
|
||||
@apply scale-95;
|
||||
}
|
||||
|
||||
.prompt-voice-button.is-recording {
|
||||
min-width: 3.5rem;
|
||||
background-color: color-mix(in oklab, var(--button-danger-bg, rgba(239, 68, 68, 0.85)) 88%, white 12%);
|
||||
color: var(--button-danger-text, var(--text-inverted, #ffffff));
|
||||
}
|
||||
|
||||
.prompt-nav-voice-button {
|
||||
min-width: 1.75rem;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.prompt-nav-voice-button.is-recording {
|
||||
min-width: 3.5rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.prompt-voice-button:disabled {
|
||||
@apply opacity-50 cursor-not-allowed;
|
||||
}
|
||||
|
||||
.prompt-voice-timer {
|
||||
font-size: 0.68rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
.stop-button:hover:not(:disabled) {
|
||||
background-color: var(--button-danger-hover-bg, rgba(239, 68, 68, 0.9));
|
||||
@apply opacity-95 scale-105;
|
||||
@@ -344,7 +397,7 @@
|
||||
.prompt-input {
|
||||
min-height: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding-inline-start: 2.5rem; /* preserve space for nav buttons */
|
||||
padding-inline-end: 5.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user