Skip to content

Fix/toolbar grid and chart tooltip - #69

Closed
furqan-debug wants to merge 15 commits into
mainfrom
fix/toolbar-grid-and-chart-tooltip
Closed

furqan-debug wants to merge 15 commits into
mainfrom
fix/toolbar-grid-and-chart-tooltip

Conversation

@furqan-debug

Copy link
Copy Markdown
Owner

No description provided.

Muhammad Huzaifa and others added 15 commits September 22, 2026 03:00
My own regression. The selected row used to be bg-slate-900, so its
contents were written as text-white. Making selected states invert — so
they could be seen in dark mode — turned the row near-white there, and the
name, role and avatar initial kept their hard-coded white.

They take the same inverting token as the row now, so they flip with it
instead of against it.

Checked the three other files that got the inverted selection: none has a
hard-coded white inside one.
It was hard-coded #ffffff with #000000 text — a light-mode tooltip that
stayed white in dark mode. Recharts also colours the value after the slice
it came from, so on a pale slice the number was light text on a light
card.

All three styles take theme tokens now: the card is the surface colour,
and the label and value are both forced to text-main rather than
inheriting the slice's. The other chart on this page already did this; the
donut was the one left behind.

The value also runs through formatDuration, so it reads "8h 01m" rather
than 481 — the raw minutes meant nothing next to a ring measured in hours.
The "206h HOURS" overlay sits in the middle of the ring as an absolutely
positioned sibling, after the chart in the DOM and with no stacking order
of its own — so it drew on top of the tooltip, and the two sets of text
landed on each other.

The tooltip gets z-50 and the overlay z-0, so the tooltip wins while it is
open.
The date control and the buttons were one flex row; the member filter and
the timezone were another. Each sized itself and right-aligned
independently, with different gaps — gap-6 above, gap-4 below — so the
boundary between the first and second item never lined up between the
rows.

They are four children of a two-column grid now. Both rows draw their
column widths from the same track, so the edges meet by construction
rather than by matching numbers that would drift the next time something
changed.

Nothing shrinks: the columns size to their content, and the member
filter's min-width still applies.

Below 900px it is a single column, as before.
Both items in the grid's first column carried min-[900px]:w-auto, so each
sized to its own content instead of taking the column. The date control
and the member filter came out different widths and their left edges
missed each other.

Both are w-full now, so they take the shared column — which is as wide as
the wider of the two, so neither gets smaller.
Filling the grid column stretched it to the width of the date control
above. It sizes to its own content again — a 220px minimum — and ml-auto
pushes it to the column's right edge, so it loses the width from the left
and still finishes where the date control finishes.

The date control keeps the full column, so the two right edges meet.
Both app lists used one generic window icon for everything, so a table of
twenty rows gave no help telling Chrome from Zoom from Notepad at a
glance.

AppIcon resolves a logo from the app name. Names arrive in several shapes
for the same app — "Google Chrome" and "chrome", "Microsoft Teams" and
"ms-teams", "LockApp.exe", "WhatsApp.Root", "Microsoft.Notes" — so the
lookup normalises first. Matching exactly would have put a logo on 59% of
Chrome rows and left the other 2% blank.

Real logos come from simple-icons, which covers Chrome and Zoom — 73% of
all samples between them — plus WhatsApp, AnyDesk, Firefox, Spotify,
Discord, Telegram, the Google suite and a dozen developer tools. Tree
shaking keeps this to 28kB raw, 14kB gzipped, against a 2MB package.

Microsoft's marks and Slack's were withdrawn from that set over trademark.
Rather than ship a hand-drawn imitation of someone's logo, those get their
initial on a tile in the correct brand colour: Teams in #6264A7, Edge in
#0078D7, Slack in #4A154B and so on. Anything unrecognised keeps the
neutral tile it had.

Deliberately not favicons. Fetching them from a domain service would cover
every website automatically, but it would send the list of sites every
monitored employee visits to a third party, one request per row, to
decorate a table.
…erage

The App Usage list showed a logo for a couple of dozen apps and a grey
initial for everything else, including TrackOwl's own rows.

TrackOwl now renders its own owl icon on a tinted tile. The logo and
brand-colour maps grew to about 55 entries each, covering the Microsoft
family, the Windows shell processes, Slack, Dialpad, RingCentral,
MetaTrader, Acrobat and the rest of what this org actually runs.

Two matching fixes behind that:

- normalise() strips control characters. The tracker sometimes writes a
  mangled name, e.g. Spotify followed by two control bytes and "FileV".
- lookup() falls back to the longest known name the app's name starts
  with, so "Roblox Game Client" and "Steam Client WebHelper" resolve.
  Longest wins, so "google sheets" is not beaten by "google".

Checked against 60 days of activity_samples: 99.5% of 286,236 samples
now resolve to an icon or a brand tile. The remainder is "Unknown",
which keeps the neutral tile it should have.
This card had its own icon logic predating AppIcon: a globe when the
name contained "chrome" or "browser", a generic monitor otherwise. So
Zoom, Teams and Edge all sat behind the same grey monitor, and Chrome
got a globe rather than its own mark.

