fix(ui): move prompt mic beside expand control
This commit is contained in:
@@ -543,10 +543,54 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
<div class="prompt-nav-buttons">
|
<div class="prompt-nav-buttons">
|
||||||
<ExpandButton
|
<div class="prompt-nav-top-row">
|
||||||
expandState={expandState}
|
<Show when={showVoiceInput()}>
|
||||||
onToggleExpand={handleExpandToggle}
|
<button
|
||||||
/>
|
type="button"
|
||||||
|
class={`prompt-voice-button prompt-nav-voice-button ${voiceInput.isRecording() ? "is-recording" : ""}`}
|
||||||
|
onPointerDown={(event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
beginVoicePress(event)
|
||||||
|
}}
|
||||||
|
onPointerUp={(event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
endVoicePress()
|
||||||
|
}}
|
||||||
|
onPointerCancel={() => endVoicePress()}
|
||||||
|
onLostPointerCapture={() => endVoicePress()}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.repeat) return
|
||||||
|
if (event.key !== " " && event.key !== "Enter") return
|
||||||
|
event.preventDefault()
|
||||||
|
beginVoicePress(event)
|
||||||
|
}}
|
||||||
|
onKeyUp={(event) => {
|
||||||
|
if (event.key !== " " && event.key !== "Enter") return
|
||||||
|
event.preventDefault()
|
||||||
|
endVoicePress()
|
||||||
|
}}
|
||||||
|
onBlur={() => endVoicePress()}
|
||||||
|
disabled={!voiceInput.isRecording() && (props.disabled || voiceInput.isTranscribing() || !voiceInput.canUseVoiceInput())}
|
||||||
|
aria-label={voiceInput.buttonTitle()}
|
||||||
|
title={voiceInput.buttonTitle()}
|
||||||
|
>
|
||||||
|
<Show
|
||||||
|
when={voiceInput.isRecording()}
|
||||||
|
fallback={
|
||||||
|
<Show when={voiceInput.isTranscribing()} fallback={<Mic class="h-4 w-4" aria-hidden="true" />}>
|
||||||
|
<Loader2 class="h-4 w-4 animate-spin" aria-hidden="true" />
|
||||||
|
</Show>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span class="prompt-voice-timer">{formatVoiceTimer(voiceInput.elapsedMs())}</span>
|
||||||
|
</Show>
|
||||||
|
</button>
|
||||||
|
</Show>
|
||||||
|
<ExpandButton
|
||||||
|
expandState={expandState}
|
||||||
|
onToggleExpand={handleExpandToggle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Show when={hasHistory()}>
|
<Show when={hasHistory()}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -634,48 +678,6 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="prompt-input-actions">
|
<div class="prompt-input-actions">
|
||||||
<Show when={showVoiceInput()}>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class={`prompt-voice-button ${voiceInput.isRecording() ? "is-recording" : ""}`}
|
|
||||||
onPointerDown={(event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
beginVoicePress(event)
|
|
||||||
}}
|
|
||||||
onPointerUp={(event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
endVoicePress()
|
|
||||||
}}
|
|
||||||
onPointerCancel={() => endVoicePress()}
|
|
||||||
onLostPointerCapture={() => endVoicePress()}
|
|
||||||
onKeyDown={(event) => {
|
|
||||||
if (event.repeat) return
|
|
||||||
if (event.key !== " " && event.key !== "Enter") return
|
|
||||||
event.preventDefault()
|
|
||||||
beginVoicePress(event)
|
|
||||||
}}
|
|
||||||
onKeyUp={(event) => {
|
|
||||||
if (event.key !== " " && event.key !== "Enter") return
|
|
||||||
event.preventDefault()
|
|
||||||
endVoicePress()
|
|
||||||
}}
|
|
||||||
onBlur={() => endVoicePress()}
|
|
||||||
disabled={!voiceInput.isRecording() && (props.disabled || voiceInput.isTranscribing() || !voiceInput.canUseVoiceInput())}
|
|
||||||
aria-label={voiceInput.buttonTitle()}
|
|
||||||
title={voiceInput.buttonTitle()}
|
|
||||||
>
|
|
||||||
<Show
|
|
||||||
when={voiceInput.isRecording()}
|
|
||||||
fallback={
|
|
||||||
<Show when={voiceInput.isTranscribing()} fallback={<Mic class="h-4 w-4" aria-hidden="true" />}>
|
|
||||||
<Loader2 class="h-4 w-4 animate-spin" aria-hidden="true" />
|
|
||||||
</Show>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span class="prompt-voice-timer">{formatVoiceTimer(voiceInput.elapsedMs())}</span>
|
|
||||||
</Show>
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="stop-button"
|
class="stop-button"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
.prompt-input {
|
.prompt-input {
|
||||||
@apply w-full pt-2.5 border text-sm resize-none outline-none transition-colors;
|
@apply w-full pt-2.5 border text-sm resize-none outline-none transition-colors;
|
||||||
padding-inline-start: 0.75rem;
|
padding-inline-start: 0.75rem;
|
||||||
padding-inline-end: 2.5rem;
|
padding-inline-end: 5.5rem;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
background-color: var(--surface-base);
|
background-color: var(--surface-base);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
@@ -91,11 +91,19 @@
|
|||||||
bottom: 0.25rem;
|
bottom: 0.25rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
gap: 0.125rem;
|
gap: 0.125rem;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prompt-nav-top-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.prompt-expand-button,
|
.prompt-expand-button,
|
||||||
.prompt-history-button {
|
.prompt-history-button {
|
||||||
@apply w-7 h-7 flex items-center justify-center rounded-md;
|
@apply w-7 h-7 flex items-center justify-center rounded-md;
|
||||||
@@ -200,6 +208,18 @@
|
|||||||
color: var(--button-danger-text, var(--text-inverted, #ffffff));
|
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 {
|
.prompt-voice-button:disabled {
|
||||||
@apply opacity-50 cursor-not-allowed;
|
@apply opacity-50 cursor-not-allowed;
|
||||||
}
|
}
|
||||||
@@ -377,7 +397,7 @@
|
|||||||
.prompt-input {
|
.prompt-input {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
padding-inline-end: 2.5rem;
|
padding-inline-end: 5.5rem;
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user