A chat app's shape: sidebar, a new chat as a chat page, the chat's settings as composer chips
- Sidebar: New chat, search, Scheduled, Files, the chats of both kinds by day (Today, Earlier), Settings with the account at the foot; folds away (Ctrl+B), a drawer on a narrow window. - A new chat is the chat page empty: a greeting, Agent or Chat, and the composer. - The composer is a card: the text, then attach, the chips (folder and mode for an agent chat, model with its picture, effort as the model offers it, the team's size), and a round Send that Stop replaces while a reply is written. An open chat's chips change the chat. - Messages: the person's in a bubble on the right with attached pictures as thumbnails, a reply full width; thinking and tool calls as compact rows that unfold. - Activity: a chip above the composer for every open chat, the panel on the right as before. - The agent: a chip in the title bar opening its state and the one thing to do about it; "This computer is not linked yet" with Link this computer right above the composer of an agent chat, and "refused" only with the server's reason. - Files: a page with the two trees as tabs. Settings: grouped, the groups listed beside them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
15 files changed
+1856
-916
No files matched your search
+17
-7
@@ -273,16 +273,26 @@ async function read(withContext) {
|
||||
|
||||
function renderStrip() {
|
||||
const strip = $("activity-strip")
|
||||
// While something runs, as the server's strip: a chat whose helpers all finished long ago does
|
||||
// not carry "12 finished" above its message box for ever (the panel still lists them).
|
||||
const text = chat && summary?.active ? summaryText(summary) : ""
|
||||
strip.hidden = !text
|
||||
if (!text) return clear(strip)
|
||||
// A chip for every open chat: what runs, while something does, as the server's strip says it (a
|
||||
// chat whose helpers all finished long ago does not carry "12 finished" for ever: the panel
|
||||
// still lists them); else only the way into the panel.
|
||||
strip.hidden = !chat
|
||||
if (!chat) return clear(strip)
|
||||
const active = summary?.active ? summaryText(summary) : ""
|
||||
const text = active || t("Activity")
|
||||
strip.replaceChildren(
|
||||
h(
|
||||
"button",
|
||||
{ type: "button", class: "strip__btn", "aria-label": `${text} — ${t("Open the activity panel")}`, onclick: () => showPanel(true) },
|
||||
h("span", { class: "dot is-busy", "aria-hidden": "true" }),
|
||||
{
|
||||
type: "button",
|
||||
id: "activity-open",
|
||||
class: `strip__btn${active ? " is-active" : ""}`,
|
||||
"aria-label": `${text} — ${panelOpen() ? t("Close the activity panel") : t("Open the activity panel")}`,
|
||||
"aria-controls": "activity",
|
||||
"aria-expanded": String(panelOpen()),
|
||||
onclick: togglePanel,
|
||||
},
|
||||
h("span", { class: "dot", "aria-hidden": "true" }),
|
||||
h("span", { class: "strip__text", text }),
|
||||
icon(ICONS.chevron),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user