perf(markers): a marker's shadow no longer animates

The shadow of a device marker is sized from the marker, and the marker is
sized from the container: --device-shell-shadow is expressed in
--dev-size, which resolves to 2.5cqw. With box-shadow in the transition
list, every container-query re-evaluation — a tooltip, a scrollbar, a
rotation — produced a new computed value and restarted a 150 ms
non-composited transition on every marker at once.

The owner's Firefox profile shows what that costs: 244 box-shadow
transitions, all on span.device-shell-frame, all oncompositor:false, in
bursts of exactly 61 (the markers on screen), four bursts in two
seconds. During them the tab presented 103 frames in 11 seconds — 9.4
per second, CONTENT_FRAME_TIME median 149 ms and up to 320 — while the
refresh driver waited for paint 381 times. Our JavaScript in the worst
three seconds: 16 ms. Chromium starts the same transitions (measured:
one pixel of container width starts two per marker in both engines) and
merely pays less for them, which is why this hid there.

The shadow itself is unchanged; it simply applies at once. The core
keeps the same treatment, so the selection and focus rings appear
without a fade — an instant ring is ordinary feedback, a faded one costs
a full-frame repaint per marker. Hover still animates border-color.

Issue: #524
User-Visible: yes
This commit is contained in:
Codex
2026-09-11 08:28:49 +03:00
parent f4625dd4fb
commit 6b64801603
48 changed files with 586 additions and 410 deletions
+12
View File
@@ -3611,6 +3611,18 @@ const MUTANT_DEFINITIONS = [
replace: " if (ledger.caught[mutant.id] === fingerprint || mutant.id in ledger.caught) skipped.push(mutant);",
}],
},
{
id: 'marker-shadow-animates-again',
guard: 'node demo/smoke_marker_shadow_transitions.mjs',
because: '#524: тень маркера выражена в контейнерных единицах — с переходом любой пересчёт '
+ 'контейнерных запросов запускает некомпозируемый переход на каждом маркере; в профиле '
+ 'владельца 61 штука разом дала 9,4 к/с и кадры по 149 мс',
patches: [{
file: 'src/styles/devices.styles.ts',
find: ' transition: border-color .15s, opacity' + ' .2s;',
replace: ' transition: border-color .15s, box-shadow .15s, opacity .2s;',
}],
},
{
id: 'anchor-region-narrows-ambiguous-anchor',
guard: 'node --test --test-name-pattern="#518 AC4" test/mutation-gate.test.mjs',