swarm-ui: shared Hint, ActionRow, Toolbar, EmptyState, ExternalLink and ExpandableCard replace per-page copies
Hint, ActionRow, Toolbar, EmptyState and ExternalLink replace the muted text, button row, refresh bar, empty line and _blank anchor that each page restyled under its own class. ExpandableCard (with a loading twin) holds the builds and recent-runs cards, which had identical head and body CSS. The create form's raw checkbox becomes CheckboxField. The components page shows each new piece.
This commit is contained in:
parent
b74b5e77e4
commit
8a2e5203ad
68 changed files with 689 additions and 427 deletions
|
|
@ -8,6 +8,5 @@
|
|||
margin-top: 1em;
|
||||
}
|
||||
.claude-login-ok {
|
||||
margin-top: 1em;
|
||||
color: var(--green);
|
||||
margin-block: 1em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
|||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { Dialog } from "../../ui/dialog/Dialog.js";
|
||||
import { ExternalLink } from "../../ui/external-link/ExternalLink.js";
|
||||
import { Hint } from "../../ui/hint/Hint.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import { TextField } from "../../ui/text-field/TextField.js";
|
||||
import {
|
||||
|
|
@ -98,9 +100,7 @@ export function ClaudeLoginDialog({
|
|||
<>
|
||||
<p>
|
||||
Open{" "}
|
||||
<a href={step.url} target="_blank" rel="noopener noreferrer">
|
||||
the claude login page
|
||||
</a>
|
||||
<ExternalLink href={step.url}>the claude login page</ExternalLink>
|
||||
, sign in with this agent's account, and paste the code it shows.
|
||||
</p>
|
||||
<form class="claude-login-form" onSubmit={submit}>
|
||||
|
|
@ -122,10 +122,10 @@ export function ClaudeLoginDialog({
|
|||
</>
|
||||
)}
|
||||
{step.step === "stored" && (
|
||||
<p class="claude-login-ok">
|
||||
<Hint tone="ok" class="claude-login-ok">
|
||||
Stored. <strong>{agent}</strong> picks the login up within a minute
|
||||
and resumes.
|
||||
</p>
|
||||
</Hint>
|
||||
)}
|
||||
{step.step === "failed" && (
|
||||
<ApiErrorPanel
|
||||
|
|
|
|||
|
|
@ -17,11 +17,6 @@
|
|||
flex-wrap: wrap;
|
||||
gap: 0.4em 1em;
|
||||
}
|
||||
.ui-agent-detail-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75em;
|
||||
}
|
||||
|
||||
/* The folded sections of an opened card sit one under another, each with the
|
||||
shared disclosure look; the fields keep the grid above. */
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@
|
|||
// change or a link made here shows wherever else the same row is drawn.
|
||||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ActionRow } from "../../ui/action-row/ActionRow.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { ExternalLink } from "../../ui/external-link/ExternalLink.js";
|
||||
import { Hint } from "../../ui/hint/Hint.js";
|
||||
import { RelativeTime } from "../../ui/relative-time/RelativeTime.js";
|
||||
import type { AgentActions } from "../roster/AgentActions.js";
|
||||
import { AgentInference } from "./AgentInference.js";
|
||||
|
|
@ -118,12 +121,10 @@ function OverviewRows({
|
|||
<>
|
||||
<dt>forge</dt>
|
||||
<dd class="ui-agent-detail-links">
|
||||
<a href={forgeLinks.profile} target="_blank" rel="noreferrer">
|
||||
profile
|
||||
</a>
|
||||
<a href={forgeLinks.configRepo} target="_blank" rel="noreferrer">
|
||||
<ExternalLink href={forgeLinks.profile}>profile</ExternalLink>
|
||||
<ExternalLink href={forgeLinks.configRepo}>
|
||||
config repo
|
||||
</a>
|
||||
</ExternalLink>
|
||||
</dd>
|
||||
</>
|
||||
) : null}
|
||||
|
|
@ -134,13 +135,9 @@ function OverviewRows({
|
|||
tone="warning"
|
||||
value={
|
||||
row.config_pr.html_url ? (
|
||||
<a
|
||||
href={row.config_pr.html_url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<ExternalLink href={row.config_pr.html_url}>
|
||||
#{row.config_pr.pr_number}
|
||||
</a>
|
||||
</ExternalLink>
|
||||
) : (
|
||||
`#${row.config_pr.pr_number}`
|
||||
)
|
||||
|
|
@ -211,7 +208,7 @@ function GrantRows({ agent }: { agent: string }) {
|
|||
<dt>permissions</dt>
|
||||
<dd>
|
||||
{g.grant === null ? (
|
||||
<span class="ui-agent-limits-muted">—</span>
|
||||
<Hint as="span">—</Hint>
|
||||
) : (
|
||||
<>
|
||||
{g.readFailure}
|
||||
|
|
@ -257,13 +254,13 @@ function LinkAccountAction({
|
|||
actions: AgentActions;
|
||||
}) {
|
||||
return (
|
||||
<div class="ui-agent-detail-actions">
|
||||
<ActionRow class="ui-agent-detail-actions">
|
||||
<LinkAccountMenu
|
||||
agent={row.name}
|
||||
hasHive={row.hive !== null}
|
||||
onSelect={(kind) => actions.openLink(row, kind)}
|
||||
/>
|
||||
</div>
|
||||
</ActionRow>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
.ui-agent-inference-source {
|
||||
margin-left: -0.25em;
|
||||
}
|
||||
.ui-agent-inference-source,
|
||||
.ui-agent-inference-muted {
|
||||
.ui-agent-inference-source {
|
||||
color: var(--muted);
|
||||
}
|
||||
.ui-agent-inference-form {
|
||||
|
|
@ -28,12 +27,3 @@
|
|||
gap: 0.75em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.ui-agent-inference-problem {
|
||||
margin: 0;
|
||||
color: var(--red);
|
||||
}
|
||||
.ui-agent-inference-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ import { useEffect, useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ActionRow } from "../../ui/action-row/ActionRow.js";
|
||||
import { Dialog } from "../../ui/dialog/Dialog.js";
|
||||
import { Hint } from "../../ui/hint/Hint.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import { SelectField } from "../../ui/select-field/SelectField.js";
|
||||
import { TextField } from "../../ui/text-field/TextField.js";
|
||||
|
|
@ -171,7 +173,7 @@ export function InferenceFields({
|
|||
pattern="[0-9]*"
|
||||
onInput={(maxSubagents) => onChange({ ...draft, maxSubagents })}
|
||||
/>
|
||||
{problem ? <p class="ui-agent-inference-problem">{problem}</p> : null}
|
||||
{problem ? <Hint tone="error">{problem}</Hint> : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -215,7 +217,7 @@ export function AgentInference({ agent }: { agent: string }) {
|
|||
/>
|
||||
) : null;
|
||||
if (view === null) {
|
||||
return errorPanel ?? <span class="ui-agent-inference-muted">…</span>;
|
||||
return errorPanel ?? <Hint as="span">…</Hint>;
|
||||
}
|
||||
|
||||
const { configured, effective } = view;
|
||||
|
|
@ -368,7 +370,7 @@ function InferenceForm({
|
|||
{problem ? (
|
||||
<ApiErrorPanel context="saving failed" problem={problem} />
|
||||
) : null}
|
||||
<div class="ui-agent-inference-actions">
|
||||
<ActionRow>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
|
|
@ -382,7 +384,7 @@ function InferenceForm({
|
|||
>
|
||||
clear the swarm's setting
|
||||
</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</form>
|
||||
</Panel>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -38,9 +38,3 @@
|
|||
border: 1px solid var(--red);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.ui-agent-instructions-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { useEffect, useRef, useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ActionRow } from "../../ui/action-row/ActionRow.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { Dialog } from "../../ui/dialog/Dialog.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
|
|
@ -235,9 +236,9 @@ function InstructionsForm({
|
|||
context="loading AGENTS.md failed"
|
||||
problem={load.problem}
|
||||
/>
|
||||
<div class="ui-agent-instructions-actions">
|
||||
<ActionRow class="ui-agent-instructions-actions">
|
||||
<Button onClick={reload}>try again</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</>
|
||||
) : null}
|
||||
{load.status === "ready" ? (
|
||||
|
|
@ -263,18 +264,18 @@ function InstructionsForm({
|
|||
<pre class="ui-agent-instructions-theirs" tabIndex={0}>
|
||||
{theirs.content === "" ? "(empty)" : theirs.content}
|
||||
</pre>
|
||||
<div class="ui-agent-instructions-actions">
|
||||
<ActionRow class="ui-agent-instructions-actions">
|
||||
<Button onClick={keepMine}>
|
||||
keep my text, replace {agent}'s changes
|
||||
</Button>
|
||||
<Button onClick={takeTheirs}>use {agent}'s version</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</section>
|
||||
) : null}
|
||||
{problem ? (
|
||||
<ApiErrorPanel context="saving failed" problem={problem} />
|
||||
) : null}
|
||||
<div class="ui-agent-instructions-actions">
|
||||
<ActionRow class="ui-agent-instructions-actions">
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
|
|
@ -305,7 +306,7 @@ function InstructionsForm({
|
|||
>
|
||||
reload from {agent}
|
||||
</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</form>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,10 +23,4 @@
|
|||
}
|
||||
.ui-agent-limits-hint {
|
||||
margin: 0 0 0.5em;
|
||||
color: var(--muted);
|
||||
}
|
||||
.ui-agent-limits-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,10 @@ import { useEffect, useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ActionRow } from "../../ui/action-row/ActionRow.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { Dialog } from "../../ui/dialog/Dialog.js";
|
||||
import { Hint } from "../../ui/hint/Hint.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import { TextField } from "../../ui/text-field/TextField.js";
|
||||
import { BadgeSkeleton } from "../../ui/skeleton/BadgeSkeleton.js";
|
||||
|
|
@ -71,9 +73,9 @@ export function LimitsFields({
|
|||
placeholder="e.g. 400%"
|
||||
onInput={onCpu}
|
||||
/>
|
||||
<p class="ui-agent-limits-hint">
|
||||
<Hint class="ui-agent-limits-hint">
|
||||
A percentage of one core: 100% is one core, 400% is four.
|
||||
</p>
|
||||
</Hint>
|
||||
<TextField
|
||||
id={`${idPrefix}-memory-max`}
|
||||
label="memory max"
|
||||
|
|
@ -81,10 +83,10 @@ export function LimitsFields({
|
|||
placeholder="e.g. 8G"
|
||||
onInput={onMemory}
|
||||
/>
|
||||
<p class="ui-agent-limits-hint">
|
||||
<Hint class="ui-agent-limits-hint">
|
||||
A size such as 512M or 8G, a percentage of the machine's memory such as
|
||||
50%, or infinity.
|
||||
</p>
|
||||
</Hint>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -239,7 +241,7 @@ function LimitsForm({
|
|||
{problem ? (
|
||||
<ApiErrorPanel context="the caps were not saved" problem={problem} />
|
||||
) : null}
|
||||
<div class="ui-agent-limits-actions">
|
||||
<ActionRow>
|
||||
<Button variant="primary" type="submit" disabled={busy || empty}>
|
||||
{busy ? "saving…" : "save"}
|
||||
</Button>
|
||||
|
|
@ -249,7 +251,7 @@ function LimitsForm({
|
|||
>
|
||||
clear the swarm's caps
|
||||
</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</form>
|
||||
</Panel>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ 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 { Hint } from "../../ui/hint/Hint.js";
|
||||
import { MultiselectFilterOptions } from "../../ui/multiselect-filter/MultiselectFilter.js";
|
||||
import {
|
||||
requestPermissions,
|
||||
|
|
@ -225,9 +226,9 @@ export function AgentPermissions({
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span class="ui-agent-limits-muted" role="status">
|
||||
<Hint as="span" role="status">
|
||||
{catalogueError ? "could not load the permissions" : "loading…"}
|
||||
</span>
|
||||
</Hint>
|
||||
)}
|
||||
{saveError ? (
|
||||
<ApiErrorPanel
|
||||
|
|
@ -287,7 +288,7 @@ export function AgentInternet({ agent, g }: { agent: string; g: GrantState }) {
|
|||
})
|
||||
}
|
||||
/>{" "}
|
||||
<span class="ui-agent-limits-muted">{meaning}</span>
|
||||
<Hint as="span">{meaning}</Hint>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { ActionRow } from "../../ui/action-row/ActionRow.js";
|
||||
import { BadgePopover } from "../../ui/badge-popover/BadgePopover.js";
|
||||
import { Button } from "../../ui/button/Button.js";
|
||||
import { CheckboxField } from "../../ui/checkbox-field/CheckboxField.js";
|
||||
|
|
@ -232,7 +233,7 @@ export function AddForm({
|
|||
{problem ? (
|
||||
<ApiErrorPanel context="the domain was not added" problem={problem} />
|
||||
) : null}
|
||||
<div class="ui-agent-limits-actions">
|
||||
<ActionRow>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
|
|
@ -240,7 +241,7 @@ export function AddForm({
|
|||
>
|
||||
{busy ? "adding…" : "add"}
|
||||
</Button>
|
||||
</div>
|
||||
</ActionRow>
|
||||
</form>
|
||||
</Panel>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
gap: 0.5em;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.ui-linked-accounts-host,
|
||||
.ui-linked-accounts-muted {
|
||||
.ui-linked-accounts-host {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
|||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { CheckboxField } from "../../ui/checkbox-field/CheckboxField.js";
|
||||
import { ConfirmDialog } from "../../ui/confirm-dialog/ConfirmDialog.js";
|
||||
import { Hint } from "../../ui/hint/Hint.js";
|
||||
import { accountKindLabel } from "./account-kind.js";
|
||||
import { deleteUrl, listUrl } from "./account-api.js";
|
||||
import "./LinkedAccounts.css";
|
||||
|
|
@ -145,13 +146,13 @@ export function LinkedAccounts({
|
|||
<ApiErrorPanel context="listing linked accounts failed" problem={error} />
|
||||
) : null;
|
||||
if (accounts === null) {
|
||||
return errorPanel ?? <span class="ui-linked-accounts-muted">…</span>;
|
||||
return errorPanel ?? <Hint as="span">…</Hint>;
|
||||
}
|
||||
if (accounts.length === 0) {
|
||||
return (
|
||||
<>
|
||||
{errorPanel}
|
||||
<span class="ui-linked-accounts-muted">none linked</span>
|
||||
<Hint as="span">none linked</Hint>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { useState } from "preact/hooks";
|
|||
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
||||
import { Badge, type BadgeTone } from "@hive/shared/badge.js";
|
||||
import { Button } from "../ui/button/Button.js";
|
||||
import { ExternalLink } from "../ui/external-link/ExternalLink.js";
|
||||
import { LazyDisclosure } from "../ui/disclosure/LazyDisclosure.js";
|
||||
import { RelativeTime } from "../ui/relative-time/RelativeTime.js";
|
||||
import {
|
||||
|
|
@ -16,6 +17,7 @@ import {
|
|||
import { fetchJson, usePolled } from "../ui/polled/usePolled.js";
|
||||
import { Table, type TableColumn } from "../ui/table/Table.js";
|
||||
import { TableSkeleton } from "../ui/table/TableSkeleton.js";
|
||||
import { Toolbar } from "../ui/toolbar/Toolbar.js";
|
||||
import { activeSinceMs, alertKey, listedAlerts, type Alert } from "./alerts.js";
|
||||
|
||||
const STATE_TONE: Record<string, BadgeTone> = {
|
||||
|
|
@ -90,10 +92,10 @@ function AlertsBody() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div class="ui-alerts-bar">
|
||||
<a href={GRAFANA_ALERTS_URL} target="_blank" rel="noopener noreferrer">
|
||||
<Toolbar>
|
||||
<ExternalLink href={GRAFANA_ALERTS_URL}>
|
||||
Grafana's alert list
|
||||
</a>
|
||||
</ExternalLink>
|
||||
{showAll || hidden > 0 ? (
|
||||
<Button onClick={() => setShowAll(!showAll)}>
|
||||
{showAll ? "only firing" : `show ${hidden} more`}
|
||||
|
|
@ -105,7 +107,7 @@ function AlertsBody() {
|
|||
onChange={setIntervalMs}
|
||||
refreshing={refreshing}
|
||||
/>
|
||||
</div>
|
||||
</Toolbar>
|
||||
{error ? (
|
||||
<ApiErrorPanel
|
||||
context="failed to load Grafana's alerts"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,15 @@ import {
|
|||
import { CheckboxField } from "../ui/checkbox-field/CheckboxField.js";
|
||||
import { Button, type ButtonVariant } from "../ui/button/Button.js";
|
||||
import { Dialog } from "../ui/dialog/Dialog.js";
|
||||
import { ActionRow } from "../ui/action-row/ActionRow.js";
|
||||
import { EmptyState } from "../ui/empty-state/EmptyState.js";
|
||||
import {
|
||||
ExpandableCard,
|
||||
ExpandableCardSkeleton,
|
||||
} from "../ui/expandable-card/ExpandableCard.js";
|
||||
import { ExternalLink } from "../ui/external-link/ExternalLink.js";
|
||||
import { Hint, type HintTone } from "../ui/hint/Hint.js";
|
||||
import { Toolbar } from "../ui/toolbar/Toolbar.js";
|
||||
import { ConfirmDialog } from "../ui/confirm-dialog/ConfirmDialog.js";
|
||||
import { Popover } from "../ui/popover/Popover.js";
|
||||
import { Badge, type BadgeTone } from "@hive/shared/badge.js";
|
||||
|
|
@ -41,6 +50,8 @@ import { GearIcon } from "@hive/shared/icons.js";
|
|||
import { Dropdown, type DropdownOption } from "@hive/shared/dropdown.js";
|
||||
import "./ComponentsPage.css";
|
||||
|
||||
const HINT_TONES: HintTone[] = ["muted", "warn", "error", "ok"];
|
||||
|
||||
function Section({
|
||||
title,
|
||||
children,
|
||||
|
|
@ -590,6 +601,62 @@ export function ComponentsPage() {
|
|||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Hint">
|
||||
<div class="components-chip-row">
|
||||
{HINT_TONES.map((tone) => (
|
||||
<Sample key={tone} label={tone}>
|
||||
<Hint tone={tone}>A line of supporting text.</Hint>
|
||||
</Sample>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="ActionRow, Toolbar, EmptyState, ExternalLink">
|
||||
<Sample label="ActionRow: the buttons that end a form">
|
||||
<ActionRow>
|
||||
<Button variant="primary">save</Button>
|
||||
<Button>cancel</Button>
|
||||
</ActionRow>
|
||||
</Sample>
|
||||
<Sample label="Toolbar: the bar above a list">
|
||||
<Toolbar>
|
||||
<Button>refresh</Button>
|
||||
</Toolbar>
|
||||
</Sample>
|
||||
<Sample label="EmptyState">
|
||||
<EmptyState>Nothing here yet.</EmptyState>
|
||||
</Sample>
|
||||
<Sample label="ExternalLink">
|
||||
<ExternalLink href="https://example.com">example.com</ExternalLink>
|
||||
</Sample>
|
||||
</Section>
|
||||
|
||||
<Section title="ExpandableCard">
|
||||
<Sample label="closed, open, and the loading twin">
|
||||
<ExpandableCard
|
||||
id="components-expandable-closed"
|
||||
open={false}
|
||||
onToggle={() => {}}
|
||||
title="build 1"
|
||||
badge={<Badge value="ok" />}
|
||||
meta="2 minutes ago"
|
||||
>
|
||||
body
|
||||
</ExpandableCard>
|
||||
<ExpandableCard
|
||||
id="components-expandable-open"
|
||||
open
|
||||
onToggle={() => {}}
|
||||
title="build 2"
|
||||
badge={<Badge value="failed" />}
|
||||
meta="an hour ago"
|
||||
>
|
||||
<Hint>The body appears while the card is open.</Hint>
|
||||
</ExpandableCard>
|
||||
<ExpandableCardSkeleton />
|
||||
</Sample>
|
||||
</Section>
|
||||
|
||||
<Section title="Dialog">
|
||||
<Sample label="modal, caller-owned content">
|
||||
<DialogSample />
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@
|
|||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
margin-left: 0.25em;
|
||||
color: var(--muted);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.create-agent-summary {
|
||||
|
|
@ -118,14 +117,6 @@
|
|||
margin: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.create-agent-result-ok {
|
||||
color: var(--green);
|
||||
}
|
||||
/* The controller's refusal of the AGENTS.md text, under its box. */
|
||||
.create-agent-field-error {
|
||||
margin: 0;
|
||||
color: var(--red);
|
||||
}
|
||||
/* The picked archetype's description, under its select. */
|
||||
.create-agent-archetype-description {
|
||||
margin: 0;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ import {
|
|||
InferenceFields,
|
||||
type InferenceDraft,
|
||||
} from "../agent/detail/AgentInference.js";
|
||||
import { CheckboxField } from "../ui/checkbox-field/CheckboxField.js";
|
||||
import { FormField } from "../ui/form-field/FormField.js";
|
||||
import { Hint } from "../ui/hint/Hint.js";
|
||||
import { MultiselectFilterOptions } from "../ui/multiselect-filter/MultiselectFilter.js";
|
||||
import {
|
||||
initialSelection,
|
||||
|
|
@ -325,12 +327,12 @@ export function CreateAgentForm({
|
|||
/>
|
||||
)}
|
||||
{done && (
|
||||
<div class="create-agent-result create-agent-result-ok">
|
||||
<Hint tone="ok" as="div" class="create-agent-result">
|
||||
<p>
|
||||
Queued as job node #{result.nodeId} —{" "}
|
||||
<Link href="/jobs">watch it in jobs</Link>.
|
||||
</p>
|
||||
</div>
|
||||
</Hint>
|
||||
)}
|
||||
{!done && step === "identity" && (
|
||||
<div class="create-agent-fields">
|
||||
|
|
@ -409,7 +411,9 @@ export function CreateAgentForm({
|
|||
onInput={setAgentsMd}
|
||||
/>
|
||||
{refusal !== null && (
|
||||
<p class="create-agent-field-error">{refusal}</p>
|
||||
<Hint tone="error" class="create-agent-field-error">
|
||||
{refusal}
|
||||
</Hint>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -438,14 +442,12 @@ export function CreateAgentForm({
|
|||
)}
|
||||
</div>
|
||||
</FormField>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={internet}
|
||||
onChange={() => setInternet((v) => !v)}
|
||||
/>{" "}
|
||||
Unrestricted internet
|
||||
</label>
|
||||
<CheckboxField
|
||||
id="create-agent-internet"
|
||||
label="Unrestricted internet"
|
||||
checked={internet}
|
||||
onChange={setInternet}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!done && step === "resources" && (
|
||||
|
|
@ -531,9 +533,9 @@ export function CreateAgentForm({
|
|||
back
|
||||
</Button>
|
||||
{problem !== null && (step !== "identity" || name !== "") && (
|
||||
<span class="create-agent-hint" role="status">
|
||||
<Hint as="span" role="status" class="create-agent-hint">
|
||||
{problem}
|
||||
</span>
|
||||
</Hint>
|
||||
)}
|
||||
{step === "summary" ? (
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
|
|||
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
||||
import { Badge } from "@hive/shared/badge.js";
|
||||
import { useLocalSetting } from "@hive/shared/settings-storage.js";
|
||||
import { ExternalLink } from "../ui/external-link/ExternalLink.js";
|
||||
import { LazyDisclosure } from "../ui/disclosure/LazyDisclosure.js";
|
||||
import { CheckboxField } from "../ui/checkbox-field/CheckboxField.js";
|
||||
import { SelectField } from "../ui/select-field/SelectField.js";
|
||||
|
|
@ -268,9 +269,7 @@ function IssueReportBody() {
|
|||
ariaSort: ariaSortFor("number"),
|
||||
render: (r) =>
|
||||
r.html_url ? (
|
||||
<a href={r.html_url} target="_blank" rel="noreferrer">
|
||||
#{r.number}
|
||||
</a>
|
||||
<ExternalLink href={r.html_url}>#{r.number}</ExternalLink>
|
||||
) : (
|
||||
`#${r.number}`
|
||||
),
|
||||
|
|
|
|||
|
|
@ -14,8 +14,3 @@
|
|||
flex-direction: column;
|
||||
gap: 1em;
|
||||
}
|
||||
.ui-jobs-refresh {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-block-end: 0.5em;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue