QuantumAI / frontend /src /components /InputBar.js
Abhroneel's picture
Stage 2
cb58e5f
Raw
History Blame Contribute Delete
4.12 kB
import React, { useState, useRef, useEffect } from 'react';
import './InputBar.css';
export default function InputBar({ onSend, isLoading, config, setConfig, models }) {
const [value, setValue] = useState('');
const textareaRef = useRef(null);
useEffect(() => {
if (!isLoading && textareaRef.current) {
textareaRef.current.focus();
}
}, [isLoading]);
function autoResize() {
const ta = textareaRef.current;
if (!ta) return;
ta.style.height = 'auto';
ta.style.height = Math.min(ta.scrollHeight, 160) + 'px';
}
function handleChange(e) {
setValue(e.target.value);
autoResize();
}
function handleKeyDown(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSend();
}
}
function handleSend() {
const trimmed = value.trim();
if (!trimmed || isLoading) return;
onSend(trimmed);
setValue('');
if (textareaRef.current) {
textareaRef.current.style.height = 'auto';
}
}
const canSend = value.trim().length > 0 && !isLoading;
return (
<div className="input-bar">
<div className="input-bar__inner">
<div className="input-bar__toolbar">
<div className="input-bar__toolbar-left">
<select
className="input-bar__select"
value={config.model}
onChange={e => setConfig(c => ({ ...c, model: e.target.value }))}
>
{models.map(m => (
<option key={m.id} value={m.id}>{m.label}</option>
))}
</select>
<div className="input-bar__divider" />
<div className="input-bar__param">
<span className="input-bar__param-label">Temp</span>
<input
type="number"
className="input-bar__param-input"
value={config.temperature}
min="0"
max="1"
step="0.1"
onChange={e => setConfig(c => ({ ...c, temperature: parseFloat(e.target.value) || 0 }))}
/>
</div>
<div className="input-bar__divider" />
<div className="input-bar__param">
<span className="input-bar__param-label">Chunks</span>
<input
type="number"
className="input-bar__param-input"
value={config.topK}
min="1"
max="6"
step="1"
onChange={e => setConfig(c => ({ ...c, topK: parseInt(e.target.value) || 1 }))}
/>
</div>
</div>
<span className="input-bar__hint">⌵ Enter to send · Shift+Enter for newline</span>
</div>
<div className="input-bar__compose">
<textarea
ref={textareaRef}
className="input-bar__textarea"
value={value}
onChange={handleChange}
onKeyDown={handleKeyDown}
placeholder="Ask about quantum mechanics, entanglement, Bell's theorem…"
rows={1}
disabled={isLoading}
/>
<button
className={`input-bar__send ${canSend ? 'input-bar__send--active' : ''} ${isLoading ? 'input-bar__send--loading' : ''}`}
onClick={handleSend}
disabled={!canSend}
aria-label="Send"
>
{isLoading ? (
<svg className="input-bar__spinner" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
<path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" />
</svg>
) : (
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<line x1="22" y1="2" x2="11" y2="13" />
<polygon points="22 2 15 22 11 13 2 9 22 2" />
</svg>
)}
</button>
</div>
</div>
</div>
);
}