Skip to content

Name desktop objects after things, not after the software - #445

Merged
AllTerrainDeveloper merged 3 commits into
trunkfrom
rename-desktop-object-labels
Jul 29, 2026
Merged

Name desktop objects after things, not after the software#445
AllTerrainDeveloper merged 3 commits into
trunkfrom
rename-desktop-object-labels

Conversation

@AllTerrainDeveloper

@AllTerrainDeveloper AllTerrainDeveloper commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Three built-in windows were named after the wrong thing, and the names leaked the frame instead of naming what's inside it.

Was Now Why
My WordPress The site's own title — get_bloginfo( 'name' ) The "My" prefix is a 1995 Microsoft tic, and it names the software rather than the thing. NeXT and Mac never labeled the drive "My NeXTSTEP." It also breaks the fiction: the desktop should contain objects, not a mention of the OS you're already standing in.
Recycle Bin Trash Microsoft's word, and it fights WordPress's own vocabulary, which is Trash. Recycling also implies the material comes back as something else, which isn't what happens.
Content Graph Corkboard Data-structure jargon wearing an icon. Nobody's desk has a Graph on it — it describes the schema, not the act.

The drag-to-bin ghost chip already read Move to Trash, so the window title now agrees with the gesture that fills it.

Labels only — no slugs moved

Module directories, window ids (desktop-mode-recycle-bin, desktop-mode-my-wordpress, desktop-mode-content-graph), REST routes, CSS classes, data-* attributes, the wp.desktop.myWordpress JS API, and every desktop_mode_{recycle_bin,my_wordpress,content_graph}_* hook keep their spelling. A retitle is not a re-slug, and plugins bind to those.

New: desktop_mode_site_title()

Single source for the site's name, with a matching desktop_mode_site_title filter (Experimental). It decodes the HTML entities get_bloginfo() hands back — titles land in title= attributes and JS-rendered text nodes, so leaving them encoded would render a literal Ben & Jerry on the desktop — and falls back to WordPress for a site with no name.

It feeds four surfaces in one hook: the folder window title, its pinned desktop icon, the window's breadcrumb root, and the "Open in <site>" actions in the media detail pane and the Corkboard's detail panel. The last two reach it through a new siteName key on their respective window configs.

Tests

  • tests/phpunit/tests/siteTitle.php — decode, trim, empty-site fallback, filter override, and the two junk-filter guards (non-string / empty string fall back to the real title rather than blanking every window).
  • tests/phpunit/tests/desktopObjectTitles.php — the shipped titles for all three windows plus their icons, and that the window ids did not move.
  • tests/phpunit/tests/myWordpress.php — the folder is titled after the site, and desktop_mode_site_title retitles window + icon + bundle config together.

Verification

  • npm run test:php — 1659 tests, 4257 assertions, green (3 pre-existing skips).
  • npm run test:js — 254 files, 2470 tests, green.
  • npm run typecheck, npm run lint, npm run build — all clean.
  • php -l on every changed PHP file.

Docs updated in the same change: hooks-reference.md (new filter, plus the Trash / Site folder / Corkboard section headings, with a note in each that the slugs are unchanged), javascript-reference.md, bridge-protocol.md, architecture.md, components-reference.md, desktop-themes.md, files-on-desktop.md, native-windows-proposal.md, three examples, and the readme.txt feature list. The #recycle-bin anchor links in examples/recycle-bin.md were repointed to #trash. Changelog entries in readme.txt are historical and left alone.

Not touched: the dashicons-networking icon on the Corkboard. Picking a new glyph is a design call beyond the rename — flagging it in case you want one.

🤖 Generated with Claude Code

https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s

Open WordPress Playground Preview

AllTerrainDeveloper and others added 2 commits July 29, 2026 11:02
Three built-in windows were named after the wrong thing, and the
names leaked the frame instead of naming what's inside it.

"My WordPress" — the "My" prefix is a 1995 Microsoft tic, and it
names the software rather than the thing. NeXT and Mac never labeled
the drive "My NeXTSTEP." It also breaks the fiction: the desktop
should contain objects, not a mention of the OS you're already
standing in. The pinned folder is now titled after the site itself —
whatever `get_bloginfo( 'name' )` returns.

