agent-zero/webui/components/chat/input/chat-bar-input.html
Alessandro 0e262f7b87
Some checks are pending
Build And Publish Docker Images / plan (push) Waiting to run
Build And Publish Docker Images / build (push) Blocked by required conditions
Refresh welcome screen and composer
Rework the welcome screen around the shared new-chat composer, renewed quick actions, discovery cards, OAuth accounts, and dedicated system resources panel.

Restore static button colors and neutral surfaces, move microphone state feedback onto the icon, and keep Rubik/code-font composer behavior.

Add focused static regressions for the welcome composer, OAuth discovery panel, and speech button contract.
2026-06-22 15:12:20 +02:00

421 lines
12 KiB
HTML

<html>
<head>
<script type="module">
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">
<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(); }"
@keydown.up="$store.chatInput.historyPrev($event)" @keydown.down="$store.chatInput.historyNext($event)"
@input="$store.chatInput.handleInput($event)"
@keyup="$store.chatInput._syncCaretFromEvent($event)"
@click="$store.chatInput._syncCaretFromEvent($event)"
@select="$store.chatInput._syncCaretFromEvent($event)"
:class="{ 'progress-active': $store.chatInput.progressActive, 'is-code-context': $store.chatInput.isCodeContext }"
x-model="$store.chatInput.message"></textarea>
<div id="chat-input-progress-placeholder" x-show="$store.chatInput.showProgressPlaceholder"
x-html="$store.chatInput.progressPlaceholderHtml"
:class="{ 'progress-active': $store.chatInput.progressActive }" aria-hidden="true" style="display: none;">
</div>
<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>
</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: 0.72rem;
width: 100%;
min-height: 4.25rem;
padding: 0.42rem 0.52rem 0.42rem 0.72rem;
border: 1px solid color-mix(in srgb, var(--color-border) 72%, transparent);
border-radius: 16px;
background: color-mix(in srgb, var(--color-panel) 72%, var(--color-background) 28%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.035),
0 18px 46px rgba(0, 0, 0, 0.18);
white-space: nowrap;
transition: border-color 0.16s ease, background-color 0.16s ease, box-shadow 0.16s ease;
}
.input-row:focus-within {
border-color: color-mix(in srgb, var(--color-border) 88%, var(--color-text) 12%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.045),
0 22px 54px rgba(0, 0, 0, 0.22);
}
.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.82;
transition: opacity 0.16s ease, background-color 0.16s ease, color 0.16s ease;
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
padding: 0;
border: none;
border-radius: 10px;
background: transparent;
}
.chat-more-trigger:hover {
opacity: 1;
background: color-mix(in srgb, var(--color-border) 36%, transparent);
}
.chat-more-trigger:active {
opacity: 0.5;
}
.chat-more-trigger .material-symbols-outlined {
font-size: 1.7rem;
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: color-mix(in srgb, var(--color-panel) 90%, black 10%);
border: 1px solid var(--color-border);
border-radius: 12px;
box-shadow: 0 16px 38px rgba(0, 0, 0, 0.3);
z-index: 1050;
padding: 0.3rem;
}
.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%;
min-width: 0;
display: flex;
align-items: center;
}
#chat-input {
background-color: transparent;
border: 0;
border-radius: 0;
color: var(--color-text);
flex-grow: 1;
font-family: var(--font-family-main, "Rubik", Arial, Helvetica, sans-serif);
font-optical-sizing: auto;
-webkit-font-optical-sizing: auto;
font-size: 1rem;
line-height: 1.45;
max-height: 30vh;
min-height: 2.8rem;
width: 100%;
padding: 0.68rem 2.2rem 0.68rem 0.1rem;
margin: 0;
overflow-y: auto;
scroll-behavior: smooth;
resize: none;
align-content: center;
background-clip: border-box;
outline: none;
transition: color 0.16s ease, background-color 0.16s ease;
-webkit-transition: color 0.16s ease, background-color 0.16s ease;
}
#chat-input.is-code-context {
font-family: var(--font-family-code, "Roboto Mono", monospace);
font-size: 0.94rem;
align-content: start;
}
#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: none;
background-color: transparent;
}
#chat-input::placeholder {
color: color-mix(in srgb, var(--color-text) 62%, transparent);
opacity: 0.78;
transition: color 0.16s 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);
}
#chat-input-progress-placeholder {
position: absolute;
top: 0.74rem;
left: 0.12rem;
right: 46px;
color: var(--color-text-muted);
opacity: 0.7;
font-family: var(--font-family-code, "Roboto Mono", monospace);
font-size: 0.9rem;
line-height: 1.45;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
pointer-events: none;
display: flex;
align-items: center;
gap: 0.35rem;
}
#chat-input-progress-placeholder.progress-active {
animation: placeholder-pulse 2s ease-in-out infinite;
}
#chat-input-progress-placeholder .chat-input-progress-cue {
color: var(--color-text-muted);
}
#chat-input-progress-placeholder .chat-input-progress-icon {
font-size: 1.15rem;
line-height: 1;
color: var(--color-highlight);
vertical-align: -0.18rem;
}
#expand-button {
position: absolute;
top: 12px;
right: 0;
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: 0.58rem;
padding-left: 0;
line-height: 1;
display: -webkit-flex;
display: flex;
align-items: center;
}
.chat-button {
border: 1px solid transparent;
border-radius: 50%;
color: #fff;
cursor: pointer;
font-size: var(--font-size-normal);
height: 3.15rem;
width: 3.15rem;
margin: 0;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
flex-grow: 0;
min-width: 3.15rem;
-webkit-transition: background-color var(--transition-speed), border-color 0.16s ease, box-shadow 0.16s ease, filter 0.12s ease-in-out, transform 0.12s ease;
transition: background-color var(--transition-speed), border-color 0.16s ease, box-shadow 0.16s ease, filter 0.12s ease-in-out, transform 0.12s ease;
}
#send-button {
order: 2;
border-radius: 12px;
background-color: #4248f1;
box-shadow: none;
}
#send-button.send-queue {
background-color: #e67e22;
box-shadow: none;
}
#send-button:hover {
background-color: #353bc5;
filter: none;
box-shadow: none;
}
#send-button.send-queue:hover {
background-color: #d35400;
filter: none;
}
#send-button:active {
background-color: #2b309c;
transform: translateY(1px) scale(0.98);
filter: brightness(0.96);
}
.chat-button svg {
width: 1.5rem;
height: 1.5rem;
}
#send-button .material-symbols-outlined {
font-size: 1.78rem;
}
/* Responsive tweaks */
@media (max-width: 640px) {
#chat-input {
min-height: 4.2rem;
align-content: center;
}
#chat-buttons-wrapper {
display: flex;
gap: 0.42rem;
padding: 0 !important;
width: auto;
flex-wrap: nowrap;
-webkit-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.input-row {
gap: 0.42rem;
min-height: 4rem;
padding: 0.36rem 0.42rem 0.36rem 0.48rem;
}
.chat-more-trigger {
width: 2.15rem;
height: 2.15rem;
}
.chat-button {
width: 2.75rem;
height: 2.75rem;
min-width: 2.75rem;
}
}
@media (min-width: 768px) {
#chat-buttons-wrapper {
flex-wrap: nowrap;
-webkit-flex-wrap: nowrap;
flex-wrap: nowrap;
}
}
</style>
</body>
</html>