From 9754c59f5dc64f4c13e4f64aff44d02cd548db63 Mon Sep 17 00:00:00 2001
From: Jessica Smith <12jessicasmith34@gmail.com>
Date: Wed, 10 Jun 2026 23:11:17 -0500
Subject: [PATCH 1/8] fix(examples): add required name= to bus listener
registrations
The name= parameter became mandatory for DB-registered listeners but
five example apps were never updated, so every demo app failed at
startup with ListenerNameRequiredError.
---
examples/climate_controller.py | 3 +++
examples/cover_scheduler.py | 6 ++++--
examples/demo_stimulator.py | 1 +
examples/motion_lights.py | 2 ++
examples/presence_tracker.py | 1 +
5 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/examples/climate_controller.py b/examples/climate_controller.py
index ee0072d1d..20aaa94a1 100644
--- a/examples/climate_controller.py
+++ b/examples/climate_controller.py
@@ -42,6 +42,7 @@ async def on_initialize(self) -> None:
"sensor.*temperature*",
changed=C.Increased(),
handler=self.on_temp_increased,
+ name="climate_controller.on_temp_increased",
)
await self.bus.on_state_change(
@@ -49,6 +50,7 @@ async def on_initialize(self) -> None:
changed=C.Decreased(),
changed_from=C.Present(),
handler=self.on_temp_decreased,
+ name="climate_controller.on_temp_decreased",
)
# Watch HVAC current_temperature attribute
@@ -56,6 +58,7 @@ async def on_initialize(self) -> None:
cfg.climate_entity,
"current_temperature",
handler=self.on_hvac_temp_change,
+ name="climate_controller.on_hvac_temp_change",
)
# Periodic climate summary — group for easy filtering in the dashboard
diff --git a/examples/cover_scheduler.py b/examples/cover_scheduler.py
index 17a25a93b..3a572b438 100644
--- a/examples/cover_scheduler.py
+++ b/examples/cover_scheduler.py
@@ -70,10 +70,12 @@ async def on_initialize(self) -> None:
await self.scheduler.run_in(self.report_sun_state, 10, name="startup_sun_report")
# Listen for any cover state changes
- await self.bus.on_state_change("cover.*", handler=self.on_cover_change)
+ await self.bus.on_state_change("cover.*", handler=self.on_cover_change, name="cover_scheduler.on_cover_change")
# One-time listener: log when sun state first changes
- await self.bus.on_state_change("sun.sun", handler=self.on_sun_first_change, once=True)
+ await self.bus.on_state_change(
+ "sun.sun", handler=self.on_sun_first_change, once=True, name="cover_scheduler.on_sun_first_change"
+ )
async def on_shutdown(self) -> None:
"""Persist cover positions to cache before stopping."""
diff --git a/examples/demo_stimulator.py b/examples/demo_stimulator.py
index e505e3854..ba451612d 100644
--- a/examples/demo_stimulator.py
+++ b/examples/demo_stimulator.py
@@ -39,6 +39,7 @@ async def on_initialize(self) -> None:
await self.bus.on_state_change(
"input_boolean.test_toggle",
handler=self.on_toggle_changed,
+ name="demo_stimulator.on_toggle_changed",
)
await self.scheduler.run_in(self.trigger_activity_burst, BURST_DELAY_SECONDS, name="initial_burst")
diff --git a/examples/motion_lights.py b/examples/motion_lights.py
index 47b4410e2..ca1cecd46 100644
--- a/examples/motion_lights.py
+++ b/examples/motion_lights.py
@@ -42,6 +42,7 @@ async def on_initialize(self) -> None:
cfg.motion_entity,
changed_to="on",
handler=self.on_motion_detected,
+ name="motion_lights.on_motion_detected",
)
# Motion cleared → turn light off after a delay
@@ -50,6 +51,7 @@ async def on_initialize(self) -> None:
changed_to="off",
handler=self.on_motion_cleared,
debounce=cfg.off_delay,
+ name="motion_lights.on_motion_cleared",
)
# Log the current state of the motion sensor
diff --git a/examples/presence_tracker.py b/examples/presence_tracker.py
index 9545dc1a3..230b24203 100644
--- a/examples/presence_tracker.py
+++ b/examples/presence_tracker.py
@@ -42,6 +42,7 @@ async def on_initialize(self) -> None:
await self.bus.on_state_change(
cfg.tracker_entity,
handler=self.on_tracker_change,
+ name="presence_tracker.on_tracker_change",
)
# Periodic status log — group for easy filtering in the dashboard
From 8d44e61a0e1bcf95ada0044a51292671efe1cfbd Mon Sep 17 00:00:00 2001
From: Jessica Smith <12jessicasmith34@gmail.com>
Date: Wed, 10 Jun 2026 23:11:31 -0500
Subject: [PATCH 2/8] fix(ui): keep fixed table layout on mobile to stop column
cropping
Tables flipped to table-layout: auto at 768px, which let unbreakable
mono content (app keys, log messages) push tables past the viewport
and crop columns mid-word. Fixed-layout tables now stay fixed on
mobile: the apps table colgroup moves to CSS module classes so media
queries can reallocate all width to the visible columns, app names
truncate with ellipsis, and the log table's existing mobile colgroup
widths take effect again.
---
frontend/src/pages/apps.module.css | 57 ++++++++++++++++++++++++++----
frontend/src/pages/apps.tsx | 12 +++----
frontend/src/styles/tables.css | 4 ++-
tests/e2e/test_responsive.py | 12 +++++--
4 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/frontend/src/pages/apps.module.css b/frontend/src/pages/apps.module.css
index 2b5f3033a..2e9bfdf68 100644
--- a/frontend/src/pages/apps.module.css
+++ b/frontend/src/pages/apps.module.css
@@ -32,6 +32,32 @@
letter-spacing: var(--tr-label-wide);
}
+/* Column widths — reshaped per breakpoint to match the visible column set */
+
+.colName {
+ width: 35%;
+}
+
+.colStatus {
+ width: 12%;
+}
+
+.colError {
+ width: 22%;
+}
+
+.colRuns {
+ width: 10%;
+}
+
+.colLast {
+ width: 11%;
+}
+
+.colActions {
+ width: 10%;
+}
+
/* Table rows */
.row {
@@ -63,6 +89,13 @@
min-width: 0;
}
+.nameCellInner a {
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
.expandGutter {
width: var(--sp-4);
flex-shrink: 0;
@@ -167,10 +200,25 @@
justify-content: center;
}
- .appsTable {
- table-layout: auto;
+ /* Reallocate all width to the two visible columns; the hidden columns'
+ cols get 0 so fixed layout doesn't reserve space for them. */
+ .colName {
+ width: 68%;
+ }
+
+ .colStatus {
+ width: 32%;
+ }
+
+ .colError,
+ .colRuns,
+ .colLast,
+ .colActions {
+ width: 0;
}
+ /* Hide everything except name + status (including actions — rows
+ navigate to the detail page on mobile). */
.appsTable thead th:nth-child(n + 3),
.appsTable tbody td:nth-child(n + 3) {
display: none;
@@ -185,11 +233,6 @@
display: none;
}
- .appsTable th:nth-child(n + 3):not(:last-child),
- .appsTable td:nth-child(n + 3):not(:last-child) {
- display: none;
- }
-
.nameCellInner::after {
content: "›";
margin-left: auto;
diff --git a/frontend/src/pages/apps.tsx b/frontend/src/pages/apps.tsx
index 32cc1fa42..809007253 100644
--- a/frontend/src/pages/apps.tsx
+++ b/frontend/src/pages/apps.tsx
@@ -262,12 +262,12 @@ export function AppsPage() {
) : (
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/frontend/src/styles/tables.css b/frontend/src/styles/tables.css
index fd44d398d..ccb9216d1 100644
--- a/frontend/src/styles/tables.css
+++ b/frontend/src/styles/tables.css
@@ -74,8 +74,10 @@
width: 14%;
}
+/* --fixed tables keep fixed layout on mobile: their colgroups define
+ mobile-appropriate widths, and auto layout lets unbreakable mono
+ content push the table past the viewport. */
@media screen and (max-width: 768px) {
- .ht-table--fixed,
.ht-table--compact {
table-layout: auto;
}
diff --git a/tests/e2e/test_responsive.py b/tests/e2e/test_responsive.py
index eb74c3601..5d5f2a4f9 100644
--- a/tests/e2e/test_responsive.py
+++ b/tests/e2e/test_responsive.py
@@ -220,7 +220,12 @@ def test_log_table_no_horizontal_scroll_at_375px(page: Page, base_url: str) -> N
def test_apps_table_columns_fill_width_at_mobile(page: Page, base_url: str) -> None:
- """Visible apps table columns should fill the full table width on mobile."""
+ """Visible apps table columns should fill the full table width on mobile.
+
+ The table keeps table-layout: fixed on mobile (auto layout lets long mono
+ names push the table past the viewport); the colgroup reallocates all
+ width to the two visible columns.
+ """
page.set_viewport_size(MOBILE_VIEWPORT)
page.goto(base_url + "/apps")
@@ -228,7 +233,10 @@ def test_apps_table_columns_fill_width_at_mobile(page: Page, base_url: str) -> N
expect(table).to_be_visible()
table_layout = table.evaluate("el => getComputedStyle(el).tableLayout")
- assert table_layout == "auto", f"Apps table should use table-layout: auto on mobile, got: {table_layout}"
+ assert table_layout == "fixed", f"Apps table should use table-layout: fixed on mobile, got: {table_layout}"
+
+ page_scrollable = page.evaluate("document.documentElement.scrollWidth > document.documentElement.clientWidth")
+ assert not page_scrollable, "Page is horizontally scrollable — apps table is breaking out of viewport"
# ──────────────────────────────────────────────────────────────────────
From 65512eaf03e52b23e1f652018ffd937431257d2a Mon Sep 17 00:00:00 2001
From: Jessica Smith <12jessicasmith34@gmail.com>
Date: Wed, 10 Jun 2026 23:11:54 -0500
Subject: [PATCH 3/8] feat(ui): redesign diagnostics page and add it to
navigation
The page was hidden because it read as a wall of noise: 20 identical
'running' rows, a giant empty state for boot issues, and a mostly
empty telemetry card. Now a stats strip summarizes health at a glance,
services render as a compact multi-column grid with anomalies sorted
first (status/phase text only appears for non-running services), and
the boot-issues and telemetry panels render only when there is
something to show. Diagnostics joins the sidebar nav and command
palette.
---
.../src/components/layout/palette-items.ts | 7 +
frontend/src/components/layout/sidebar.tsx | 1 +
frontend/src/pages/diagnostics.module.css | 25 ++--
frontend/src/pages/diagnostics.test.tsx | 55 +++++--
frontend/src/pages/diagnostics.tsx | 141 ++++++++++--------
tests/e2e/test_navigation.py | 2 +
6 files changed, 144 insertions(+), 87 deletions(-)
diff --git a/frontend/src/components/layout/palette-items.ts b/frontend/src/components/layout/palette-items.ts
index 8801b32bc..bb8d8c960 100644
--- a/frontend/src/components/layout/palette-items.ts
+++ b/frontend/src/components/layout/palette-items.ts
@@ -54,6 +54,13 @@ export function buildStaticPageItems(navigate: (path: string) => void): PaletteI
sub: "/config",
action: () => navigate("/config"),
},
+ {
+ id: "page-diagnostics",
+ kind: "page",
+ label: "diagnostics",
+ sub: "/diagnostics",
+ action: () => navigate("/diagnostics"),
+ },
];
}
diff --git a/frontend/src/components/layout/sidebar.tsx b/frontend/src/components/layout/sidebar.tsx
index b4a3a99fc..5acb2f52c 100644
--- a/frontend/src/components/layout/sidebar.tsx
+++ b/frontend/src/components/layout/sidebar.tsx
@@ -23,6 +23,7 @@ const NAV_ITEMS = [
{ path: "/handlers", label: "handlers", testId: "nav-handlers" },
{ path: "/logs", label: "logs", testId: "nav-logs" },
{ path: "/config", label: "config", testId: "nav-config" },
+ { path: "/diagnostics", label: "diagnostics", testId: "nav-diagnostics" },
] as const;
interface AppEntryProps {
diff --git a/frontend/src/pages/diagnostics.module.css b/frontend/src/pages/diagnostics.module.css
index 37c0f717b..bdabefb5b 100644
--- a/frontend/src/pages/diagnostics.module.css
+++ b/frontend/src/pages/diagnostics.module.css
@@ -34,36 +34,41 @@
padding: 1px var(--sp-2);
}
-/* Services list */
+/* Services grid — compact tiles; anomalous services span the full row */
-.serviceList {
+.serviceGrid {
list-style: none;
margin: 0;
padding: 0;
- display: flex;
- flex-direction: column;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+ gap: var(--sp-1) var(--sp-5);
}
.serviceRow {
- border-bottom: 1px solid var(--line-2);
- padding: var(--sp-2) 0;
+ padding: var(--sp-1) 0;
+ min-width: 0;
}
-.serviceRow:last-child {
- border-bottom: none;
+.serviceRowDetailed {
+ grid-column: 1 / -1;
}
.serviceMain {
display: flex;
align-items: center;
- gap: var(--sp-3);
+ gap: var(--sp-2);
flex-wrap: wrap;
+ min-width: 0;
}
.serviceName {
- font-size: var(--fs-mono-md);
+ font-size: var(--fs-mono-sm);
color: var(--ink-1);
font-weight: var(--fw-medium);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
.serviceStatus {
diff --git a/frontend/src/pages/diagnostics.test.tsx b/frontend/src/pages/diagnostics.test.tsx
index 30d3103e2..d72076694 100644
--- a/frontend/src/pages/diagnostics.test.tsx
+++ b/frontend/src/pages/diagnostics.test.tsx
@@ -71,11 +71,12 @@ describe("DiagnosticsPage", () => {
expect(alert.textContent).toBeTruthy();
});
- it("renders all three sections after load", async () => {
- const { findByTestId } = renderWithAppState();
+ it("renders stats strip and services panel after load; clean boot/telemetry panels stay hidden", async () => {
+ const { findByTestId, queryByTestId } = renderWithAppState();
+ expect(await findByTestId("diag-stats-strip")).toBeDefined();
expect(await findByTestId("diag-services-panel")).toBeDefined();
- expect(await findByTestId("diag-boot-panel")).toBeDefined();
- expect(await findByTestId("diag-telemetry-panel")).toBeDefined();
+ expect(queryByTestId("diag-boot-panel")).toBeNull();
+ expect(queryByTestId("diag-telemetry-panel")).toBeNull();
});
it("shows empty state when no services returned from HTTP seed", async () => {
@@ -158,10 +159,11 @@ describe("DiagnosticsPage", () => {
expect(queryByTestId("diag-services-stale")).toBeNull();
});
- it("shows clean startup when no boot issues", async () => {
+ it("hides the boot issues panel when startup was clean", async () => {
server.use(http.get("/api/health", () => HttpResponse.json(makeSystemStatus({ boot_issues: [] }))));
- const { findByTestId } = renderWithAppState();
- expect(await findByTestId("diag-boot-clean")).toBeDefined();
+ const { findByTestId, queryByTestId } = renderWithAppState();
+ await findByTestId("diag-services-panel");
+ expect(queryByTestId("diag-boot-panel")).toBeNull();
});
it("renders boot issues sorted by severity (errors first)", async () => {
@@ -199,13 +201,14 @@ describe("DiagnosticsPage", () => {
expect((await findByTestId("diag-boot-detail-0")).textContent).toBe("The full detail text");
});
- it("shows 'No telemetry drops.' when all counters are zero", async () => {
- const { findByTestId } = renderWithAppState();
- expect(await findByTestId("diag-no-drops")).toBeDefined();
+ it("hides the telemetry panel when all counters are zero", async () => {
+ const { findByTestId, queryByTestId } = renderWithAppState();
+ await findByTestId("diag-services-panel");
+ expect(queryByTestId("diag-telemetry-panel")).toBeNull();
});
it("renders per-category drop counters when non-zero", async () => {
- const { findByTestId, queryByTestId } = renderWithAppState(, {
+ const { findByTestId } = renderWithAppState(, {
stateOverrides: {
droppedOverflow: signal(5),
droppedExhausted: signal(3),
@@ -214,8 +217,6 @@ describe("DiagnosticsPage", () => {
},
});
await findByTestId("diag-telemetry-panel");
- // No-drops message should be gone
- expect(queryByTestId("diag-no-drops")).toBeNull();
// Each row should be present
expect(await findByTestId("diag-drop-overflow")).toBeDefined();
expect(await findByTestId("diag-drop-exhausted")).toBeDefined();
@@ -236,13 +237,21 @@ describe("DiagnosticsPage", () => {
expect(await findByTestId("diag-telemetry-degraded")).toBeDefined();
});
- it("service row shows ready_phase text", async () => {
+ it("shows degraded banner without drop rows when all counters are zero", async () => {
+ const { findByTestId, queryByTestId } = renderWithAppState(, {
+ stateOverrides: { telemetryDegraded: signal(true) },
+ });
+ expect(await findByTestId("diag-telemetry-degraded")).toBeDefined();
+ expect(queryByTestId("diag-drop-overflow")).toBeNull();
+ });
+
+ it("service row shows ready_phase text for a non-running service", async () => {
server.use(
http.get("/api/health", () =>
HttpResponse.json(
makeSystemStatus({
services: [
- makeServiceInfo({ name: "db", status: "running", role: "storage", ready_phase: "migrating schema" }),
+ makeServiceInfo({ name: "db", status: "starting", role: "storage", ready_phase: "migrating schema" }),
],
}),
),
@@ -252,4 +261,20 @@ describe("DiagnosticsPage", () => {
const phaseEl = await findByTestId("diag-service-phase-db");
expect(phaseEl.textContent).toBe("migrating schema");
});
+
+ it("hides status text and phase for running services (the dot carries the signal)", async () => {
+ server.use(
+ http.get("/api/health", () =>
+ HttpResponse.json(
+ makeSystemStatus({
+ services: [makeServiceInfo({ name: "bus", status: "running", ready_phase: "Bus initialized" })],
+ }),
+ ),
+ ),
+ );
+ const { findByTestId, queryByTestId } = renderWithAppState();
+ await findByTestId("diag-service-row-bus");
+ expect(queryByTestId("diag-service-status-bus")).toBeNull();
+ expect(queryByTestId("diag-service-phase-bus")).toBeNull();
+ });
});
diff --git a/frontend/src/pages/diagnostics.tsx b/frontend/src/pages/diagnostics.tsx
index d7ba01460..3eec87da9 100644
--- a/frontend/src/pages/diagnostics.tsx
+++ b/frontend/src/pages/diagnostics.tsx
@@ -8,6 +8,7 @@ import type { components } from "../api/generated-types";
import cardStyles from "../components/shared/card.module.css";
import { EmptyState } from "../components/shared/empty-state";
import { Spinner } from "../components/shared/spinner";
+import { StatsStrip, type StatsStripCell } from "../components/shared/stats-strip";
import { StatusShape } from "../components/shared/status-shape";
import { useDocumentTitle } from "../hooks/use-document-title";
import { useRelativeTime } from "../hooks/use-relative-time";
@@ -25,8 +26,6 @@ interface MergedService {
ready_phase: string | null;
retry_at: number | null;
exception: string | null;
- /** True when this entry came from a WS update (not just the HTTP seed). */
- from_ws: boolean;
}
function mergeServices(
@@ -44,7 +43,6 @@ function mergeServices(
ready_phase: svc.ready_phase ?? null,
retry_at: svc.retry_at ?? null,
exception: null,
- from_ws: false,
});
}
@@ -57,11 +55,24 @@ function mergeServices(
ready_phase: entry.ready_phase ?? null,
retry_at: entry.retry_at ?? null,
exception: entry.exception ?? null,
- from_ws: true,
});
}
- return [...merged.values()].sort((a, b) => a.resource_name.localeCompare(b.resource_name));
+ // Anomalies first, then alphabetical — a failed service should never hide below the fold.
+ return [...merged.values()].sort((a, b) => {
+ const anomalyFirst = Number(a.status === "running") - Number(b.status === "running");
+ return anomalyFirst || a.resource_name.localeCompare(b.resource_name);
+ });
+}
+
+function buildDiagCells(services: MergedService[], bootIssueCount: number, totalDrops: number): StatsStripCell[] {
+ const running = services.filter((s) => s.status === "running").length;
+ return [
+ { label: "services", value: services.length },
+ { label: "running", value: running, tone: running === services.length ? "ok" : "warn" },
+ { label: "boot issues", value: bootIssueCount, tone: bootIssueCount > 0 ? "err" : undefined },
+ { label: "drops", value: totalDrops, tone: totalDrops > 0 ? "warn" : undefined },
+ ];
}
interface DiagServiceRowProps {
@@ -72,20 +83,28 @@ function DiagServiceRow({ service }: DiagServiceRowProps) {
const [exceptionOpen, setExceptionOpen] = useState(false);
const retryAtLabel = useRelativeTime(service.retry_at);
const isCooling = service.status === "exhausted_cooling";
+ const isRunning = service.status === "running";
const kind = statusToKind(service.status);
+ // Rows with extra content (status text, phase, exception toggle) span the full grid width.
+ const spansFullRow = !isRunning || !!service.exception;
return (
-
-
-
+
+
+
{service.resource_name}
-
- {service.status}
-
- {service.ready_phase && (
+ {!isRunning && (
+
+ {service.status}
+
+ )}
+ {!isRunning && service.ready_phase && (
{service.ready_phase}
@@ -137,7 +156,7 @@ function ServicesPanel({ services, wsConnected }: ServicesPanelProps) {
{services.length === 0 ? (
) : (
-
+
{services.map((svc) => (
))}
@@ -164,32 +183,28 @@ function BootIssuesPanel({ bootIssues }: BootIssuesPanelProps) {
return (
boot issues
- {sorted.length === 0 ? (
-
- ) : (
-
- )}
+
);
}
@@ -224,13 +239,6 @@ function TelemetryPanel({
errorHandlerFailures,
telemetryDegraded,
}: TelemetryPanelProps) {
- const allZero =
- !telemetryDegraded &&
- droppedOverflow === 0 &&
- droppedExhausted === 0 &&
- droppedShutdown === 0 &&
- errorHandlerFailures === 0;
-
return (
)}
- {allZero ? (
-
- No telemetry drops.
-
- ) : (
+ {droppedOverflow + droppedExhausted + droppedShutdown + errorHandlerFailures > 0 && (
@@ -293,6 +297,10 @@ export function DiagnosticsPage() {
const bootIssues: BootIssue[] = systemStatus?.boot_issues ?? [];
+ const totalDrops =
+ droppedOverflow.value + droppedExhausted.value + droppedShutdown.value + errorHandlerFailures.value;
+ const showTelemetry = telemetryDegraded.value || totalDrops > 0;
+
if (loading) return ;
return (
@@ -307,19 +315,28 @@ export function DiagnosticsPage() {
) : (
<>
+
+
-
+ {bootIssues.length > 0 && }
>
)}
-
+ {/* Telemetry counters come from the WS stream, not the HTTP seed,
+ so they render even when the HTTP load failed. */}
+ {showTelemetry && (
+
+ )}
);
}
diff --git a/tests/e2e/test_navigation.py b/tests/e2e/test_navigation.py
index 742e72484..b72c7b9ce 100644
--- a/tests/e2e/test_navigation.py
+++ b/tests/e2e/test_navigation.py
@@ -43,6 +43,7 @@ def test_config_page_loads(page: Page, base_url: str) -> None:
("nav-apps", "/apps", "apps"),
("nav-logs", "/logs", "logs"),
("nav-config", "/config", "config"),
+ ("nav-diagnostics", "/diagnostics", "diagnostics"),
]
@@ -73,6 +74,7 @@ def test_sidebar_navigation(page: Page, base_url: str, testid: str, expected_pat
("/apps", "nav-apps"),
("/logs", "nav-logs"),
("/config", "nav-config"),
+ ("/diagnostics", "nav-diagnostics"),
]
From 2abee4b69a3b9e793438452ee96b066286c90ad0 Mon Sep 17 00:00:00 2001
From: Jessica Smith <12jessicasmith34@gmail.com>
Date: Wed, 10 Jun 2026 23:13:37 -0500
Subject: [PATCH 4/8] chore: update table responsiveness guidance in
DESIGN_RULES.md
The old rule recommended table-layout: auto on mobile, which is the
exact mechanism that caused the column cropping fixed in the previous
commit. Document the fixed-layout + colgroup-reallocation pattern
instead.
---
frontend/DESIGN_RULES.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/DESIGN_RULES.md b/frontend/DESIGN_RULES.md
index d76de6276..8841cb4c6 100644
--- a/frontend/DESIGN_RULES.md
+++ b/frontend/DESIGN_RULES.md
@@ -450,7 +450,7 @@ The existing breakpoints are correct:
### Table Behavior at 768px
-Tables should switch to `table-layout: auto` and hide non-essential columns rather than allowing horizontal scroll or header truncation. Any table whose headers truncate or wrap at a breakpoint needs column hiding at that breakpoint.
+Tables keep `table-layout: fixed` at every breakpoint and hide non-essential columns rather than allowing horizontal scroll or header truncation. Switching to `table-layout: auto` on mobile lets unbreakable mono content (entity IDs, app keys, log messages) push the table past the viewport and crop columns mid-word — the colgroup must instead reallocate widths to the columns that remain visible at that breakpoint (see `apps.module.css` for the pattern). Any table whose headers truncate or wrap at a breakpoint needs column hiding at that breakpoint.
### Mobile Detail Pages (<768px)
From 98b5a451b0d66ae90f88b8d8159a2b51988e8340 Mon Sep 17 00:00:00 2001
From: Jessica Smith <12jessicasmith34@gmail.com>
Date: Wed, 10 Jun 2026 23:28:53 -0500
Subject: [PATCH 5/8] docs: document the diagnostics page and refresh UI
screenshots
Adds the web-ui/diagnostics.md page, updates layout.md nav references
from four to five top-level pages, and regenerates all docs screenshots
to reflect the new sidebar item and diagnostics redesign.
---
docs/_static/web_ui_app_detail_code.png | Bin 106632 -> 108094 bytes
docs/_static/web_ui_app_detail_config.png | Bin 102084 -> 103125 bytes
docs/_static/web_ui_app_detail_handlers.png | Bin 117912 -> 117952 bytes
docs/_static/web_ui_app_detail_overview.png | Bin 162698 -> 161321 bytes
docs/_static/web_ui_apps.png | Bin 81361 -> 84492 bytes
docs/_static/web_ui_config.png | Bin 99079 -> 99927 bytes
docs/_static/web_ui_detail_column_picker.png | Bin 9751 -> 10102 bytes
.../_static/web_ui_detail_command_palette.png | Bin 104532 -> 106017 bytes
docs/_static/web_ui_detail_log_drawer.png | Bin 20049 -> 19694 bytes
docs/_static/web_ui_detail_sidebar.png | Bin 18545 -> 17407 bytes
docs/_static/web_ui_detail_status_bar.png | Bin 4671 -> 4650 bytes
docs/_static/web_ui_diagnostics.png | Bin 0 -> 62595 bytes
docs/_static/web_ui_handlers.png | Bin 96279 -> 98104 bytes
docs/_static/web_ui_logs.png | Bin 126256 -> 122175 bytes
docs/pages/web-ui/diagnostics.md | 51 ++++++++++++++++++
docs/pages/web-ui/layout.md | 5 +-
docs/screenshots.yml | 6 +++
mkdocs.yml | 1 +
18 files changed, 61 insertions(+), 2 deletions(-)
create mode 100644 docs/_static/web_ui_diagnostics.png
create mode 100644 docs/pages/web-ui/diagnostics.md
diff --git a/docs/_static/web_ui_app_detail_code.png b/docs/_static/web_ui_app_detail_code.png
index 48b825befbd600069ba01adbd1181c14fc5e4933..4602617888a51813db2defa6277c5e021a0d893d 100644
GIT binary patch
literal 108094
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