swarm-ui: a group pane's maximize and close are icon-only badges in its top right corner
The two controls sat among the pane's header badges as a labelled badge and a cross glyph. They are now icon badges in the top right corner, through a `trailing` slot of the terminal preview, so the header on the left keeps the agent, split, subagents and state badges and a narrow pane wraps less.
This commit is contained in:
parent
d733b1e2a9
commit
4876acd02a
5 changed files with 53 additions and 15 deletions
|
|
@ -169,11 +169,12 @@ a group of the two, with its own header tab at `/agents/group/<id>`. In a group,
|
|||
the same drag onto a pane splits that pane, as many times as you like, and
|
||||
dragging a pane's header badge onto another pane moves it there. The **split**
|
||||
button in a pane's header does the same for an agent whose terminal tab is open:
|
||||
**right** or **below** puts it beside the pane. **maximize** opens that
|
||||
agent's own terminal in its tab, or goes to the tab when one is open already. A pane
|
||||
can hold a subagent's terminal (its header reads `agent/subagent`), put there by
|
||||
the **subagents** badge in the pane's header. The **×** takes the pane's
|
||||
agent out of the group, and a group left with one agent goes, landing on that
|
||||
**right** or **below** puts it beside the pane. A pane can hold a subagent's
|
||||
terminal (its header reads `agent/subagent`), put there by the **subagents**
|
||||
badge in the pane's header. Two icon buttons sit in a pane's top right corner.
|
||||
**Maximize** (the arrows pointing to the corners) opens that pane's own terminal
|
||||
in its tab, or goes to the tab when one is open already. **Close** (the cross)
|
||||
takes the pane out of the group, and a group left with one pane goes, landing on that
|
||||
agent's own terminal. Drag a divider to resize, or focus it and use the arrow
|
||||
keys. Panes have no minimum size; a divider stops at 2% so a pane can't
|
||||
vanish.
|
||||
|
|
|
|||
|
|
@ -83,6 +83,27 @@ export function ExpandIcon() {
|
|||
);
|
||||
}
|
||||
|
||||
// A cross, for an icon-only close trigger (a pane's "take this out of the
|
||||
// group"). Same size and stroke as `ExpandIcon`.
|
||||
export function CloseIcon() {
|
||||
return (
|
||||
<svg
|
||||
width="1.3em"
|
||||
height="1.3em"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<line x1="5" y1="5" x2="19" y2="19" />
|
||||
<line x1="19" y1="5" x2="5" y2="19" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
// A funnel, the standard "filter" glyph — smaller than the other two
|
||||
// (1em not 1.3em) since its first caller sits inside a table header
|
||||
// cell, not a nav trigger button; scale via the caller's own
|
||||
|
|
|
|||
|
|
@ -102,6 +102,12 @@
|
|||
.ui-agent-term-preview-controls > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
/* The icon-only controls in the top right corner. */
|
||||
.ui-agent-term-preview-trailing {
|
||||
display: flex;
|
||||
flex: none;
|
||||
gap: 0.25em;
|
||||
}
|
||||
.ui-agent-term-preview-header-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ export function AgentTermPreview({
|
|||
subagent,
|
||||
fullHeight = false,
|
||||
leading,
|
||||
trailing,
|
||||
}: {
|
||||
agentName: string;
|
||||
// Set: this is one of `agentName`'s subagents, output only like the
|
||||
|
|
@ -217,6 +218,9 @@ export function AgentTermPreview({
|
|||
// A badge ahead of the connection badge, for the full-tab mount's
|
||||
// link back to the agent's details.
|
||||
leading?: ComponentChildren;
|
||||
// Icon-only badges in the top right corner, for the full-tab mount's own
|
||||
// controls (a group pane's maximize and close).
|
||||
trailing?: ComponentChildren;
|
||||
}) {
|
||||
const paths = termPaths(agentName, subagent);
|
||||
const { rows, connection, reconnect } = useSwarmTermStream(paths.stream);
|
||||
|
|
@ -293,6 +297,9 @@ export function AgentTermPreview({
|
|||
onClick={() => openTab({ href: paths.page, label: paths.label })}
|
||||
/>
|
||||
)}
|
||||
{trailing !== undefined && (
|
||||
<div class="ui-agent-term-preview-trailing">{trailing}</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="live terminal" ref={logRef} onScroll={handleScroll}>
|
||||
{rows.length === 0 ? (
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@
|
|||
// `/agents/group/:id`: each pane is one agent's full terminal, split by
|
||||
// dragging another agent's terminal tab (or a pane's header) onto the edge of
|
||||
// a pane, or by the split button in a pane's header. A pane can also be one of
|
||||
// an agent's subagents, put beside it by the subagents menu. Dividers resize, and the
|
||||
// layout is saved in the browser (`useTermGroups`). A pane's × takes its agent
|
||||
// out of the group; a group of one gives way to that agent's own terminal.
|
||||
// an agent's subagents, put beside it by the subagents menu. Dividers resize,
|
||||
// and the layout is saved in the browser (`useTermGroups`). A pane's close icon
|
||||
// takes its agent out of the group, its maximize icon opens the agent on its
|
||||
// own; a group of one gives way to that agent's own terminal.
|
||||
//
|
||||
// Registers its header tab like an agent terminal does, so a reload or a
|
||||
// bookmark reopens it. The tab shows the group's name, or its agents.
|
||||
import { useEffect } from "preact/hooks";
|
||||
import { useLocation, type RouteComponentProps } from "wouter-preact";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ExpandIcon } from "@hive/shared/icons.js";
|
||||
import { CloseIcon, ExpandIcon } from "@hive/shared/icons.js";
|
||||
import { AgentIcon } from "../../agent/AgentIcon.js";
|
||||
import { SubagentsMenu } from "../../agent/terminal/SubagentsMenu.js";
|
||||
import {
|
||||
|
|
@ -185,10 +186,13 @@ export function AgentGroupPage({
|
|||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
trailing={
|
||||
<>
|
||||
<Badge
|
||||
icon={<ExpandIcon />}
|
||||
value="maximize"
|
||||
title={`open ${key}'s terminal on its own`}
|
||||
value={<ExpandIcon />}
|
||||
title={`maximize: open ${key}'s terminal on its own`}
|
||||
onClick={() =>
|
||||
open({
|
||||
href: termPaths(agent, subagent).page,
|
||||
|
|
@ -197,9 +201,8 @@ export function AgentGroupPage({
|
|||
}
|
||||
/>
|
||||
<Badge
|
||||
variant="quiet"
|
||||
value="×"
|
||||
title={`take ${key} out of this group`}
|
||||
value={<CloseIcon />}
|
||||
title={`close: take ${key} out of this group`}
|
||||
onClick={() =>
|
||||
groups.update(id, (r) => removeAgent(r, key) ?? r)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue