milestone 32: task-shaped configuration, file mode as a rendering, config status api
Gates / frontend (push) Successful in 1m22s
Gates / test (push) Successful in 1m54s
Gates / test-aarch64 (push) Successful in 7m57s
Gates / package (push) Successful in 5m29s
Gates / container (push) Successful in 10s
CI / gates (push) Successful in 32m51s

This commit is contained in:
2026-08-22 22:42:50 +02:00
parent 025edbb093
commit 7e0df5fd94
89 changed files with 6101 additions and 3750 deletions
+70
View File
@@ -0,0 +1,70 @@
import type { ReactNode } from "react";
import * as stylex from "@stylexjs/stylex";
import { styles as shared } from "./styles";
import { colors } from "./tokens.stylex";
export interface Definition {
/** What the operator calls the value. */
label: string;
/**
* The exact key in the configuration file, shown secondarily so the reader
* can find the line to edit. Omitted for a derived value that has no key —
* inventing one would send the reader looking for something not there.
*/
zonKey?: string;
value: ReactNode;
}
const styles = stylex.create({
list: {
display: "grid",
gap: "0.75rem",
gridTemplateColumns: {
default: "repeat(1, minmax(0, 1fr))",
"@media (min-width: 640px)": "repeat(2, minmax(0, 1fr))",
},
margin: 0,
},
term: {
fontSize: "0.875rem",
lineHeight: "1.25rem",
fontWeight: 500,
},
key: {
marginLeft: "0.375rem",
fontSize: "0.75rem",
lineHeight: "1rem",
fontWeight: 400,
color: colors.textMuted,
},
value: {
marginTop: "0.125rem",
marginLeft: 0,
fontSize: "0.875rem",
lineHeight: "1.25rem",
color: colors.text,
},
});
/**
* Scalars as a definition list — the file-mode counterpart of a form section.
* Nothing here is interactive: a value the process loaded from a file is read,
* not edited.
*/
export default function DefinitionList({ items }: { items: readonly Definition[] }) {
return (
<dl {...stylex.props(styles.list)}>
{items.map((item) => (
<div key={item.label}>
<dt {...stylex.props(styles.term)}>
{item.label}
{item.zonKey !== undefined && (
<code {...stylex.props(shared.mono, styles.key)}>{item.zonKey}</code>
)}
</dt>
<dd {...stylex.props(styles.value)}>{item.value}</dd>
</div>
))}
</dl>
);
}
+28 -1
View File
@@ -11,7 +11,16 @@
*/
import * as stylex from "@stylexjs/stylex";
import { Button, Label, ListBox, ListBoxItem, Popover, Select as AriaSelect, SelectValue } from "react-aria-components";
import {
Button,
Label,
ListBox,
ListBoxItem,
Popover,
Select as AriaSelect,
SelectValue,
Text,
} from "react-aria-components";
import { colors } from "./tokens.stylex";
import { styles as shared } from "./styles";
@@ -27,6 +36,12 @@ interface Props {
/** The visible label. Omit it only when `aria-label` names the control. */
label?: string;
"aria-label"?: string;
/**
* Text under the control that qualifies it. RAC gives it an id and points the
* trigger's `aria-describedby` at it, which a sibling rendered by the caller
* cannot be: the trigger is this file's, so only this file can name it.
*/
description?: string;
/**
* `field` matches a full-width form input, `compactField` the smaller one a
* dialog uses, `inline` a control sitting in a row of other controls.
@@ -70,6 +85,12 @@ const styles = stylex.create({
chevron: {
color: colors.textMuted,
},
description: {
display: "block",
fontSize: "0.75rem",
lineHeight: "1rem",
color: colors.textMuted,
},
popover: {
width: "var(--trigger-width)",
maxHeight: "16rem",
@@ -116,6 +137,7 @@ export default function Select({
onChange,
label,
"aria-label": ariaLabel,
description,
variant = "field",
isDisabled = false,
}: Props) {
@@ -136,6 +158,11 @@ export default function Select({
</span>
</Button>
{description !== undefined && (
<Text slot="description" {...stylex.props(styles.description)}>
{description}
</Text>
)}
<Popover className={() => stylex.props(styles.popover).className ?? ""}>
<ListBox {...stylex.props(styles.listBox)}>
{options.map((option) => (
+13 -2
View File
@@ -25,6 +25,13 @@ interface Props {
/** The tab list's accessible name. */
label: string;
tabs: readonly TabSpec[];
/**
* The open tab, when a caller owns the selection — the configuration pages
* keep it in the URL. Omit both of these to let RAC hold the state, which
* is what a tab set with no linkable identity wants.
*/
selectedKey?: string;
onSelectionChange?: (key: string) => void;
}
const styles = stylex.create({
@@ -73,9 +80,13 @@ const styles = stylex.create({
},
});
export default function Tabs({ label, tabs }: Props) {
export default function Tabs({ label, tabs, selectedKey, onSelectionChange }: Props) {
return (
<AriaTabs className={() => stylex.props(styles.root).className ?? ""}>
<AriaTabs
selectedKey={selectedKey}
onSelectionChange={onSelectionChange === undefined ? undefined : (key) => onSelectionChange(String(key))}
className={() => stylex.props(styles.root).className ?? ""}
>
<TabList aria-label={label} className={() => stylex.props(styles.list).className ?? ""}>
{tabs.map((tab) => (
<Tab