cac1115035
Widens prose props on FleetDiagram, HandoffTable, PhasePanel, RouteTable, SkillPackage, and WorktreeMap to accept {en, pt} as well as string, and conditionally renders language spans. Non-prose props (id, code, etc) were left as strings.
174 lines
4.3 KiB
TypeScript
174 lines
4.3 KiB
TypeScript
---
|
|
// HandoffTable — the four-row "what crosses contexts" table.
|
|
//
|
|
// Static shell: the row data is passed in via `rows` so this component has
|
|
// no opinion on what each handoff package contains. The table structure is
|
|
// the load-bearing part of the design (dark header, blue row labels,
|
|
// muted body) and lives here so the next page that needs it gets the same
|
|
// beat for free.
|
|
|
|
type Localized = { en: string; pt: string };
|
|
|
|
interface Row {
|
|
/** The package name, rendered as a `<th>` (column 1). */
|
|
package: string | Localized;
|
|
/** What the package contains (column 2). */
|
|
contains: string | Localized;
|
|
/** Why this matters (column 3). */
|
|
why: string | Localized;
|
|
}
|
|
|
|
interface Props {
|
|
/** Column headers in render order. */
|
|
columns: [string | Localized, string | Localized, string | Localized];
|
|
rows: Row[];
|
|
}
|
|
|
|
const { columns, rows } = Astro.props;
|
|
---
|
|
|
|
<table class="handoff-table">
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
{
|
|
typeof columns[0] === 'string' ? (
|
|
columns[0]
|
|
) : (
|
|
<>
|
|
<>
|
|
<span data-language-content="en">{columns[0].en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{columns[0].pt}
|
|
</span>
|
|
</>
|
|
</>
|
|
)
|
|
}
|
|
</th>
|
|
<th>
|
|
{
|
|
typeof columns[1] === 'string' ? (
|
|
columns[1]
|
|
) : (
|
|
<>
|
|
<>
|
|
<span data-language-content="en">{columns[1].en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{columns[1].pt}
|
|
</span>
|
|
</>
|
|
</>
|
|
)
|
|
}
|
|
</th>
|
|
<th>
|
|
{
|
|
typeof columns[2] === 'string' ? (
|
|
columns[2]
|
|
) : (
|
|
<>
|
|
<>
|
|
<span data-language-content="en">{columns[2].en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{columns[2].pt}
|
|
</span>
|
|
</>
|
|
</>
|
|
)
|
|
}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{
|
|
rows.map((row) => (
|
|
<tr>
|
|
<th scope="row">
|
|
{typeof row.package === 'string' ? (
|
|
row.package
|
|
) : (
|
|
<>
|
|
<span data-language-content="en">{row.package.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{row.package.pt}
|
|
</span>
|
|
</>
|
|
)}
|
|
</th>
|
|
<td>
|
|
{typeof row.contains === 'string' ? (
|
|
row.contains
|
|
) : (
|
|
<>
|
|
<span data-language-content="en">{row.contains.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{row.contains.pt}
|
|
</span>
|
|
</>
|
|
)}
|
|
</td>
|
|
<td>
|
|
{typeof row.why === 'string' ? (
|
|
row.why
|
|
) : (
|
|
<>
|
|
<span data-language-content="en">{row.why.en}</span>
|
|
<span data-language-content="pt" hidden>
|
|
{row.why.pt}
|
|
</span>
|
|
</>
|
|
)}
|
|
</td>
|
|
</tr>
|
|
))
|
|
}
|
|
</tbody>
|
|
</table>
|
|
|
|
<style>
|
|
.handoff-table {
|
|
width: 100%;
|
|
margin-top: 30px;
|
|
border-collapse: collapse;
|
|
text-align: left;
|
|
}
|
|
.handoff-table th,
|
|
.handoff-table td {
|
|
padding: 17px 14px;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
.handoff-table thead {
|
|
color: var(--paper);
|
|
background: var(--ink);
|
|
/* token-gap: source uses 10px; no --step-* covers 10px; owner design-system-keeper */
|
|
font:
|
|
500 10px 'DM Mono',
|
|
monospace;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
.handoff-table tbody th {
|
|
color: var(--blue);
|
|
/* token-gap: source uses 14px; no --step-* covers 14px; owner design-system-keeper */
|
|
font:
|
|
600 14px 'DM Mono',
|
|
monospace;
|
|
}
|
|
.handoff-table td {
|
|
color: var(--muted);
|
|
/* token-gap: source uses 13px; no --step-* covers 13px; owner design-system-keeper */
|
|
font-size: 13px;
|
|
}
|
|
|
|
@media (max-width: 800px) {
|
|
.handoff-table {
|
|
display: block;
|
|
overflow-x: auto;
|
|
}
|
|
.handoff-table {
|
|
min-width: 650px;
|
|
}
|
|
}
|
|
</style>
|