6bfae2033e
Extended the typography `--step-*` scale to cover the ad-hoc pixel values used across components (10px to 48px). Added overlay tokens `--white-14`, `--white-23`, `--white-25`, `--white-31`. Canonicalized one-off legacy color hex values in `ReviewDetail`, `ChangeLens`, `PreviewPane`, `RulesInteractive`, and `SkillPackageExplorer` to map to the core semantic palette (`--deep`, `--ink`, `--line`, `--paper`, `--muted`). Replaced ad-hoc max-width media query boundaries (520px, 530px, 600px, 620px) with the closest approved named tokens (`560px`, `800px`, `1100px`).
208 lines
5.2 KiB
TypeScript
208 lines
5.2 KiB
TypeScript
---
|
|
// FleetDiagram — orchestrator card, an arrow, and a 1-up of worker cards.
|
|
//
|
|
// Static shell: the captain renders literally, the workers render as toggle
|
|
// buttons with the `data-worker` hook asserted by `scripts/verify.mjs`. The
|
|
// `initial` worker is marked active and pressed.
|
|
//
|
|
// The source uses `gap:1px` over a coloured parent background to fake
|
|
// hairlines between worker cards; the parent background is an off-token seam
|
|
// colour marked inline with `token-gap`.
|
|
|
|
type Localized = { en: string; pt: string };
|
|
|
|
interface Worker {
|
|
/** Used as the `data-worker` hook and the key in the source. */
|
|
id: string;
|
|
/** Short label rendered uppercase, e.g. "UI". */
|
|
label: string | Localized;
|
|
/** Body copy describing the worker's remit. */
|
|
strong: string | Localized;
|
|
/** Path label, e.g. "agent/ui". */
|
|
code: string;
|
|
}
|
|
|
|
interface Props {
|
|
orchestrator: {
|
|
eyebrow: string | Localized;
|
|
/** May contain inline `<br>`; rendered with `set:html`. */
|
|
title: string | Localized;
|
|
code: string;
|
|
};
|
|
workers: Worker[];
|
|
initial?: string;
|
|
}
|
|
|
|
const { orchestrator, workers, initial = workers[0]?.id } = Astro.props;
|
|
---
|
|
|
|
<div class="fleet-grid">
|
|
<article class="captain">
|
|
<span class="captain-eyebrow">
|
|
{
|
|
typeof orchestrator.eyebrow === 'string' ? (
|
|
orchestrator.eyebrow
|
|
) : (
|
|
<>
|
|
<>
|
|
<span data-language-content="en">{orchestrator.eyebrow.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{orchestrator.eyebrow.pt}
|
|
</span>
|
|
</>
|
|
</>
|
|
)
|
|
}
|
|
</span>
|
|
{
|
|
typeof orchestrator.title === 'string' ? (
|
|
<h2 set:html={orchestrator.title} />
|
|
) : (
|
|
<>
|
|
<h2 data-language-content="en" set:html={orchestrator.title.en} />
|
|
<h2 data-language-content="pt" hidden set:html={orchestrator.title.pt} />
|
|
</>
|
|
)
|
|
}
|
|
<code>{orchestrator.code}</code>
|
|
</article>
|
|
<div class="arrow" aria-hidden="true">→</div>
|
|
<div class="workers" role="group" aria-label="Worker agents">
|
|
{
|
|
workers.map((worker) => (
|
|
<button
|
|
class:list={['worker-card', { active: worker.id === initial }]}
|
|
data-worker={worker.id}
|
|
aria-pressed={worker.id === initial}
|
|
>
|
|
<span>
|
|
{typeof worker.label === 'string' ? (
|
|
worker.label
|
|
) : (
|
|
<>
|
|
<span data-language-content="en">{worker.label.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{worker.label.pt}
|
|
</span>
|
|
</>
|
|
)}
|
|
</span>
|
|
<strong>
|
|
{typeof worker.strong === 'string' ? (
|
|
worker.strong
|
|
) : (
|
|
<>
|
|
<span data-language-content="en">{worker.strong.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{worker.strong.pt}
|
|
</span>
|
|
</>
|
|
)}
|
|
</strong>
|
|
<code>{worker.code}</code>
|
|
</button>
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.fleet-grid {
|
|
display: grid;
|
|
grid-template-columns: 0.8fr 50px 1.5fr;
|
|
gap: 24px;
|
|
margin-top: 30px;
|
|
color: var(--paper);
|
|
background: var(--deep);
|
|
}
|
|
.captain {
|
|
display: grid;
|
|
align-content: center;
|
|
gap: 16px;
|
|
padding: 32px;
|
|
}
|
|
.captain-eyebrow {
|
|
color: var(--gold);
|
|
/* token-gap: source uses 10px; no --step-* covers 10px; owner design-system-keeper */
|
|
font:
|
|
500 10px 'DM Mono',
|
|
monospace;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
}
|
|
.captain h2 {
|
|
margin: 0;
|
|
/* token-gap: source uses clamp(24px,3vw,38px); --step-5 is clamp(36px,5vw,65px); owner design-system-keeper */
|
|
font-size: clamp(24px, 3vw, 38px);
|
|
line-height: 0.98;
|
|
letter-spacing: -0.06em;
|
|
}
|
|
.captain code {
|
|
color: var(--gold);
|
|
font:
|
|
500 var(--step-0) 'DM Mono',
|
|
monospace;
|
|
}
|
|
|
|
.arrow {
|
|
display: grid;
|
|
place-items: center;
|
|
color: var(--gold);
|
|
font-size: var(--step-30);
|
|
}
|
|
|
|
.workers {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 1px;
|
|
background: var(--muted);
|
|
}
|
|
.worker-card {
|
|
display: grid;
|
|
align-content: space-between;
|
|
gap: 20px;
|
|
min-height: 180px;
|
|
padding: 22px;
|
|
color: var(--paper);
|
|
background: var(--ink);
|
|
border: 0;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
.worker-card span {
|
|
color: var(--muted);
|
|
/* token-gap: source uses 10px; no --step-* covers 10px; owner design-system-keeper */
|
|
font:
|
|
500 10px 'DM Mono',
|
|
monospace;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
}
|
|
.worker-card strong {
|
|
font-size: var(--step-16);
|
|
line-height: 1.2;
|
|
}
|
|
.worker-card code {
|
|
color: var(--gold);
|
|
font:
|
|
500 var(--step-0) 'DM Mono',
|
|
monospace;
|
|
}
|
|
.worker-card.active {
|
|
box-shadow: inset 4px 0 0 var(--gold);
|
|
}
|
|
|
|
@media (max-width: 800px) {
|
|
.fleet-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.arrow {
|
|
transform: rotate(90deg);
|
|
min-height: 35px;
|
|
}
|
|
.workers {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|