"Recycle Bin" — Microsoft's word, and it fights WordPress's own
vocabulary, which is Trash. Recycling also implies the material comes
back as something else, which isn't what happens. Now: Trash. The
drag-to-bin ghost chip already said "Move to Trash", so the window
title now agrees with it.

"Content Graph" — data-structure jargon wearing an icon. Nobody's
desk has a Graph on it; it describes the schema, not the act. Now:
Corkboard.

Labels only. Module directories, window ids
(`desktop-mode-recycle-bin`, `desktop-mode-my-wordpress`,
`desktop-mode-content-graph`), REST routes, CSS classes, data
attributes, the `wp.desktop.myWordpress` JS API, and every
`desktop_mode_{recycle_bin,my_wordpress,content_graph}_*` hook keep
their spelling — a retitle is not a re-slug, and plugins bind to
those.

New `desktop_mode_site_title()` helper (+ `desktop_mode_site_title`
filter) is the single source for the site's name: it decodes the
entities `get_bloginfo()` returns, since titles land in `title=`
attributes and JS text nodes, and falls back to "WordPress" for a
site with no name. It feeds the folder window, its pinned icon, the
breadcrumb root, and the "Open in <site>" actions in the media detail
pane and the Corkboard panel — the last two get it via a new
`siteName` key on their window config.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s
`dashicons-networking` draws an org chart — boxes joined by
connector lines. That's the data structure, which is the same flaw
the "Content Graph" name had; renaming the window without changing
the glyph only fixed half of it.

A corkboard holds index cards, so that's the icon. The pushpin was
not available: `dashicons-admin-post` is the Posts icon, and a second
pin-shaped glyph would read as Posts in the dock. The card is the
other half of the same metaphor and reads as a sibling of Posts
rather than a competitor — honest, since the Corkboard is a view of
your posts.

`dashicons-index-card` was unused anywhere in the plugin, so there's
no collision in the dock, the taskbar, or the wallpaper grid. It also
frees `dashicons-networking` from an accidental clash with the
"Related" title-bar button (`src/related-entities/index.ts`), which
keeps it and means connectedness legitimately.

Grid-shaped alternatives were rejected: `grid-view` and
`screenoptions` are already taken and collapse into the same
checkerboard at 20px, and `layout` is UI jargon — the trap that made
"Graph" wrong in the first place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s
@AllTerrainDeveloper

Copy link
Copy Markdown
Collaborator Author

Icon swapped: dashicons-networkingdashicons-index-card (bdc3b9b).

The pushpin wasn't available — dashicons-admin-post is the Posts icon, and a second pin-shaped glyph would just read as Posts in the dock. So the Corkboard takes the other half of the metaphor: the card that gets pinned to it. Reads as a sibling of Posts rather than a competitor, which is honest — the Corkboard is a view of your posts.

The old glyph had the same flaw the old name did: dashicons-networking is an org chart, boxes joined by connector lines. That draws the data structure. Renaming the window but keeping the diagram would only have fixed half of it.

Two side benefits:

  • dashicons-index-card was unused anywhere in the plugin — no collision in the dock, the taskbar, or the wallpaper grid.
  • It frees dashicons-networking from an accidental clash with the Related title-bar button (src/related-entities/index.ts), which keeps it and legitimately means connectedness.

Grid-shaped alternatives were rejected: grid-view and screenoptions are already taken and collapse into the same checkerboard at 20px, and layout is UI jargon — the trap that made "Graph" wrong to begin with.

Covered by a new assertion in desktopObjectTitles.php that pins the icon on both the window and the desktop icon, and asserts it hasn't drifted onto Posts' pushpin. Suite green; npm run build clean.

Replaces the full-colour cork board with a monochrome one: an
outlined board, two tilted notes, and a thread arcing between two pin
heads. The thread is the window's subject — the links between pieces
of content — and it is what stops the icon reading as a generic
"documents" glyph. It arcs through the empty top half rather than
running between the notes, where a 5px gap would swallow it.

Monochrome needed a colour source. An SVG data URI is painted as a
CSS `background-image`, and a background image has no colour to
inherit — art drawn in `currentColor` would come out black, invisible
on the dark dock. A fixed white would invert the problem and vanish
on a light wallpaper or title bar, with no way for a theme to fix it.