It now uses AppIcon, the same component the App Usage page uses, so the
two lists agree and the card picks up the full logo and brand-colour
coverage.
Teams, Edge, Word, Excel, Outlook, Slack, LinkedIn, Acrobat, VS Code and
ChatGPT were all showing a lettered tile rather than a logo. The reason
was not the lookup: simple-icons withdrew every one of those marks in
v12 under its trademark policy, so the installed v16 does not have them
at all.

Those icons are still in v11, which is now installed alongside under the
alias "brand-icons" purely to supply them. v16 stays the primary set for
everything current, including marks v11 predates such as Claude.

The Windows shell processes the tracker reports by name - Explorer,
LockApp, ShellHost, SearchHost, Calculator, Settings, Notepad and the
rest - now carry the Windows logo, so they read as one family.

Measured over 60 days of activity_samples: 96.5% of 286,236 samples now
draw a real logo, up from roughly 63%. 3.0% are small vendors no icon
set ships (Dialpad, RingCentral, WPS, MetaTrader, Balto, Antigravity,
MuMu, Scrnli) and keep an initial on a tile in the vendor's own colour -
redrawing someone's mark by eye would only get it subtly wrong. The last
0.5% is "Unknown", which keeps the neutral tile.
Mapping the Windows shell processes to the Windows mark was right for
Explorer, ShellHost, LockApp and the rest, but it swept up Notepad,
Calculator and Snipping Tool too. Those are separate apps, so the row
read as though Notepad were Windows itself.

They now take a tile in roughly the product's own accent colour. Their
real icons are not in any icon set, so this is the honest option until
the icons come off the executable itself.

Real-logo coverage moves 96.5% -> 95.1% of 286,236 samples, which is
the cost of not mislabelling 4,127 of them.
Notepad's mark is in no icon set, so it had been showing a lettered
tile. Its real artwork now ships in assets/app-icons.

The source was flat RGB with a white background, which would have read
as a white square on the tinted tile, so it was converted to RGBA with
the white knocked out, cropped to the glyph and scaled to 128px: 9.7 kB.

The owl branch generalises into IMAGE_ICONS, a map of apps whose icon is
artwork rather than a single-path mark, each with its own tile tint.
Adding another app is now one entry plus one file.

That map is matched exactly, never by prefix — the prefix pass would
otherwise hand Notepad's artwork to Notepad++, a different app that has
a mark of its own.
simple-icons ships one path and one hex per icon, so every logo came out
flat: Edge a solid blue rather than its blue-green swirl, Teams solid
purple, Chrome a single-colour disc.

The real artwork comes from the Iconify collections instead. Those hold
about 3,700 icons between them and importing either one would put all of
it in the bundle, so they are devDependencies and scripts/
generate-app-icons.mjs copies out only the icons referenced, into
src/components/ui/appIconArt.ts. Regenerate with `npm run gen:app-icons`.

Two things the generated file does deliberately:

- It prefers a collection's square "-icon" variant over the base entry.
  The base is often the full horizontal wordmark, which is an unreadable
  smudge at 40px — Slack, WhatsApp, GitHub and npm were all affected.
  Picking the square variants also cut the file from 163 kB to 102 kB.
- Icons are emitted once and referenced by every name that maps to them,
  rather than inlined per name. Twenty Windows shell processes share one
  body.

Order in the component is now artwork, then full-colour icon, then the
monochrome mark, then a brand-colour tile. Anything without artwork
keeps the mark it had, so nothing regressed.

Of 286,236 samples over 60 days: 95.5% now draw a full-colour logo, 0.8%
a monochrome mark, 3.2% a colour tile, 0.5% the neutral tile. Cost is
about 48 kB gzipped.
Settings was wearing the Windows logo, Calendar had no mapping at all,
and Dialpad — the third busiest app in the fleet at 5,526 samples — was
a lone "D" on a tile.

None of the three has a logo to fetch. Dialpad's mark is in neither
Iconify nor simple-icons; a search of the whole Iconify catalogue
returns only generic keypad pictograms, no brand mark. Windows Settings
and Calendar are the same story.

So they get a pictogram of what the app is, in the vendor's colour: a
gear for Settings, a calendar for Calendar, a keypad for Dialpad,
scissors for Snipping Tool, a calculator for Calculator. lucide-react is
already a dependency, so this costs nothing to ship. It is not the real
mark, but it reads as the app at a glance, which a letter never did.

Anything here is superseded the moment real artwork lands in
IMAGE_ICONS, the way Notepad's did.

Of 286,236 samples: 95.4% full-colour logo, 0.9% monochrome mark, 2.1%
pictogram, 1.0% colour tile, 0.5% neutral — down from 3.2% on tiles.
feat(activity): show app logos in their own colours
@vercel

vercel Bot commented Sep 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
trackowl Building Building Preview Sep 22, 2026 6:19pm UTC

This branch was successfully deployed

2 active deployments
Preview – trackowl — 53c84e97 Deployed Sep 22, 2026 by vercel[bot]
Preview – trackowl-admin — 53c84e97 Deployed Sep 22, 2026 by vercel[bot]
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.

1 participant