Polish Lite chart axes and sub-tab styling#862
Conversation
- Chart X-axis prints the date line only on the first tick and on ticks where the date changes; all other ticks show time only. Format respects current culture (en-GB → dd/MM, de-DE → dd.MM, 24h clocks, etc.). Implemented as a DateTimeTicksBottomDateChange() extension in Lite/Helpers/AxesExtensions.cs and applied to every DateTimeTicksBottom call site in ServerTab and CorrelatedTimelineLanesControl. - Server name no longer duplicated in the ServerTab header status line; ConnectionStatusText now shows just "Connecting..." / "Last refresh: ...". - Chart tick label font bumped from 12 to 13 for readability. - New SubTabItemStyle (thin accent underline, transparent background) in all three themes, applied to Queries / Memory / File I/O / Blocking / Perfmon / Running Jobs sub-TabControls so sub-tab selection no longer looks identical to main-tab selection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
erikdarlingdata
left a comment
There was a problem hiding this comment.
Review summary
What this does
Lite UI polish: (1) new DateTimeTicksBottomDateChange() extension replaces DateTimeTicksBottom() at every call site in ServerTab.xaml.cs and CorrelatedTimelineLanesControl.xaml.cs, printing the date only when it changes; (2) ConnectionStatusText stops duplicating the server name already shown in ServerNameText; (3) chart tick font bumped 12 → 13 in both ApplyTheme and ReapplyAxisColors; (4) new SubTabItemStyle added to Dark/Light/CoolBreeze themes and applied to the six sub-TabControls in ServerTab.xaml.
Process checks
- Base branch is
dev✓ - Lite-only — no Dashboard port needed, and Lite-first is the correct ordering ✓
- No
PlanAnalyzer.cschanges — sync check N/A - No SQL / install / upgrade changes — schema-path check N/A
- No
.github/workflows/build.ymlchanges — SignPath check N/A
Needs attention (details inline)
Lite/Helpers/AxesExtensions.cs:31-42— thelastDateclosure persists across ScottPlot render passes, so after a zoom/pan the first visible tick of the new view may not show the date. This is the main correctness issue.Lite/Controls/ServerTab.xaml.cs:844— header time string is still hardcodedHH:mm:sswhile the chart-tick formatter this PR adds is culture-aware; minor inconsistency.Lite/Themes/{Dark,Light,CoolBreeze}Theme.xamlSubTabItemStyle— customControlTemplatehas no keyboard-focus visual; minor a11y nit.
Other notes
BuildMonthDayPattern()atAxesExtensions.cs:12-19— the regex-based stripping of the year component will produce unexpected output for cultures whoseShortDatePatternhas the year in the middle (rare, but e.g. some locale customisations). The fallback to"M/d"only triggers if the result is whitespace, not if it's malformed. Low risk but worth a glance.- Test plan in the PR description is appropriate for UI polish; no unit tests warranted.
Generated by Claude Code
| DateTime? lastDate = null; | ||
| var culture = CultureInfo.CurrentCulture; | ||
| gen.LabelFormatter = dt => | ||
| { | ||
| var time = dt.ToString("t", culture); | ||
| if (lastDate is null || dt.Date != lastDate.Value) | ||
| { | ||
| lastDate = dt.Date; | ||
| return $"{dt.ToString(MonthDayPattern, culture)}\n{time}"; | ||
| } | ||
| return time; | ||
| }; |
There was a problem hiding this comment.
Correctness concern: lastDate is captured in a closure and persists across ScottPlot render passes after the formatter is installed. The state is only reset when DateTimeTicksBottomDateChange() is called again (new closure), which happens on full chart refresh — but not on zoom/pan, where ScottPlot re-invokes the existing LabelFormatter for new visible ticks.
Concrete failure mode: chart shows Apr 15 → Apr 18. Last rendered tick is Apr 18, so lastDate ends at Apr 18. User zooms into a 1-hour window within Apr 18. All visible ticks have dt.Date == lastDate.Value, so the formatter returns time-only for every one of them — the date line never appears in the zoomed view, even though the contract is "first tick gets the date."
There's also an ordering assumption: the state machine only works if ScottPlot iterates ticks in chronological order. If it ever calls the formatter out of order (or twice for the same tick during layout), the output will flicker.
Safer approach: compute the "show date?" decision from the tick positions array after ticks are generated, rather than via stateful closure. ScottPlot's DateTimeAutomatic exposes Ticks after regeneration — you can iterate once and assign labels via a precomputed dictionary, or hook the regeneration event if one is available.
Generated by Claude Code
|
|
||
| var tz = ServerTimeHelper.GetTimezoneLabel(ServerTimeHelper.CurrentDisplayMode); | ||
| ConnectionStatusText.Text = $"{_server.ServerNameDisplay} - Last refresh: {DateTime.Now:HH:mm:ss} ({tz})"; | ||
| ConnectionStatusText.Text = $"Last refresh: {DateTime.Now:HH:mm:ss} ({tz})"; |
There was a problem hiding this comment.
Minor inconsistency: the chart-tick formatter this PR introduces is culture-aware (uses "t" and culture-specific month-day pattern), but this status line is still hardcoded HH:mm:ss. For an en-US user the chart shows 3:45 PM while the header shows 15:45:03. Either pick one policy or use DateTime.Now.ToString("T", CultureInfo.CurrentCulture) for consistency.
Generated by Claude Code
| <Setter Property="Template"> | ||
| <Setter.Value> | ||
| <ControlTemplate TargetType="TabItem"> | ||
| <Border x:Name="border" | ||
| Background="{TemplateBinding Background}" | ||
| BorderBrush="{StaticResource AccentBrush}" | ||
| BorderThickness="0" | ||
| Padding="{TemplateBinding Padding}"> | ||
| <ContentPresenter ContentSource="Header" | ||
| HorizontalAlignment="Center" | ||
| VerticalAlignment="Center"/> | ||
| </Border> | ||
| <ControlTemplate.Triggers> | ||
| <Trigger Property="IsSelected" Value="True"> | ||
| <Setter TargetName="border" Property="BorderThickness" Value="0,0,0,2"/> | ||
| <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> | ||
| </Trigger> | ||
| <Trigger Property="IsMouseOver" Value="True"> |
There was a problem hiding this comment.
The custom ControlTemplate replaces the default TabItem template without setting a FocusVisualStyle or any visual cue for IsKeyboardFocused/IsFocused. Users navigating by keyboard won't see which sub-tab is focused when tabbing through the UI. Consider adding a FocusVisualStyle setter or a trigger on IsKeyboardFocused that changes the border/background. Same applies to the identical style in LightTheme.xaml and CoolBreezeTheme.xaml.
Generated by Claude Code
Dashboard polish (ports the same items merged to Lite in #862): - New Dashboard/Helpers/AxesExtensions.cs with DateTimeTicksBottomDateChange(), culture-aware (dd/MM for en-GB, dd.MM for de-DE, 24h clocks, etc.). All 52 call sites of DateTimeTicksBottom() across 10 files swapped to use it. - TabHelpers.ApplyTheme + ReapplyAxisColors bump chart tick label font from 12 to 13 so numbers read cleaner on wide charts. - SubTabItemStyle added to Dark / Light / CoolBreeze themes: thin accent underline + transparent background instead of filled cyan, so sub-tabs don't look identical to main tabs when selected. Wired via ItemContainerStyle on 11 sub-TabControls (Overview's inner tabs, Collection Health's inner tabs, Locking, ConfigChanges, CurrentConfig, FinOps, Memory, ResourceMetrics ×2, SystemEvents, QueryPerformance). LSP diagnostics cleanup (tracked work from chore/lsp-diagnostics-cleanup): - Small nullability/warning fixes across Dashboard and Lite services, analysis helpers, and BenefitScorer / PlanAnalyzer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Small set of Lite UI polish items reviewed in-session:
dd/MM, de-DE showsdd.MM, 24-hour clocks, etc.). Implemented as aDateTimeTicksBottomDateChange()extension inLite/Helpers/AxesExtensions.csand applied at everyDateTimeTicksBottom()call site inServerTabandCorrelatedTimelineLanesControl.ConnectionStatusTextno longer prefixes the server name beforeLast refresh: …sinceServerNameTextalready shows it. Initial value isConnecting...instead of the server name.ApplyThemeandReapplyAxisColorsso it survivesDateTimeTicksBottomresets.SubTabItemStyleadded to all three themes (Dark / Light / CoolBreeze) and wired up on the six sub-TabControls inServerTab.xaml(Queries, Memory, File I/O, Blocking, plus two unnamed). Sub-tabs now use a thin accent underline with transparent background instead of the filled-cyan block, so sub-tab selection no longer looks identical to main-tab selection.Test plan
Connecting...→Last refresh: HH:mm:ss (…)with no duplicate server nameCultureInfolocally) to en-GB / de-DE and verify date format and 24-hour times🤖 Generated with Claude Code