So `renderIcon()` learns one branch: an SVG whose markup names
`currentColor` is painted as a CSS mask filled with `currentColor`
instead. Only the alpha survives and the fill comes from whatever the
surface is already using for text, so one drawing stays legible on
the dark dock, on a light title bar, on hover, and under a theme that
recolours the slot.

The art declares its own intent. No registration flag, no payload
key, no plumbing: `renderIcon` is the single canonical dispatcher and
all five call sites (desktop icons, `<wpd-tile>`, OS Settings, window
title bar, window chrome) already route through it. The declaration
cannot drift out of sync with the drawing because it IS the drawing.

This is the mechanism `applyIconMask` was written for — its docblock
already describes `currentColor` as the interesting tint value, and
notes that monochrome art is "invisible on a dark dock as an image
and perfect as a mask". Until now only a desktop theme could reach
it.

Fixed-colour art is untouched: no `currentColor`, no mask, same
background-image path as before. The Games icons render identically.
Existing plugin SVGs containing `currentColor` render black or
invisible today, so the new branch strictly improves them.

Decoding is memoized — icons re-render on every dock and wallpaper
repaint, and the answer per URI never changes — and the memo is
bounded at 256 entries so a long tail of plugin icons can't grow it
without limit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s
@AllTerrainDeveloper

Copy link
Copy Markdown
Collaborator Author

Corkboard icon is now a monochrome silhouette (a14a38d) — outlined board, two tilted notes, a thread arcing between two pin heads.

The thread earns its place

It's the window's actual subject — the links between pieces of content. Without it the icon says "pinboard"; with it, "connections". It arcs through the empty top half rather than running between the notes, where the 5px gap would have swallowed it at dock size.

Monochrome needed a colour source

An SVG data URI is painted as a CSS background-image, and a background image has no colour to inherit — art drawn in currentColor comes out black, invisible on the dark dock. A hardcoded white inverts the problem: it vanishes on a light wallpaper or title bar, with no way for a theme to fix it.

So renderIcon() learns one branch: an SVG whose markup names currentColor is painted as a CSS mask filled with currentColor. Only the alpha survives; the fill comes from whatever the surface is already using for text. One drawing, legible on the dark dock, a light title bar, a hover state, and under a theme that recolours the slot.

This is the mechanism applyIconMask was written for — its own docblock already calls currentColor "the interesting tint value" and notes that monochrome art is "invisible on a dark dock as an image and perfect as a mask." Until now only a desktop theme could reach it.

Why this stayed small

The art declares its own intent. No registration flag, no payload key, no plumbing — renderIcon is the single canonical dispatcher and all five call sites (desktop icons, <wpd-tile>, OS Settings, window title bar, window chrome) already route through it. The declaration can't drift out of sync with the drawing, because it is the drawing.

Compatibility

  • Fixed-colour art is untouched — no currentColor, no mask, same background-image path. The Games icons render identically (asserted in the new test).
  • Existing plugin SVGs containing currentColor render black or invisible today, so the new branch strictly improves them.
  • An explicit desktop-theme icon colour still wins over currentColor; branch order is unchanged.
  • Decoding is memoized (icons re-render on every dock/wallpaper repaint) and bounded at 256 entries.

Tests & docs

  • tests/vitest/icon-silhouette.test.ts — 6 tests: mask applied with currentColor, background-image cleared underneath, contain/no-repeat sizing parity, fixed-colour art keeps its path, memo stability, and both malformed-base64 degradation paths (charset-reject → letter badge; atob throw → background-image).
  • desktopObjectTitles.php — asserts the art contains no literal fill="#…" / stroke="#…". That's load-bearing, not cosmetic: a stray literal colour still contributes only its alpha through the mask, so mixed art is a bug that looks like a design choice.
  • javascript-reference.mdrenderIcon's shape table (five → six shapes) plus a new Silhouette icons section with the all-of-it-or-none-of-it rule; examples/register-icon.md points at it.

Full suite: PHPUnit 1663/4265 green, Vitest 2476 green, typecheck + lint + build clean.

@AllTerrainDeveloper
AllTerrainDeveloper merged commit 16d3ce0 into trunk Jul 29, 2026
5 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the rename-desktop-object-labels branch July 29, 2026 10:41
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