@post-print/agent-test 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/viewer/styles.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,IAAI,MAAM,CA+FlC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/viewer/styles.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,IAAI,MAAM,CAkHlC"}
@@ -92,6 +92,25 @@ export function viewerCss() {
92
92
  button:disabled { cursor: not-allowed; opacity: 0.5; }
93
93
  summary { list-style: none; }
94
94
  summary::-webkit-details-marker { display: none; }
95
+ dialog[data-mobile-drawer="true"]::backdrop {
96
+ background: oklch(0.07 0.02 258 / 0.72);
97
+ animation: viewer-drawer-backdrop-in 160ms ease-out;
98
+ }
99
+ dialog[data-mobile-drawer="true"][open] {
100
+ animation: viewer-drawer-in 180ms ease-out;
101
+ }
102
+ @keyframes viewer-drawer-in {
103
+ from { transform: translateX(-100%); }
104
+ to { transform: translateX(0); }
105
+ }
106
+ @keyframes viewer-drawer-backdrop-in {
107
+ from { background: transparent; }
108
+ to { background: oklch(0.07 0.02 258 / 0.72); }
109
+ }
110
+ @media (prefers-reduced-motion: reduce) {
111
+ dialog[data-mobile-drawer="true"][open],
112
+ dialog[data-mobile-drawer="true"]::backdrop { animation: none; }
113
+ }
95
114
  `;
96
115
  }
97
116
  //# sourceMappingURL=styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/viewer/styles.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACxB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6FL,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/viewer/styles.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACxB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHL,CAAC;AACJ,CAAC"}
@@ -114,6 +114,10 @@
114
114
  padding: .65rem .7rem;
115
115
  }
116
116
 
117
+ .x1ri45tz {
118
+ padding: .65rem .85rem;
119
+ }
120
+
117
121
  .x1i4hug3 {
118
122
  padding: .65rem .8rem;
119
123
  }
@@ -571,6 +575,11 @@
571
575
  box-shadow: 0 1px 2px lab(.441307% .0500679 -1.52896 / .35);
572
576
  }
573
577
 
578
+ .x11t4c4f {
579
+ box-shadow: 0 1rem 3rem #00010373;
580
+ box-shadow: 0 1rem 3rem lab(.180326% .0797361 -.947684 / .45);
581
+ }
582
+
574
583
  .x1gnnqk1 {
575
584
  box-shadow: none;
576
585
  }
@@ -758,6 +767,14 @@
758
767
  font-size: 1.08rem;
759
768
  }
760
769
 
770
+ .x1gqo1bu {
771
+ font-size: 1.15rem;
772
+ }
773
+
774
+ .x1jchvi3 {
775
+ font-size: 1rem;
776
+ }
777
+
761
778
  .x1t69poc {
762
779
  font-size: clamp(1.08rem, 1.5vw, 1.3rem);
763
780
  }
@@ -838,6 +855,10 @@
838
855
  grid-template-columns: minmax(0, 1fr) max-content;
839
856
  }
840
857
 
858
+ .x1mkdm3x {
859
+ grid-template-columns: minmax(0, 1fr);
860
+ }
861
+
841
862
  .x190l7ji {
842
863
  grid-template-columns: minmax(7.5rem, .3fr) minmax(0, 1fr);
843
864
  }
@@ -850,6 +871,10 @@
850
871
  grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
851
872
  }
852
873
 
874
+ .x16p6thf {
875
+ grid-template-rows: auto minmax(0, 1fr);
876
+ }
877
+
853
878
  .xl56j7k {
854
879
  justify-content: center;
855
880
  }
@@ -886,6 +911,10 @@
886
911
  letter-spacing: -.025em;
887
912
  }
888
913
 
914
+ .x72az59 {
915
+ letter-spacing: -.02em;
916
+ }
917
+
889
918
  .x1yf5rgg {
890
919
  letter-spacing: .01em;
891
920
  }
@@ -978,6 +1007,10 @@
978
1007
  position: fixed;
979
1008
  }
980
1009
 
1010
+ .x7wzq59 {
1011
+ position: sticky;
1012
+ }
1013
+
981
1014
  .x1rohswg {
982
1015
  scrollbar-width: none;
983
1016
  }
@@ -1018,6 +1051,10 @@
1018
1051
  z-index: 10;
1019
1052
  }
1020
1053
 
1054
+ .xhtitgo {
1055
+ z-index: 2;
1056
+ }
1057
+
1021
1058
  .x784prv:focus-visible {
1022
1059
  outline-width: 2px;
1023
1060
  }
@@ -1088,8 +1125,8 @@
1088
1125
  }
1089
1126
  }
1090
1127
 
1091
- @media (width >= 620.01px) and (width <= 820px) {
1092
- .xoh86gq.xoh86gq {
1128
+ @media (width <= 820px) {
1129
+ .x17wzt7p.x17wzt7p {
1093
1130
  grid-template-columns: 14rem minmax(0, 1fr);
1094
1131
  }
1095
1132
  }
@@ -1183,10 +1220,18 @@
1183
1220
  height: 1.8rem;
1184
1221
  }
1185
1222
 
1223
+ .x5yr21d {
1224
+ height: 100%;
1225
+ }
1226
+
1186
1227
  .xtdtrs8 {
1187
1228
  height: 100dvh;
1188
1229
  }
1189
1230
 
1231
+ .x12hms15 {
1232
+ height: 2.75rem;
1233
+ }
1234
+
1190
1235
  .x1hagigm {
1191
1236
  height: 7px;
1192
1237
  }
@@ -1259,6 +1304,10 @@
1259
1304
  max-width: 88rem;
1260
1305
  }
1261
1306
 
1307
+ .x1x1rfll {
1308
+ max-width: none;
1309
+ }
1310
+
1262
1311
  .x2lwn1j {
1263
1312
  min-height: 0;
1264
1313
  }
@@ -1319,6 +1368,10 @@
1319
1368
  top: .75rem;
1320
1369
  }
1321
1370
 
1371
+ .x13vifvy {
1372
+ top: 0;
1373
+ }
1374
+
1322
1375
  .x1tkjwfh {
1323
1376
  width: .28rem;
1324
1377
  }
@@ -1347,6 +1400,10 @@
1347
1400
  width: 100%;
1348
1401
  }
1349
1402
 
1403
+ .xb1qrhf {
1404
+ width: 2.75rem;
1405
+ }
1406
+
1350
1407
  .x1xb5dxl {
1351
1408
  width: 2.8rem;
1352
1409
  }
@@ -1359,18 +1416,12 @@
1359
1416
  width: fit-content;
1360
1417
  }
1361
1418
 
1362
- .xgfx6k7 {
1363
- width: min(86%, 46rem);
1419
+ .x2u06rm {
1420
+ width: min(22rem, 100vw - 2.75rem);
1364
1421
  }
1365
1422
 
1366
- @media (width <= 620px) {
1367
- .xvfkbv4.xvfkbv4 {
1368
- height: auto;
1369
- }
1370
-
1371
- .xjkoizw.xjkoizw {
1372
- max-height: 18rem;
1373
- }
1423
+ .xgfx6k7 {
1424
+ width: min(86%, 46rem);
1374
1425
  }
1375
1426
  }
1376
1427
 
@@ -1 +1 @@
1
- {"version":3,"file":"v2-client.d.ts","sourceRoot":"","sources":["../../src/viewer/v2-client.tsx"],"names":[],"mappings":"AA4DA,KAAK,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AA2ChD,eAAO,MAAM,YAAY,uuCAnBC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,msDAqBzF,CAAC"}
1
+ {"version":3,"file":"v2-client.d.ts","sourceRoot":"","sources":["../../src/viewer/v2-client.tsx"],"names":[],"mappings":"AAgEA,KAAK,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AA4ChD,eAAO,MAAM,YAAY,uuCAnBC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,msDAqBzF,CAAC"}
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  import * as stylex from "@stylexjs/stylex";
3
3
  import { useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { createRootRoute, createRoute, createRouter, Link, Outlet, useNavigate, } from "@tanstack/react-router";
5
- import { createContext, useContext, useId, useState, } from "react";
5
+ import { createContext, useCallback, useContext, useEffect, useId, useRef, useState, } from "react";
6
6
  import Markdown from "react-markdown";
7
7
  import { viewerApi } from "./generated-api.js";
8
8
  import { assertionComparison, conversationPlaceholder, preferredExecutionId, stripAnsi, } from "./presentation.js";
@@ -14,6 +14,7 @@ const runningPulse = stylex.keyframes({
14
14
  });
15
15
  const CAMEL_CASE_BOUNDARY = /([a-z])([A-Z])/g;
16
16
  const INITIAL_CHARACTER = /^./;
17
+ const NARROW_VIEWER_QUERY = "(max-width: 820px)";
17
18
  const WorkerContext = createContext({ workers: 1, setWorkers: () => undefined });
18
19
  const rootRoute = createRootRoute({ component: ViewerLayout });
19
20
  const indexRoute = createRoute({
@@ -69,11 +70,11 @@ const styles = stylex.create({
69
70
  gridTemplateColumns: {
70
71
  default: "18rem minmax(0, 1fr)",
71
72
  "@media (max-width: 820px)": "14rem minmax(0, 1fr)",
72
- "@media (max-width: 620px)": "1fr",
73
73
  },
74
74
  height: "100dvh",
75
75
  minHeight: 0,
76
76
  },
77
+ shellNarrow: { gridTemplateColumns: "minmax(0, 1fr)", gridTemplateRows: "auto minmax(0, 1fr)" },
77
78
  shellCollapsed: { gridTemplateColumns: "3.75rem minmax(0, 1fr)" },
78
79
  sidebar: {
79
80
  borderRight: "1px solid var(--border)",
@@ -83,10 +84,54 @@ const styles = stylex.create({
83
84
  padding: "1rem 0 0",
84
85
  backgroundColor: "var(--sidebar)",
85
86
  minHeight: 0,
86
- height: { default: "100dvh", "@media (max-width: 620px)": "auto" },
87
- maxHeight: { default: "none", "@media (max-width: 620px)": "18rem" },
87
+ height: "100dvh",
88
88
  },
89
89
  sidebarCollapsed: { paddingTop: "1rem", height: "100dvh", maxHeight: "none" },
90
+ mobileHeader: {
91
+ position: "sticky",
92
+ top: 0,
93
+ zIndex: 2,
94
+ display: "flex",
95
+ alignItems: "center",
96
+ gap: "0.75rem",
97
+ minWidth: 0,
98
+ padding: "0.65rem 0.85rem",
99
+ borderBottom: "1px solid var(--border)",
100
+ backgroundColor: "var(--sidebar)",
101
+ },
102
+ mobileMenuButton: {
103
+ width: "2.75rem",
104
+ height: "2.75rem",
105
+ padding: 0,
106
+ borderRadius: 9,
107
+ backgroundColor: { default: "var(--panel-2)", ":hover": "var(--panel-3)" },
108
+ color: "var(--text)",
109
+ fontSize: "1.15rem",
110
+ cursor: "pointer",
111
+ },
112
+ mobileHeaderIdentity: { display: "flex", alignItems: "center", gap: "0.6rem", minWidth: 0 },
113
+ mobileHeaderTitle: { fontSize: "1rem", fontWeight: 720, letterSpacing: "-0.02em" },
114
+ mobileDrawerDialog: {
115
+ width: "min(22rem, calc(100vw - 2.75rem))",
116
+ maxWidth: "none",
117
+ height: "100dvh",
118
+ maxHeight: "none",
119
+ margin: 0,
120
+ padding: 0,
121
+ borderWidth: 0,
122
+ backgroundColor: "var(--sidebar)",
123
+ color: "var(--text)",
124
+ overflow: "hidden",
125
+ },
126
+ mobileDrawerSurface: {
127
+ display: "flex",
128
+ flexDirection: "column",
129
+ height: "100%",
130
+ minHeight: 0,
131
+ paddingTop: "1rem",
132
+ backgroundColor: "var(--sidebar)",
133
+ boxShadow: "0 1rem 3rem oklch(0.06 0.02 258 / 0.45)",
134
+ },
90
135
  main: {
91
136
  overflow: "auto",
92
137
  minWidth: 0,
@@ -139,6 +184,7 @@ const styles = stylex.create({
139
184
  lineHeight: 1,
140
185
  boxShadow: "none",
141
186
  },
187
+ mobileCloseButton: { width: "2.75rem", height: "2.75rem", fontSize: "1.15rem" },
142
188
  sidebarTitleRow: {
143
189
  display: "flex",
144
190
  alignItems: "center",
@@ -1102,20 +1148,74 @@ const styles = stylex.create({
1102
1148
  });
1103
1149
  function ViewerLayout() {
1104
1150
  const [sidebarOpen, setSidebarOpen] = useState(true);
1151
+ const [drawerOpen, setDrawerOpen] = useState(false);
1105
1152
  const [workers, setWorkers] = useState(1);
1106
- return (_jsx(WorkerContext.Provider, { value: { workers, setWorkers }, children: _jsxs("div", { ...stylex.props(styles.shell, !sidebarOpen && styles.shellCollapsed), children: [_jsx("a", { href: "#viewer-main", ...stylex.props(styles.skipLink), children: "Skip to content" }), _jsx(ViewerSidebar, { open: sidebarOpen, onToggle: () => setSidebarOpen((open) => !open) }), _jsx("main", { id: "viewer-main", tabIndex: -1, ...stylex.props(styles.main), children: _jsx(Outlet, {}) })] }) }));
1153
+ const narrow = useNarrowViewer();
1154
+ const menuButton = useRef(null);
1155
+ const closeDrawer = useCallback(() => setDrawerOpen(false), []);
1156
+ useEffect(() => {
1157
+ if (!narrow)
1158
+ setDrawerOpen(false);
1159
+ }, [narrow]);
1160
+ return (_jsx(WorkerContext.Provider, { value: { workers, setWorkers }, children: _jsxs("div", { ...stylex.props(styles.shell, narrow && styles.shellNarrow, !narrow && !sidebarOpen && styles.shellCollapsed), children: [_jsx("a", { href: "#viewer-main", ...stylex.props(styles.skipLink), children: "Skip to content" }), narrow ? (_jsxs(_Fragment, { children: [_jsx(MobileViewerHeader, { buttonRef: menuButton, open: drawerOpen, onOpen: () => setDrawerOpen(true) }), _jsx(MobileTestDrawer, { open: drawerOpen, onClose: closeDrawer })] })) : (_jsx(ViewerSidebar, { open: sidebarOpen, onToggle: () => setSidebarOpen((open) => !open) })), _jsx("main", { id: "viewer-main", tabIndex: -1, ...stylex.props(styles.main), children: _jsx(Outlet, {}) })] }) }));
1161
+ }
1162
+ function useNarrowViewer() {
1163
+ const [narrow, setNarrow] = useState(() => window.matchMedia(NARROW_VIEWER_QUERY).matches);
1164
+ useEffect(() => {
1165
+ const query = window.matchMedia(NARROW_VIEWER_QUERY);
1166
+ const update = () => setNarrow(query.matches);
1167
+ update();
1168
+ query.addEventListener("change", update);
1169
+ return () => query.removeEventListener("change", update);
1170
+ }, []);
1171
+ return narrow;
1107
1172
  }
1108
1173
  function useCatalog() {
1109
1174
  return useQuery({ queryKey: ["test-catalog"], queryFn: fetchTestCatalog });
1110
1175
  }
1176
+ function MobileViewerHeader({ buttonRef, open, onOpen, }) {
1177
+ const catalog = useCatalog();
1178
+ return (_jsxs("header", { ...stylex.props(styles.mobileHeader), children: [_jsx("button", { ref: buttonRef, type: "button", "aria-haspopup": "dialog", "aria-controls": "mobile-test-drawer", "aria-expanded": open, "aria-label": "Open test menu", ...stylex.props(styles.buttonReset, styles.mobileMenuButton), onClick: onOpen, children: _jsx("span", { "aria-hidden": "true", children: "\u2630" }) }), _jsxs("div", { ...stylex.props(styles.mobileHeaderIdentity), children: [_jsx("span", { ...stylex.props(styles.mobileHeaderTitle), children: "Tests" }), _jsx("span", { ...stylex.props(styles.countBadge), children: catalog.data?.tests.length ?? 0 })] })] }));
1179
+ }
1180
+ function MobileTestDrawer({ open, onClose }) {
1181
+ const dialog = useRef(null);
1182
+ useEffect(() => {
1183
+ const element = dialog.current;
1184
+ if (!element)
1185
+ return;
1186
+ const closeOnBackdrop = (event) => {
1187
+ if (event.target === element)
1188
+ onClose();
1189
+ };
1190
+ element.addEventListener("click", closeOnBackdrop);
1191
+ let focusFrame;
1192
+ if (open && !element.open) {
1193
+ element.showModal();
1194
+ focusFrame = requestAnimationFrame(() => {
1195
+ element.querySelector("[data-drawer-close]")?.focus();
1196
+ });
1197
+ }
1198
+ if (!open && element.open)
1199
+ element.close();
1200
+ return () => {
1201
+ element.removeEventListener("click", closeOnBackdrop);
1202
+ if (focusFrame !== undefined)
1203
+ cancelAnimationFrame(focusFrame);
1204
+ };
1205
+ }, [onClose, open]);
1206
+ return (_jsx("dialog", { ref: dialog, id: "mobile-test-drawer", "data-mobile-drawer": "true", "aria-labelledby": "mobile-tests-title", ...stylex.props(styles.mobileDrawerDialog), onCancel: onClose, onClose: onClose, children: _jsx("div", { ...stylex.props(styles.mobileDrawerSurface), children: _jsx(ViewerSidebarContent, { mode: "mobile", headingId: "mobile-tests-title", navigationId: "mobile-test-navigation", onClose: onClose }) }) }));
1207
+ }
1111
1208
  function ViewerSidebar({ open, onToggle }) {
1209
+ return (_jsx("aside", { ...stylex.props(styles.sidebar, !open && styles.sidebarCollapsed), children: _jsx(ViewerSidebarContent, { mode: "desktop", open: open, navigationId: "test-navigation", onToggle: onToggle }) }));
1210
+ }
1211
+ function ViewerSidebarContent({ mode, open = true, headingId, navigationId, onToggle, onClose, }) {
1112
1212
  const catalog = useCatalog();
1113
1213
  const history = useExecutionHistory();
1114
1214
  const groups = groupTests(catalog.data?.tests ?? []);
1115
1215
  const statuses = latestTestStatuses(history.data ?? []);
1116
- return (_jsxs("aside", { ...stylex.props(styles.sidebar, !open && styles.sidebarCollapsed), children: [_jsx(SidebarHeader, { open: open, count: catalog.data?.tests.length ?? 0, onToggle: onToggle }), open ? (_jsx(SidebarNavigation, { groups: groups, statuses: statuses, error: catalog.isError })) : null] }));
1216
+ return (_jsxs(_Fragment, { children: [_jsx(SidebarHeader, { mode: mode, open: open, count: catalog.data?.tests.length ?? 0, headingId: headingId, navigationId: navigationId, onToggle: mode === "mobile" ? onClose : onToggle, onNavigate: onClose }), open ? (_jsx(SidebarNavigation, { groups: groups, statuses: statuses, error: catalog.isError, navigationId: navigationId, onNavigate: onClose })) : null] }));
1117
1217
  }
1118
- function SidebarHeader({ open, count, onToggle, }) {
1218
+ function SidebarHeader({ mode, open, count, headingId, navigationId, onToggle, onNavigate, }) {
1119
1219
  const { workers } = useContext(WorkerContext);
1120
1220
  const navigate = useNavigate();
1121
1221
  const client = useQueryClient();
@@ -1124,9 +1224,10 @@ function SidebarHeader({ open, count, onToggle, }) {
1124
1224
  onSuccess: ({ executionId }) => {
1125
1225
  void client.invalidateQueries({ queryKey: ["execution-history"] });
1126
1226
  void navigate({ to: "/executions/$executionId", params: { executionId } });
1227
+ onNavigate?.();
1127
1228
  },
1128
1229
  });
1129
- return (_jsx("header", { ...stylex.props(styles.sidebarHeader, !open && styles.sidebarHeaderCollapsed), children: open ? (_jsxs(_Fragment, { children: [_jsxs("div", { ...stylex.props(styles.sidebarTitleRow), children: [_jsxs("div", { ...stylex.props(styles.sidebarTitleIdentity), children: [_jsx("h1", { ...stylex.props(styles.title, styles.sidebarTitle), children: "Tests" }), _jsx("span", { ...stylex.props(styles.countBadge), children: count })] }), _jsx(SidebarToggle, { open: open, onToggle: onToggle })] }), _jsxs("div", { ...stylex.props(styles.suiteControls), children: [_jsxs("button", { type: "button", ...stylex.props(styles.buttonReset, styles.suiteRunButton), onClick: () => run.mutate(), disabled: run.isPending || count === 0, children: [_jsx("span", { "aria-hidden": "true", children: run.isPending ? "●" : "▶" }), run.isPending ? "Starting suite…" : "Run all tests"] }), _jsx(WorkerControl, {})] }), run.isError ? _jsx("p", { role: "alert", children: run.error.message }) : null] })) : (_jsx(SidebarToggle, { open: open, onToggle: onToggle })) }));
1230
+ return (_jsx("header", { ...stylex.props(styles.sidebarHeader, !open && styles.sidebarHeaderCollapsed), children: open ? (_jsxs(_Fragment, { children: [_jsxs("div", { ...stylex.props(styles.sidebarTitleRow), children: [_jsxs("div", { ...stylex.props(styles.sidebarTitleIdentity), children: [_jsx("h1", { id: headingId, ...stylex.props(styles.title, styles.sidebarTitle), children: "Tests" }), _jsx("span", { ...stylex.props(styles.countBadge), children: count })] }), _jsx(SidebarToggle, { mode: mode, open: open, navigationId: navigationId, onToggle: onToggle })] }), _jsxs("div", { ...stylex.props(styles.suiteControls), children: [_jsxs("button", { type: "button", ...stylex.props(styles.buttonReset, styles.suiteRunButton), onClick: () => run.mutate(), disabled: run.isPending || count === 0, children: [_jsx("span", { "aria-hidden": "true", children: run.isPending ? "●" : "▶" }), run.isPending ? "Starting suite…" : "Run all tests"] }), _jsx(WorkerControl, {})] }), run.isError ? _jsx("p", { role: "alert", children: run.error.message }) : null] })) : (_jsx(SidebarToggle, { mode: mode, open: open, navigationId: navigationId, onToggle: onToggle })) }));
1130
1231
  }
1131
1232
  function WorkerControl() {
1132
1233
  const { workers, setWorkers } = useContext(WorkerContext);
@@ -1136,13 +1237,14 @@ function WorkerControl() {
1136
1237
  setWorkers(Math.min(32, Math.max(1, next)));
1137
1238
  } })] }));
1138
1239
  }
1139
- function SidebarToggle({ open, onToggle }) {
1140
- return (_jsx("button", { type: "button", "aria-controls": "test-navigation", "aria-expanded": open, "aria-label": open ? "Collapse test sidebar" : "Expand test sidebar", ...stylex.props(styles.buttonReset, styles.toggleButton), onClick: onToggle, children: open ? "←" : "→" }));
1240
+ function SidebarToggle({ mode, open, navigationId, onToggle, }) {
1241
+ const mobile = mode === "mobile";
1242
+ return (_jsx("button", { type: "button", "data-drawer-close": mobile ? "true" : undefined, "aria-controls": navigationId, "aria-expanded": open, "aria-label": mobile ? "Close test menu" : open ? "Collapse test sidebar" : "Expand test sidebar", ...stylex.props(styles.buttonReset, styles.toggleButton, mobile && styles.mobileCloseButton), onClick: onToggle, children: mobile ? "×" : open ? "←" : "→" }));
1141
1243
  }
1142
- function SidebarNavigation({ groups, statuses, error, }) {
1143
- return (_jsxs(_Fragment, { children: [error ? _jsx("p", { role: "alert", children: "Test discovery is unavailable." }) : null, _jsx("nav", { id: "test-navigation", "aria-label": "Tests", ...stylex.props(styles.navigation), children: [...groups].map(([name, tests]) => (_jsxs("section", { "aria-label": `${name} tests`, ...stylex.props(styles.navSection), children: [_jsxs("div", { ...stylex.props(styles.groupHeader), children: [_jsx("strong", { ...stylex.props(styles.groupLabel), children: name }), _jsxs("div", { ...stylex.props(styles.groupHeaderActions), children: [_jsx("span", { ...stylex.props(styles.groupCount), children: tests.length }), _jsx(RunTestGroupButton, { name: name, tests: tests })] })] }), tests.map((test) => (_jsx(TestLink, { test: test, status: statuses.get(test.id) }, test.id)))] }, name))) })] }));
1244
+ function SidebarNavigation({ groups, statuses, error, navigationId, onNavigate, }) {
1245
+ return (_jsxs(_Fragment, { children: [error ? _jsx("p", { role: "alert", children: "Test discovery is unavailable." }) : null, _jsx("nav", { id: navigationId, "aria-label": "Tests", ...stylex.props(styles.navigation), children: [...groups].map(([name, tests]) => (_jsxs("section", { "aria-label": `${name} tests`, ...stylex.props(styles.navSection), children: [_jsxs("div", { ...stylex.props(styles.groupHeader), children: [_jsx("strong", { ...stylex.props(styles.groupLabel), children: name }), _jsxs("div", { ...stylex.props(styles.groupHeaderActions), children: [_jsx("span", { ...stylex.props(styles.groupCount), children: tests.length }), _jsx(RunTestGroupButton, { name: name, tests: tests, onNavigate: onNavigate })] })] }), tests.map((test) => (_jsx(TestLink, { test: test, status: statuses.get(test.id), onNavigate: onNavigate }, test.id)))] }, name))) })] }));
1144
1246
  }
1145
- function RunTestGroupButton({ name, tests }) {
1247
+ function RunTestGroupButton({ name, tests, onNavigate, }) {
1146
1248
  const { workers } = useContext(WorkerContext);
1147
1249
  const navigate = useNavigate();
1148
1250
  const client = useQueryClient();
@@ -1151,12 +1253,13 @@ function RunTestGroupButton({ name, tests }) {
1151
1253
  onSuccess: ({ executionId }) => {
1152
1254
  void client.invalidateQueries({ queryKey: ["execution-history"] });
1153
1255
  void navigate({ to: "/executions/$executionId", params: { executionId } });
1256
+ onNavigate?.();
1154
1257
  },
1155
1258
  });
1156
1259
  return (_jsx("button", { type: "button", "aria-label": `Run ${name} suite`, title: `Run ${name} suite`, ...stylex.props(styles.buttonReset, styles.groupRunButton), onClick: () => run.mutate(), disabled: run.isPending, children: run.isPending ? "●" : "▶" }));
1157
1260
  }
1158
- function TestLink({ test, status }) {
1159
- return (_jsxs(Link, { to: "/tests/$testId", params: { testId: test.id }, search: {}, ...stylex.props(styles.navLink), activeProps: stylex.props(styles.navLink, styles.active), children: [_jsxs("div", { ...stylex.props(styles.navItemHeader), children: [status ? _jsx(TestStatus, { status: status }) : _jsx("span", { "aria-hidden": "true" }), _jsx("span", { ...stylex.props(styles.navItemTitle), children: test.title.at(-1) })] }), test.project !== "default" ? _jsx("div", { ...stylex.props(styles.meta), children: test.project }) : null] }));
1261
+ function TestLink({ test, status, onNavigate, }) {
1262
+ return (_jsxs(Link, { to: "/tests/$testId", params: { testId: test.id }, search: {}, ...stylex.props(styles.navLink), activeProps: stylex.props(styles.navLink, styles.active), onClick: onNavigate, children: [_jsxs("div", { ...stylex.props(styles.navItemHeader), children: [status ? _jsx(TestStatus, { status: status }) : _jsx("span", { "aria-hidden": "true" }), _jsx("span", { ...stylex.props(styles.navItemTitle), children: test.title.at(-1) })] }), test.project !== "default" ? _jsx("div", { ...stylex.props(styles.meta), children: test.project }) : null] }));
1160
1263
  }
1161
1264
  function TestStatus({ status }) {
1162
1265
  return (_jsx("span", { role: "img", "aria-label": `Latest execution: ${status}`, title: `Latest execution: ${status}`, ...stylex.props(styles.navStatus), children: _jsx("span", { "aria-hidden": "true", ...stylex.props(styles.navStatusDot, status === "passed" && styles.navStatusDotPass, status === "failed" && styles.navStatusDotFail, status === "running" && styles.navStatusDotRunning) }) }));