console: GitHub 风格(Primer)

保持一页式控制台排版与全部功能、API 不变,只换视觉:
深色顶栏 #24292f、Primer 浅色配色(边框 #d0d7de、链接蓝
#0969da、绿主按钮 #2da44e)、6px 圆角方框、系统字体与
等宽 ID/trace;任务列表改 issues 式(状态圆点 + 标题 +
灰色元信息);对话改评论时间线(白框 + 头部 + 正文,
竖线连接),灰/蓝气泡已移除;自动选项目与继续消息历史
不受影响。console 标记单测本地 53 项通过。
This commit is contained in:
host committed 2026-10-29 10:13:30 +08:00
1 parent bbe02efc14
commit e90c885290
6 files changed
+171 -158

No files matched your search

@@ -18,16 +18,19 @@ export function useAutoFollow(dep: unknown) {
return { ref, following, onScroll };
}
// GitHub-style comment box, not a chat bubble: full-width white box
// with a subtle header row (role label only — no timestamp or sender
// is invented; the backend provides neither) and the body below.
// Status entries are plain muted timeline text on the timeline line.
export function ChatBubble({ msg }: { msg: ChatMessage }) {
if (msg.role === "status") {
return <div className="chat-status">{msg.text}</div>;
}
const author = msg.label || (msg.role === "user" ? "用户" : msg.role === "assistant" ? "助手" : "工具");
return (
<div className={"chat-row " + msg.role}>
<div className={"chat-bubble " + msg.role}>
{msg.label ? <div className="chat-label">{msg.label}</div> : null}
<div className="chat-text">{msg.text}</div>
</div>
<div className={"gh-comment " + msg.role}>
<div className="gh-comment-header"><span className="gh-comment-author">{author}</span></div>
<div className="gh-comment-body">{msg.text}</div>
</div>
);
}
@@ -54,25 +57,24 @@ export function ChatInput({ onSend, disabled, placeholder }: {
onSend(v);
setText("");
};
// Pill input bar, Muse screenshot style: the textarea is the pill
// itself, and send is a light-blue circular arrow. No mic or
// attachment button here: the continue chat has no voice or
// attachment API (attachments live in Dispatch), so a mic/+ icon
// would be a dead button; the left list header's + is the new-task
// entry instead.
// GitHub comment box: textarea on top, a subtle footer row with the
// green primary send button. No mic or attachment button here: the
// continue chat has no voice or attachment API (attachments live in
// Dispatch), so a mic/+ icon would be a dead button.
return (
<div className="chat-input-bar">
<div className="gh-comment-box">
<textarea
aria-label="会话输入"
className="chat-input"
rows={1}
rows={3}
placeholder={placeholder || "消息"}
value={text}
disabled={disabled}
onChange={(e) => setText(e.target.value)}
onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }}
/>
<button type="button" className="chat-send" aria-label="发送" disabled={disabled || !text.trim()} onClick={send}>↑</button>
<div className="gh-comment-footer">
<button type="button" className="primary" aria-label="发送" disabled={disabled || !text.trim()} onClick={send}>发送</button>
</div>
</div>
);
}