Skip to content

Commit 8cf5413

Browse files
Indicate thinking process
1 parent bb8dc88 commit 8cf5413

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

src/styles.css

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ body {
138138
}
139139
.btn:disabled { opacity: .6; cursor: not-allowed; }
140140

141+
.spinner {
142+
width: 14px; height: 14px;
143+
border: 2px solid color-mix(in oklab, var(--text), transparent 70%);
144+
border-top-color: var(--accent);
145+
border-radius: 50%;
146+
animation: spin .8s linear infinite;
147+
}
148+
149+
@keyframes spin { to { transform: rotate(360deg); } }
150+
141151
.select, .progress {
142152
width: 100%;
143153
background: var(--panel-2);
@@ -160,6 +170,28 @@ body {
160170

161171
.stat { font-variant-numeric: tabular-nums; }
162172

173+
.thinking-pill {
174+
align-self: start;
175+
margin: 6px 16px 0 16px;
176+
display: inline-flex; align-items: center; gap: 8px;
177+
background: var(--panel-2);
178+
border: 1px solid var(--border);
179+
color: var(--muted);
180+
padding: 6px 10px; border-radius: 999px;
181+
font-size: 12px;
182+
}
183+
184+
.dots::after {
185+
content: '…';
186+
animation: blinkdots 1.4s steps(3, end) infinite;
187+
}
188+
@keyframes blinkdots {
189+
0% { content: ''; }
190+
33% { content: '.'; }
191+
66% { content: '..'; }
192+
100% { content: '...'; }
193+
}
194+
163195
@media (max-width: 900px) {
164196
.container { grid-template-columns: 1fr; }
165197
}

src/ui/App.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ export default function App() {
104104
</aside>
105105

106106
<section className="content">
107+
{engine.streaming && (
108+
<div className="thinking-pill" aria-live="polite">
109+
<span className="spinner" />
110+
<span>Assistant is thinking</span>
111+
</div>
112+
)}
107113
<div className="chat">
108114
<ChatPanel
109115
messages={chat.items}
@@ -143,7 +149,7 @@ export default function App() {
143149
autoComplete="off"
144150
/>
145151
<button className="btn" disabled={engine.state !== 'ready' || engine.streaming}>
146-
Send
152+
{engine.streaming ? <><span className="spinner"/> Thinking…</> : 'Send'}
147153
</button>
148154
</form>
149155
</section>

src/ui/chat/ChatPanel.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ export const ChatPanel: FC<{ messages: ChatMessage[]; streaming?: boolean }>
1919
</div>
2020
</div>
2121
))}
22+
{streaming && (messages.length === 0 || messages[messages.length - 1]?.role !== 'assistant') && (
23+
<div className="msg">
24+
<div className="avatar">A</div>
25+
<div className="bubble">Thinking<span className="dots"/></div>
26+
</div>
27+
)}
2228
{messages.length === 0 && (
2329
<div className="muted">Start a conversation by asking a question.</div>
2430
)}
@@ -29,4 +35,3 @@ export const ChatPanel: FC<{ messages: ChatMessage[]; streaming?: boolean }>
2935
function Blink() {
3036
return <span style={{opacity:.6}}>|</span>;
3137
}
32-

0 commit comments

Comments
 (0)