diff --git a/src/PlanViewer.Core/Output/HtmlExporter.cs b/src/PlanViewer.Core/Output/HtmlExporter.cs index 3102c10..5d87f26 100644 --- a/src/PlanViewer.Core/Output/HtmlExporter.cs +++ b/src/PlanViewer.Core/Output/HtmlExporter.cs @@ -109,10 +109,15 @@ .statement h2 { /* Insights grid */ .insights { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0.75rem; margin-bottom: 0.75rem; } .card { border-radius: 6px; border: 1px solid var(--border); overflow: hidden; } -.card h3 { +.card h3, .card > summary { padding: 0.4rem 0.75rem; font-size: 0.8rem; font-weight: 500; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 0.5rem; + list-style: none; cursor: pointer; } +.card > summary::-webkit-details-marker { display: none; } +.card > summary::before { content: ""\25B8""; font-size: 0.7rem; color: var(--text-muted); width: 0.7rem; } +details.card[open] > summary::before { content: ""\25BE""; } +.card.waits summary { color: #2a4365; } .card-body { padding: 0.5rem 0.75rem; font-size: 0.8rem; } .card.runtime { background: var(--card-runtime); border-color: var(--card-runtime-border); } .card.runtime h3 { color: #2c5282; } @@ -432,11 +437,12 @@ private static void WriteParametersCard(StringBuilder sb, StatementResult stmt) private static void WriteWaitStatsCard(StringBuilder sb, StatementResult stmt, bool hasActualStats) { - sb.AppendLine("
"); - sb.Append("

Wait Stats"); + // Collapsible (#215 E12): default-closed so improvement items aren't pushed below the fold. + sb.AppendLine("
"); + sb.Append("Wait Stats"); if (stmt.WaitStats.Count > 0) sb.Append($" {stmt.WaitStats.Sum(w => w.WaitTimeMs):N0} ms"); - sb.AppendLine("

"); + sb.AppendLine(""); sb.AppendLine("
"); if (stmt.WaitStats.Count > 0) { @@ -464,7 +470,7 @@ private static void WriteWaitStatsCard(StringBuilder sb, StatementResult stmt, b sb.AppendLine($"
{(hasActualStats ? "No waits recorded" : "Estimated plan — no wait stats")}
"); } sb.AppendLine("
"); - sb.AppendLine("
"); + sb.AppendLine(""); } private static void WriteWarnings(StringBuilder sb, StatementResult stmt) diff --git a/src/PlanViewer.Web/Pages/Index.razor b/src/PlanViewer.Web/Pages/Index.razor index 5d46382..652583c 100644 --- a/src/PlanViewer.Web/Pages/Index.razor +++ b/src/PlanViewer.Web/Pages/Index.razor @@ -299,14 +299,14 @@ else - @* Wait Stats *@ -
-

Wait Stats + @* Wait Stats — collapsible (#215 E12): default-closed so it doesn't push improvement items below the fold *@ +
+ Wait Stats @if (ActiveStmt!.WaitStats.Count > 0) { @ActiveStmt!.WaitStats.Sum(w => w.WaitTimeMs).ToString("N0") ms } -

+
@if (ActiveStmt!.WaitStats.Count > 0) { @@ -336,7 +336,7 @@ else
@(result.Summary.HasActualStats ? "No waits recorded" : "Estimated plan — no wait stats")
}
-
+ @* Warnings strip *@ diff --git a/src/PlanViewer.Web/wwwroot/css/app.css b/src/PlanViewer.Web/wwwroot/css/app.css index 8c13d50..b44467c 100644 --- a/src/PlanViewer.Web/wwwroot/css/app.css +++ b/src/PlanViewer.Web/wwwroot/css/app.css @@ -541,7 +541,8 @@ textarea::placeholder { overflow: hidden; } -.insight-card h4 { +.insight-card h4, +.insight-card > summary { padding: 0.4rem 0.75rem; font-size: 0.8rem; font-weight: 500; @@ -549,8 +550,24 @@ textarea::placeholder { display: flex; align-items: center; gap: 0.5rem; + list-style: none; + cursor: pointer; +} + +.insight-card > summary::-webkit-details-marker { display: none; } + +.insight-card > summary::before { + content: "\25B8"; + font-size: 0.7rem; + color: var(--text-muted); + transition: transform 0.15s ease; + width: 0.7rem; } +.insight-card[open] > summary::before { content: "\25BE"; } + +details.insight-card:not([open]) { border-bottom: 1px solid var(--border); } + .insight-body { padding: 0.5rem 0.75rem; font-size: 0.8rem;