fix(ui): give embedded settings sections the shared section rhythm (#126541)

* fix(ui): give embedded settings sections the shared section rhythm

The agents tab panel hosted settings sections in a bare div, so sections
stacked with zero separation; the bespoke .agents-main margin rule in
agents.css missed the nested tabpanel entirely. Descriptions also pulled
up to 4px under control-height header actions (squeezed Verify/Save rows).

Add a .settings-stack primitive to settings.css for embedded surfaces,
use it on the agent tab panel, delete the page-local margin fork, and let
section descriptions clear action-bearing headers.

* test(agents): export getRuntimeConfigSourceSnapshot from runtime-snapshot mock

Main's checks-node-compact-large shard is red: #126531 routed
provider-model-routes through projectConfigOntoRuntimeSourceSnapshot,
which reads getRuntimeConfigSourceSnapshot, and this suite's explicit
vi.mock factory did not export it (24 failures). Return null so the
projection no-ops and resolvers keep reading the provided config.
This commit is contained in:
Peter Steinberger
2026-08-19 22:31:35 -07:00
committed by GitHub
parent 33744584f3
commit 0a8226c3db
5 changed files with 20 additions and 6 deletions
@@ -397,6 +397,9 @@ vi.mock("../skills/discovery/chat-commands.runtime.js", () => ({
vi.mock("../config/runtime-snapshot.js", () => ({
getRuntimeConfigSnapshot: () => state.runtimeConfigMock ?? state.defaultRuntimeConfig,
// No source snapshot: runtime-source projection no-ops and resolvers read the
// provided config directly, matching this suite's pre-projection world.
getRuntimeConfigSourceSnapshot: () => null,
registerRuntimeConfigSnapshotPreparer: vi.fn(),
setRuntimeConfigSnapshot: vi.fn(),
}));
+1
View File
@@ -14,6 +14,7 @@ Every settings surface (the `/settings` takeover pages plus the Plugins/Skills h
```
- **Sections are typography, not chrome.** Grouping comes from whitespace + a small uppercase heading — never a card header.
- **Embedded surfaces keep the rhythm.** A container that hosts sections without `.settings-page`'s centered column (tab panels, split layouts) takes `.settings-stack`; never re-space sections with page-local margin rules.
- **Exactly one level of elevation.** A group never contains another card, callout, or bordered box. Nested detail uses `.settings-subrows` (indented rows), a stacked row, or a drill-in nav row.
- **Row anatomy:** left is title (`--control-ui-text-md`, weight 500) over an optional one-line description (muted, sm). Right is exactly one control: toggle, select, segmented, button, plain value, or chevron (nav). Wide editors use the `stacked` variant.
- **Lists are rows too.** An entity list (plugin, device, session) is a group whose rows carry an action cluster in the control slot — same anatomy as a toggle row.
+1
View File
@@ -330,6 +330,7 @@ export function renderAgents(props: AgentsProps) {
)}
<div
id="agent-panel"
class="settings-stack"
role="tabpanel"
aria-labelledby=${`agents-tab-${props.activePanel}`}
>
-6
View File
@@ -15,9 +15,3 @@
.agents-panel-body + .settings-kv {
border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
}
/* .agents-main is a 14px-gap grid (components.css); settings sections need
more whitespace between each other than panel chrome does. */
.agents-main > .settings-section:not(:first-child) {
margin-top: var(--space-4);
}
+15
View File
@@ -87,6 +87,15 @@
max-width: 1120px;
}
/* Section rhythm for embedded surfaces (tab panels, split layouts) that host
settings sections without .settings-page's centered column. Sections crammed
into a plain wrapper collapse to zero separation. */
.settings-stack {
display: flex;
flex-direction: column;
gap: var(--space-8);
}
.settings-page__intro {
margin: 0;
font-size: var(--control-ui-text-sm);
@@ -130,6 +139,12 @@
color: var(--muted);
}
/* Control-height header actions overhang the one-line heading; keep the
description's negative pull from squeezing it against the button row. */
.settings-section__header:has(.settings-section__actions) + .settings-section__desc {
margin-top: 0;
}
.settings-section__actions {
display: flex;
align-items: center;