Desktop Material

The dim sum surprise

Roughly one launch in ten, Desktop Material puts a small photograph of a Hong Kong dim sum dish in the bottom-left corner, names it in English and Traditional Chinese, and takes it away again after about nine seconds.

That is the whole feature. It is a delight, not a system: there is nothing to configure, nothing to acknowledge, and nothing it can stop you doing.

Behavior

Aspect Behavior
Chance DimSumSurpriseProbability = 0.1, drawn fresh on every launch
Draws per launch Exactly one, whether it hits or misses
Duration DimSumSurpriseDurationMs = 9000, then it clears itself
Position Bottom-left, fixed; the error notice stack owns bottom-right
Focus Never taken. role="status", aria-live="polite", no tab stop
Blocking Never. It is not a dialog and it is not in the top layer
Dismissal Self-clearing; a labelled close button only saves you the wait
Off switch None. See No opt-out below

When it stays away

The launch's state is checked before the probability is consulted. A suppressed launch simply shows nothing, and is not retried later: the check runs once, at startup, so closing a dialog can never be ambushed by a surprise that was waiting for it. In priority order:

Reason Meaning
error Startup failed, or an error notice is on screen
first-run The welcome flow owns the window
update An update is being checked for, downloaded, or is ready
modal A blocking dialog has the user mid-decision
quiet-hours The user's configured quiet-hours window is open
already-drawn This launch has spent its single draw
no-dishes No bundled dish survived verification

The most serious applicable reason is the one reported, so a user whose app just failed to start is told error, never quiet-hours.

The draw runs at the very end of performDeferredLaunchActions in app/src/ui/app.tsx — on an idle callback, well after the shell is committed and the window is interactive. It cannot delay startup, and the whole thing is wrapped: a failure costs you a picture of a dumpling and nothing else.

No opt-out

There is no setting that turns the surprise off, and the shared instructions are explicit that there must not be. Three things follow:

The pictures

Every picture is a real photograph copied byte for byte out of the shared dim sum catalog. Nothing is generated, downloaded, resized, or re-encoded at any point, and nothing is fetched at runtime — the card builds a file:// URL into the app's own bundled directory.

Aspect Detail
Location app/static/dim-sum/, copied to out/static/dim-sum by the build
Count 12 dishes, about 27 MiB
Format Lossless PNG, at least 1024×1024, exactly as the catalog holds them
Manifest manifest.json — names, alt text, byte length, dimensions, SHA-256

Twelve rather than the whole catalog because each picture is a multi-megabyte lossless PNG that the installer pays for. The twelve cover steamed, baked, fried, rolled, bakery, dessert and drink, so the draw stays varied without turning a small delight into a download.

Regenerating them

yarn generate-dim-sum-assets [catalogDirectory]

The catalog directory defaults to $DIM_SUM_CATALOG_DIR, then to an agent-global-memory/dim-sum checkout inside the current user's GitHub folder. The script verifies that each file is a real PNG with a well-formed IHDR and a terminating IEND chunk before copying it, records its SHA-256, and removes any picture a previous run left behind. A dish whose picture is missing or undecodable is reported and skipped, never replaced by a substitute.

This is a maintenance tool, not a build step. The pictures and the manifest are committed, so a build, a test run, and CI never need the catalog present.

Language and tone

The dish's name is a fact, not voice. It reads identically in all three language modes and at all five playfulness levels; only the order changes.

Mode Rendered name
English Classic Har Gow · 蝦餃
Bilingual Classic Har Gow · 蝦餃
Cantonese 蝦餃 · Classic Har Gow

The copy around the name is banded (dimSum.title.*, dimSum.lead.*) and follows each language's own funny level, so English can read plainly while Cantonese reads playfully. Every band states the same two facts: the odds (one launch in ten) and that the card clears itself. No band promises a way to switch it off, because there is not one.

Accessibility

Security and privacy

Failure modes

Failure Result
Manifest missing or malformed Zero dishes, no-dishes, no card
One dish entry corrupt That dish is dropped; the rest still draw
Duplicate id or filename The later copy is dropped, so no dish is twice as likely
Picture missing on disk A broken image is possible only if the asset test was skipped; the test hashes every file on every run
localStorage unreadable Migration is skipped; the surprise still shows
No CSPRNG reachable The draw throws, is caught, and the launch shows nothing
Any unexpected error Caught and logged at debug; startup is untouched

Verification

Suite Covers
app/test/unit/dim-sum-surprise-test.ts The 10% band, malformed draws, uniformity over 200k CSPRNG draws, dish selection, every suppression reason, opt-out migration, bilingual naming and alt text
app/test/unit/dim-sum-copy-test.ts All 15 mode × level combinations: the odds survive every band, no band promises an off switch, the name and alt text never change with voice
app/test/unit/dim-sum-assets-test.ts Every bundled PNG exists, decodes, and hashes to the value the manifest recorded; the directory holds nothing else
app/test/unit/dim-sum-wiring-test.ts Drawn from deferred startup, one draw per launch, every suppression path checked, no settings surface offers a toggle, reduced-motion and forced-colors honoured
app/test/unit/ui/dim-sum-surprise-test.tsx The rendered card: polite roles, no tab stop, both names at every level, file:// source, labelled dismiss

Suggested articles