Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: an agent's settings and AGENTS.md show placeholders while they load

BadgeSkeleton is the twin of Badge: the real Badge frame, as tall as an
interactive one (the settings values are buttons), with a placeholder for its
value. Permissions, resource caps, internet and allowed domains use it in place of
their "loading…" text, the details popover shows lines of text, and the
AGENTS.md editor a block, in place of theirs. SkeletonLines is a few stacked
lines for such blocks.
This commit is contained in:
iris 2026-11-06 17:27:55 +01:00
commit a9f0d61daa
5 changed files with 106 additions and 27 deletions

View file

@ -16,6 +16,7 @@ import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
import { Panel } from "../../ui/panel/Panel.js";
import { Popover } from "../../ui/popover/Popover.js";
import { useAgentActions } from "../roster/AgentActions.js";
import { SkeletonLines } from "../../ui/skeleton/Skeleton.js";
import { AgentDetail } from "./AgentDetail.js";
import type { AgentRow } from "../AgentTypes.js";
@ -83,7 +84,7 @@ export function AgentDetailPopover({
) : row === null ? (
<p>{agent} is not in the swarm's agent roster</p>
) : (
<p>loading…</p>
<SkeletonLines label="the agent's details" count={4} />
)}
</Panel>
</Popover>

View file

@ -27,6 +27,7 @@ import {
STALE_STATUS,
type Instructions,
} from "./instructions.js";
import { Skeleton, SkeletonRegion } from "../../ui/skeleton/Skeleton.js";
import "./AgentInstructions.css";
// An edit that was not saved: the text, and the version it was made on.
@ -218,14 +219,16 @@ function InstructionsForm({
role="status"
aria-live="polite"
>
{load.status === "loading"
? "loading…"
: busy
? "saving…"
: saved
? "saved"
: ""}
{busy ? "saving…" : saved ? "saved" : ""}
</p>
{load.status === "loading" ? (
<SkeletonRegion label="AGENTS.md">
<div class="ui-skeleton-lines">
<Skeleton width="6em" />
<Skeleton shape="block" width="100%" height="24em" />
</div>
</SkeletonRegion>
) : null}
{load.status === "error" ? (
<>
<ApiErrorPanel

View file

@ -20,6 +20,7 @@ import { Button } from "../../ui/button/Button.js";
import { Dialog } from "../../ui/dialog/Dialog.js";
import { Panel } from "../../ui/panel/Panel.js";
import { TextField } from "../../ui/text-field/TextField.js";
import { BadgeSkeleton } from "../../ui/skeleton/BadgeSkeleton.js";
import "../../ui/badge-row/BadgeRow.css";
import "./AgentLimits.css";
@ -127,13 +128,7 @@ export function AgentLimits({ agent }: { agent: string }) {
</>
) : null;
if (caps === null) {
return (
errorPanel ?? (
<span class="ui-agent-limits-muted" role="status">
loading the resource caps…
</span>
)
);
return errorPanel ?? <BadgeSkeleton what="the resource caps" width="9em" />;
}
return (

View file

@ -21,6 +21,7 @@ import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
import { Badge } from "@hive/shared/badge.js";
import { BadgePopover } from "../../ui/badge-popover/BadgePopover.js";
import { Button } from "../../ui/button/Button.js";
import { BadgeSkeleton } from "../../ui/skeleton/BadgeSkeleton.js";
import { MultiselectFilterOptions } from "../../ui/multiselect-filter/MultiselectFilter.js";
import {
requestPermissions,
@ -130,11 +131,7 @@ export function useGrant(agent: string) {
) : null;
const loading =
grant === null
? (readFailure ?? (
<span class="ui-agent-limits-muted" role="status">
loading the permissions…
</span>
))
? (readFailure ?? <BadgeSkeleton what="the permissions" />)
: null;
return { grant, busy, saveError, readFailure, loading, send };
}

View file

@ -39,6 +39,7 @@ import {
type EntryGroup,
} from "./allowed-domains.js";
import { useAllowedDomains } from "./useAllowedDomains.js";
import { BadgeSkeleton } from "../../ui/skeleton/BadgeSkeleton.js";
import "../../ui/badge-row/BadgeRow.css";
import "./AgentLimits.css";
@ -77,11 +78,7 @@ export function AllowedDomains({ agent }: { agent: string }) {
) : null;
if (entries === null) {
return (
errorPanel ?? (
<span class="ui-agent-limits-muted" role="status">
loading the allowed domains…
</span>
)
errorPanel ?? <BadgeSkeleton what="the allowed domains" width="7em" />
);
}