agent-zero/webui/components/chat/input/chat-bar-input.html
TerminallyLazy a2547f12a1 Add model config presets and ignore agent artifacts
- Add model switcher component for chat input with progress display
- Enhance model config store with active preset/model retrieval
- Show agent progress as ghost text in chat input placeholder
- Add agent artifact patterns to .gitignore
2026-03-28 11:10:52 -04:00

210 lines
9.3 KiB
HTML

<html>
<head>
<script type="module">
import { store as speechStore } from "/components/chat/speech/speech-store.js";
import { store as fullScreenStore } from "/components/modals/full-screen-input/full-screen-store.js";
import { store as messageQueueStore } from "/components/chat/message-queue/message-queue-store.js";
import { store as chatInputStore } from "/components/chat/input/input-store.js";
</script>
</head>
<body>
<div x-data>
<x-extension id="chat-input-box-start"></x-extension>
<div class="input-row">
<!-- More actions (+): opens upward; content lives in bottom-actions.html -->
<div
class="attachment-wrapper chat-more-dropdown"
@click.outside="$store.chatInput.closeChatMoreMenu()"
@keydown.escape.window="$store.chatInput.closeChatMoreMenu()"
>
<button
type="button"
class="chat-more-trigger"
@click.stop="$store.chatInput.toggleChatMoreMenu()"
:aria-expanded="$store.chatInput.chatMoreMenuOpen.toString()"
aria-label="More actions"
>
<span class="material-symbols-outlined" aria-hidden="true">add</span>
</button>
<div
class="chat-more-panel"
x-show="$store.chatInput.chatMoreMenuOpen"
x-transition
style="display: none;"
>
<x-component path="chat/input/bottom-actions.html"></x-component>
</div>
</div>
<!-- Container for textarea and expand button -->
<div id="chat-input-container" style="position: relative;">
<textarea id="chat-input" :placeholder="$store.chatInput.inputPlaceholder" rows="1"
@keydown.enter="if (!$event.shiftKey && !$event.isComposing && $event.keyCode !== 229) { $event.preventDefault(); $store.chatInput.sendMessage(); }"
@input="$store.chatInput.adjustTextareaHeight()"
x-model="$store.chatInput.message"></textarea>
<button id="expand-button" @click="$store.fullScreenInputModal.openModal()" aria-label="Expand input">
<span class="material-symbols-outlined" aria-hidden="true">open_in_full</span>
</button>
</div>
<div id="chat-buttons-wrapper">
<!-- Send button -->
<button class="chat-button" id="send-button" aria-label="Send message"
@click="$store.chatInput.sendMessage()"
:class="$store.chatInput.sendButtonClass"
:title="$store.chatInput.sendButtonTitle">
<span class="material-symbols-outlined" x-text="$store.chatInput.sendButtonIcon"></span>
</button>
<!-- Microphone button -->
<button class="chat-button mic-inactive" id="microphone-button" aria-label="Start/Stop recording"
@click="$store.speech.handleMicrophoneClick()" x-effect="$store.speech.updateMicrophoneButtonUI()">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 18" fill="currentColor">
<path d="m8,12c1.66,0,3-1.34,3-3V3c0-1.66-1.34-3-3-3s-3,1.34-3,3v6c0,1.66,1.34,3,3,3Zm-1,1.9c-2.7-.4-4.8-2.6-5-5.4H0c.2,3.8,3.1,6.9,7,7.5v2h2v-2c3.9-.6,6.8-3.7,7-7.5h-2c-.2,2.8-2.3,5-5,5.4h-2Z" />
</svg>
</button>
</div>
</div>
<!-- Full Screen Input Modal -->
<x-component path="modals/full-screen-input/full-screen-input.html"></x-component>
<x-extension id="chat-input-box-end"></x-extension>
</div>
<style>
/* Layout rows */
.input-row { display: flex; align-items: center; gap: var(--spacing-xs); width: 100%; white-space: nowrap; }
.attachment-wrapper { position: relative; flex-shrink: 0; }
/* Composer + menu: custom panel (edit here; not shared with file-browser dropdown) */
.chat-more-dropdown { z-index: 1; }
.chat-more-trigger {
cursor: pointer;
color: var(--color-text);
opacity: 0.75;
transition: opacity 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
}
.chat-more-trigger:hover { opacity: 1; }
.chat-more-trigger:active { opacity: 0.5; }
.chat-more-trigger .material-symbols-outlined {
font-size: 1.5rem;
line-height: 1;
}
.chat-more-panel {
position: absolute;
left: 0;
bottom: 100%;
margin-bottom: 0.25rem;
min-width: 11rem;
max-width: min(18rem, 92vw);
max-height: min(70vh, 20rem);
overflow-x: hidden;
overflow-y: auto;
background-color: var(--color-panel);
border: 1px solid var(--color-border);
border-radius: 0.4rem;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
z-index: 1050;
padding: 0.2rem 0;
}
.light-mode .chat-more-panel {
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}
/* Text input */
#chat-input-container {
position: relative;
width: 100%;
}
#chat-input {
background-color: var(--color-input);
border: 1px solid var(--color-border);
border-radius: 8px;
color: var(--color-text);
flex-grow: 1;
font-family: "Roboto Mono", monospace;
font-optical-sizing: auto;
-webkit-font-optical-sizing: auto;
font-size: 0.9rem;
max-height: 60vh;
min-height: 3.05rem;
width: 100%;
padding: 0.48rem 40px var(--spacing-sm) var(--spacing-sm);
margin-right: var(--spacing-xs);
overflow-y: auto;
scroll-behavior: smooth;
resize: none;
align-content: start;
background-clip: border-box;
border: 6px solid transparent;
outline: 1px solid var(--color-border);
transition: all 0.3s ease;
-webkit-transition: all 0.3s ease;
}
#chat-input::-webkit-scrollbar { width: 6px; height: 6px; }
#chat-input::-webkit-scrollbar-track { background: transparent; margin: 4px 0; border-radius: 6px; }
#chat-input::-webkit-scrollbar-thumb { background-color: rgba(155,155,155,0.5); border-radius: 6px; -webkit-transition: background-color 0.2s ease; transition: background-color 0.2s ease; }
#chat-input::-webkit-scrollbar-thumb:hover { background-color: rgba(155,155,155,0.7); }
#chat-input:focus { outline: 0.05rem solid rgba(155,155,155,0.5); font-size: 0.955rem; padding-top: 0.45rem; background-color: var(--color-input-focus); }
#chat-input::placeholder { color: var(--color-text-muted); opacity: 0.7; transition: color 0.3s ease; }
/* Progress ghost text animation — gentle pulse on placeholder */
#chat-input.progress-active::placeholder {
animation: placeholder-pulse 2s ease-in-out infinite;
}
@keyframes placeholder-pulse {
0%, 100% { opacity: 0.45; }
50% { opacity: 0.85; }
}
#chat-input.progress-active {
border-color: color-mix(in srgb, var(--color-highlight) 20%, transparent);
outline-color: color-mix(in srgb, var(--color-highlight) 15%, transparent);
}
#expand-button {
position: absolute;
top: 12px;
right: 6px;
background: transparent;
border: none;
cursor: pointer;
transform: scale(0.8);
font-size: 1.2rem;
color: var(--color-text);
opacity: 0.2;
transition: opacity 0.2s;
}
#expand-button:hover { opacity: 0.7; }
#expand-button:active { opacity: 1; }
#expand-button .material-symbols-outlined { display: block; font-size: 1.3rem; line-height: 1; }
/* Chat buttons (Send/Mic) */
#chat-buttons-wrapper { gap: var(--spacing-xs); padding-left: var(--spacing-xs); line-height: 0.5rem; display: -webkit-flex; display: flex; }
.chat-button { border: none; border-radius: 50%; color: var(--color-background); cursor: pointer; font-size: var(--font-size-normal); height: 2.525rem; width: 2.525rem; margin: 0 0.18rem 0 0 var(--spacing-xs); display: -webkit-flex; display: flex; align-items: center; justify-content: center; flex-shrink: 0; flex-grow: 0; min-width: 2.525rem; -webkit-transition: background-color var(--transition-speed), box-shadow 0.12s ease-in-out, filter 0.12s ease-in-out; transition: background-color var(--transition-speed), box-shadow 0.12s ease-in-out, filter 0.12s ease-in-out; }
#send-button { background-color: #4248f1; }
#send-button.send-queue { background-color: #e67e22; }
#send-button:hover { background-color: #353bc5; box-shadow: 0 0 0 1px rgba(255,255,255,0.08), 0 6px 14px rgba(0,0,0,0.2); }
#send-button.send-queue:hover { background-color: #d35400; }
#send-button:active { background-color: #2b309c; filter: brightness(0.96); }
.chat-button svg { width: 1.5rem; height: 1.5rem; }
#send-button .material-symbols-outlined { font-size: 1.5rem; }
/* Responsive tweaks */
@media (max-width: 640px) {
#chat-input { min-height: 5.3rem; align-content: start; }
#chat-buttons-wrapper { display: flex; gap: var(--spacing-xs); padding: 0 0 0 var(--spacing-sm) !important; width: 3.5rem; flex-wrap: wrap; -webkit-transition: all 0.3s ease; transition: all 0.3s ease; }
}
@media (min-width: 768px) { #chat-buttons-wrapper { flex-wrap: nowrap; -webkit-flex-wrap: nowrap; flex-wrap: nowrap; } }
</style>
</body>
</html>