Skip to content

fix(summary): outline dark-mode summary labels#891

Open
TimeToBuildBob wants to merge 1 commit into
ActivityWatch:masterfrom
TimeToBuildBob:fix/dark-mode-text-contrast-on-light-bars
Open

fix(summary): outline dark-mode summary labels#891
TimeToBuildBob wants to merge 1 commit into
ActivityWatch:masterfrom
TimeToBuildBob:fix/dark-mode-text-contrast-on-light-bars

Conversation

@TimeToBuildBob

@TimeToBuildBob TimeToBuildBob commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Problem

In dark mode, dark.css applies svg text { fill: #fff !important } globally. The summary visualization renders app-name and duration labels over category-colored bars. On light-colored bars, white text can be hard to read.

Reported in ActivityWatch/aw-server-rust#621.

Fix

Add a dark outline scoped to svg.appsummary text in static/dark.css using SVG stroke properties:

  • Keeps label fill consistent in dark mode instead of alternating text colors by bar luminosity
  • Makes white labels readable on light category bars
  • Still works when labels overflow outside short bars, because the outline travels with the text
  • Leaves the TypeScript summary rendering logic unchanged

Testing

  • npm run lint -- --no-fix — passes, with existing no-shadow warnings in vite.config.js and vue.config.js
  • npm run build — passes, with existing asset-size warnings and dependency deprecation warnings

@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 38.42%. Comparing base (f24f6e9) to head (450df59).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #891      +/-   ##
==========================================
+ Coverage   35.59%   38.42%   +2.83%     
==========================================
  Files          36       42       +6     
  Lines        2152     2225      +73     
  Branches      398      417      +19     
==========================================
+ Hits          766      855      +89     
+ Misses       1365     1349      -16     
  Partials       21       21              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a CSS outline rule scoped to svg.appsummary text in static/dark.css to improve dark-mode label readability in the summary visualization. When dark mode applies fill: #fff globally to SVG text, labels on light-colored category bars become hard to read; the stroke outline solves this without touching any TypeScript rendering logic.

  • Adds paint-order: stroke fill + stroke: #000 + stroke-linejoin: round + stroke-width: 2px exclusively to .appsummary SVG text, so it cannot affect other SVG visualisations (timespiral, etc.).
  • The svg.appsummary class selector has higher specificity than the generic svg text rule, so no !important override is needed for the new stroke properties.

Confidence Score: 5/5

Safe to merge — a small, well-scoped CSS addition that cannot affect any SVG component other than the app-summary visualization.

The change is a single CSS rule block adding a stroke outline to svg.appsummary text. It is correctly scoped by class selector, uses the right paint-order technique for text outlines, and does not interfere with the generic svg text rule or any other visualization styles in the file.

No files require special attention.

Important Files Changed

Filename Overview
static/dark.css Adds a 7-line CSS rule scoped to svg.appsummary text that renders a dark stroke outline around white labels in dark mode; no logic changes, no regressions to other SVG components.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[dark.css loads in dark mode] --> B["Generic rule: svg text\nfill: #fff !important\ntext-shadow: #000 0.5px …"]
    B --> C{Is it svg.appsummary text?}
    C -- No --> D[Other SVG text rendered\nwith white fill only]
    C -- Yes --> E["Scoped rule applies\npaint-order: stroke fill\nstroke: #000\nstroke-width: 2px\nstroke-linejoin: round"]
    E --> F[Stroke painted first,\nwhite fill on top →\ndark outline around label]
    F --> G[Readable on both\nlight and dark category bars]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[dark.css loads in dark mode] --> B["Generic rule: svg text\nfill: #fff !important\ntext-shadow: #000 0.5px …"]
    B --> C{Is it svg.appsummary text?}
    C -- No --> D[Other SVG text rendered\nwith white fill only]
    C -- Yes --> E["Scoped rule applies\npaint-order: stroke fill\nstroke: #000\nstroke-width: 2px\nstroke-linejoin: round"]
    E --> F[Stroke painted first,\nwhite fill on top →\ndark outline around label]
    F --> G[Readable on both\nlight and dark category bars]
Loading

Reviews (2): Last reviewed commit: "fix(summary): outline dark-mode summary ..." | Re-trigger Greptile

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Ready to merge

  • CI: All checks passing (Build, Lint, CodeQL, Tests, Greptile)
  • Greptile Review: 5/5 confidence
  • No outstanding review comments

This is ready for a maintainer to merge.

@ErikBjare

Copy link
Copy Markdown
Member

I think I tried this before, but it doesn't really work since the text overflows the bar which would make white text on white bg for the overflow. The way I "fixed" (improved) it was indeed by adding text-shadow (as ActivityWatch/aw-server-rust#621 suggests) but clearly it's not a complete fix, but neither is this (and the alternating white text vs black text depending on bar luminosity also looks off iirc).

Dark mode forces SVG text to white globally, which makes app summary labels hard to read on light-colored bars. The previous per-bar luminosity approach did not handle labels that overflow outside the bar and made adjacent labels vary between white and dark text.\n\nKeep the existing label fill behavior and add a dark-mode-only outline scoped to the app summary SVG labels instead. The outline preserves readable white text both on light bars and when labels overflow past the bar.\n\nFixes ActivityWatch/aw-server-rust#621
@TimeToBuildBob TimeToBuildBob force-pushed the fix/dark-mode-text-contrast-on-light-bars branch from adf8ff3 to 450df59 Compare July 3, 2026 10:16
@TimeToBuildBob TimeToBuildBob changed the title fix(summary): compute bar text color from background luminosity fix(summary): outline dark-mode summary labels Jul 3, 2026
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Agreed. The luminosity-based version was the wrong shape for this because the labels are not clipped to the bars, and alternating black/white labels looks noisy.

I rewrote the PR: it now leaves summary.ts alone and adds a dark-mode-only outline scoped to svg.appsummary text in static/dark.css. That keeps the text consistently white in dark mode while making it readable on light bars and when it overflows outside a short bar.

Local checks passed:

  • npm run lint -- --no-fix (existing no-shadow warnings only)
  • npm run build (existing asset-size/deprecation warnings only)

GitHub CI is rerunning on the new commit now.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

All CI checks ✅ and Greptile review (5/5 confidence) now complete on the rewritten version (CSS outline approach).

The rewrite addresses your concern about text overflow: instead of a luminosity-based approach that varies label colors (which looked noisy), this adds a dark-mode-only outline scoped to svg.appsummary text in static/dark.css. Keeps text consistently white in dark mode and readable on both light and dark bars, including when labels overflow outside short bars.

Ready to merge when you are.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants