Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5578d9a
test: ⌘K and Ctrl+K open the dialog and focus the box; the sidebar bu…
V3RON Oct 21, 2026
d3483e5
feat(console): the search dialog opens from ⌘K, Ctrl+K and the sideba…
V3RON Oct 21, 2026
2de87d7
test: typing `fleet` and Enter goes to /fleet; a worker result goes t…
V3RON Oct 21, 2026
1a827c6
feat(console): Enter on a page, worker, device, lease or request resu…
V3RON Oct 21, 2026
0b00329
test: every row of the In short table gives the results it lists (#770)
V3RON Oct 21, 2026
79f924a
feat(console): the search filters by word, ranks whole words first an…
V3RON Oct 21, 2026
800039b
test: drain <worker> and Enter drains it with the menu's toast and Un…
V3RON Oct 21, 2026
18e45e5
feat(console): Enter on an action runs it through the menus' runner (…
V3RON Oct 21, 2026
f15c525
test: ↑ and ↓ move the highlight, and Enter runs the highlighted resu…
V3RON Oct 21, 2026
1cec269
test: no results shows "No results for <text>" (#770)
V3RON Oct 21, 2026
e459fb5
feat(console): the search says when nothing matches (#770)
V3RON Oct 21, 2026
6a9c620
test: ⌘K does nothing while a drawer is open (#770)
V3RON Oct 21, 2026
4bc27ce
feat(console): ⌘K does nothing while a drawer or dialog is open (#770)
V3RON Oct 21, 2026
00a98e2
test: opened before the data loads, the groups show Loading… and fill…
V3RON Oct 21, 2026
97292bf
feat(console): groups still loading say so and fill in while the high…
V3RON Oct 21, 2026
f946110
test: a live update while the dialog is open does not change the list…
V3RON Oct 21, 2026
cf833e3
test: axe passes with the search open, in light and dark; it adds no …
V3RON Oct 21, 2026
4afe321
docs: the console's search, its keyboard shortcut and its dialog (#770)
V3RON Oct 21, 2026
9ee206d
test: the shell's keyboard tour lists the search button after the ski…
V3RON Oct 21, 2026
ebe4dba
refactor(console): the search's statuses and shortcut live in the mod…
V3RON Oct 21, 2026
b5da44b
fix: a loading search group lists no results; ranking test; docs matc…
V3RON Oct 21, 2026
a731227
fix(console): the drawer slides in, its ⋯ shows, and Overview and Usa…
V3RON Oct 21, 2026
b5e4fb4
fix(console): a table outside a panel sits on the same card surface a…
V3RON Oct 21, 2026
cb7a51a
fix(console): a page's list fills the page's height, on a card, even …
V3RON Oct 21, 2026
fa5aeb9
fix(console): the drawer slides out when it closes, then the address …
V3RON Oct 21, 2026
3b4dd25
fix(console): a worker's Events tab sits on a card like its other tab…
V3RON Oct 21, 2026
aa5189d
fix(console): the feed's end line and an empty list's message sit ins…
V3RON Oct 21, 2026
6c57e1a
fix(console): the Inbox's empty state sits on a card, and switching t…
V3RON Oct 21, 2026
06561dc
fix(console): the drawer has no shadow, like the rest of the console …
V3RON Oct 21, 2026
d1b3bff
fix(console): Sign out and Collapse are the same secondary button, ic…
V3RON Oct 21, 2026
8bcf83b
refactor(console): split the capacity count and drop an unused type r…
V3RON Oct 21, 2026
a8e2eb2
docs(adr): one row for 0037 in the index, in order (#770)
V3RON Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion docs/internal/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ put together from them and draws nothing of its own that one of them already dra
- **Long ids** (a lease's, a worker's, a device's) stay on one line, cut with
an ellipsis. The whole id is in the element's `title`, in the text a copy or
a screen reader reads, and on the details page.
- **Search.** A dialog near the top of the page over a dim layer (`--bg`, 1px `--border-strong`),
36rem wide at most: a box, then the results in groups, each group an uppercase label in
`--text-muted` over its rows. The highlighted row is `--field` with the same 2px `--accent`
inset edge as the current page in the sidebar; orange marks interaction only. A group still
loading, or one that failed, shows one `--text-muted` line in place of rows. The box is a
combobox and the list a listbox, and the highlight is the active descendant; it is kept by the
result's id, not its place, so a group that fills in above never moves it. It sits under the
confirm dialog, so an action's confirm opens over it.
- **Buttons.** Primary: filled `--accent` with `--on-accent` text. Secondary:
outlined in `--border-strong`, `--text`. Quiet: text only. All are labels.
- **Inputs.** A `--field` fill and a 1px `--border-strong` border. A select is
Expand All @@ -236,7 +244,7 @@ put together from them and draws nothing of its own that one of them already dra
`--accent`, an area with a faint fill of it (8%), horizontal grid lines in
`--border`, axis labels in Geist Mono `--text-muted`. Every colour comes from
the stylesheet by class. Nothing moves: animation is off. Every chart has a
title saying what it counts, its numbers as a line of text under it, and every bucket as a table behind a disclosure named by the bucket width ("Minute by minute", "Every 5 minutes", "Hour by hour"), so
title saying what it counts, its numbers as a line of text under it, and every bucket in a table only a screen reader reads, so
nothing is visible only in the picture. A chart can be focused, and the
arrow keys step through it. Its focus ring goes round the whole chart, for
keyboard focus only: a click on a chart draws none.
Expand Down Expand Up @@ -271,6 +279,8 @@ put together from them and draws nothing of its own that one of them already dra
for keyboard focus (`:focus-visible`), not on a mouse click.
- The first control on every signed-in page is "Skip to content", visible only
when focused.
- ⌘K and Ctrl+K open the search while the console has focus and no drawer or dialog is open; the
browser's own use of the chord is stopped. Closing the search returns focus to where it was.

## Motion

Expand Down
3 changes: 1 addition & 2 deletions docs/internal/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,5 @@ the status is stale.
| [0034](0034-one-worker-per-user-and-the-folder-says-what-a-daemon-is.md) | One worker per user, and the folder says what a daemon is | Accepted — not yet implemented |
| [0035](0035-a-gateway-sends-chosen-fleet-events-to-webhook-destinations.md) | A gateway sends chosen fleet events to webhook destinations | Accepted — not yet implemented |
| [0036](0036-daemon-state-is-a-sqlite-database-whose-tables-each-owner-keeps.md) | Daemon state is a SQLite database, and each owner keeps its own tables | Accepted — not yet implemented |
| [0038](0038-the-warm-pool-learns-its-kinds-from-leases-and-boots-for-every-queued-request.md) | The warm pool learns its kinds from leases, and boots for every queued request | Accepted — not yet implemented |
| [0037](0037-the-console-acts-through-the-http-routes-on-base-ui.md) | The console acts through the HTTP routes, on Base UI | Proposed |
| [0037](0037-the-console-acts-through-the-http-routes-on-base-ui.md) | The console acts through the HTTP routes, on Base UI | Accepted — not yet implemented |
| [0038](0038-the-warm-pool-learns-its-kinds-from-leases-and-boots-for-every-queued-request.md) | The warm pool learns its kinds from leases, and boots for every queued request | Accepted — not yet implemented |
2 changes: 1 addition & 1 deletion e2e/console/leases.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ test.describe("the leases page", () => {
const title = await boxOf(page.getByRole("heading", { level: 1, name: "Leases" }));
const chips = await boxOf(page.getByRole("group", { name: "Filter leases" }));
const search = await boxOf(page.getByRole("searchbox", { name: "Search leases" }));
const table = await boxOf(page.locator("main table"));
const table = await boxOf(page.locator("main .table-card"));

expect(chips.x).toBeCloseTo(title.x, 0);
expect(search.x).toBeGreaterThan(chips.x + chips.width);
Expand Down
11 changes: 6 additions & 5 deletions e2e/console/overview.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
}

async function tablesOf(page: Page): Promise<readonly (readonly string[])[]> {
const tables = page.locator("#main details.chart-data");
const tables = page.locator("#main table.chart-data");
const count = await tables.count();
return Promise.all(
Array.from({ length: count }, (_, index) =>
Expand Down Expand Up @@ -248,7 +248,7 @@
await expect.poll(() => tileText(page, "Ending soon")).toBe("Ending soon | 0 | under 5 min");
await expect(page.getByRole("region", { name: "Leases held" })).toBeVisible();
await expect(page.getByRole("region", { name: "Requests in the queue" })).toBeVisible();
await expect(page.locator("#main details.chart-data")).toHaveCount(2);
await expect(page.locator("#main table.chart-data")).toHaveCount(2);
await expect(page.getByRole("region", { name: "Activity" })).toHaveCount(0);
} finally {
await host.dispose();
Expand Down Expand Up @@ -308,7 +308,7 @@
}

test.describe("the Overview's Inbox lines", () => {
test("an empty Inbox shows Nothing needs you and no Needs you panel; a disconnected worker shows the panel with that item first, and All in Inbox (1)", async ({
test("an empty Inbox shows Nothing needs you in the Needs you panel; a disconnected worker shows the panel with that item first, and All in Inbox (1)", async ({
page,
}) => {
const fleet = await startFleet([
Expand All @@ -317,8 +317,9 @@
]);
try {
await openOverview(page, fleet.gateway);
await expect(page.getByText("Nothing needs you")).toBeVisible();
await expect(page.getByRole("heading", { name: "Needs you" })).toHaveCount(0);
await expect(
page.getByRole("region", { name: "Needs you" }).getByText("Nothing needs you"),
).toBeVisible();

await (fleet.workers[1] as RunningDaemon).stop();
await waitFor(
Expand Down Expand Up @@ -477,7 +478,7 @@
await page.route(
(url) => url.pathname === "/v1/leases",
async (route: Route) => {
const response = await route.fetch();

Check failure on line 481 in e2e/console/overview.spec.ts

View workflow job for this annotation

GitHub Actions / Console

[firefox] › e2e/console/overview.spec.ts:426:3 › the Overview's five numbers › show the daemon's values: one lease held of four devices with three ready

5) [firefox] › e2e/console/overview.spec.ts:426:3 › the Overview's five numbers › show the daemon's values: one lease held of four devices with three ready, one request waiting with its longest wait, two of two workers, Wait p95, and Ending soon counting a lease with 4 minutes left and not one with 10 Error: route.fetch: connect ECONNREFUSED 127.0.0.1:41749 Call log: - → GET http://127.0.0.1:41749/v1/leases - user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:155.0) Gecko/20100101 Firefox/155.0 - accept: */* - accept-encoding: gzip, deflate, br, zstd - host: 127.0.0.1:41749 - accept-language: en-US - sec-fetch-dest: empty - sec-fetch-mode: cors - sec-fetch-site: same-origin - authorization: *** - connection: keep-alive 479 | (url) => url.pathname === "/v1/leases", 480 | async (route: Route) => { > 481 | const response = await route.fetch(); | ^ 482 | const now = new Date(response.headers().date ?? "").getTime(); 483 | const { leases } = (await response.json()) as { 484 | leases: { id: string; ttlDeadline: number }[]; at /home/runner/work/simlock/simlock/e2e/console/overview.spec.ts:481:40
const now = new Date(response.headers().date ?? "").getTime();
const { leases } = (await response.json()) as {
leases: { id: string; ttlDeadline: number }[];
Expand Down
Loading
Loading